Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/guide/07-overnight.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Walk through what each line buys you:
- "fresh worktree off `<base>`" keeps the run from colliding with anything else you have open.
- "don't ask me before committing" pre-answers the permission the agent would otherwise block on.
- A Harness loop or background job is the wake mechanism. The [Autonomous run playbook](../../skills/meta-mode/playbooks/autonomous-run.md) uses the active Harness's native mechanism when it has one, or a persistent local process with a saved log as its fallback.
- On a host with its own scheduler, the schedule can live there instead of in a session loop. In T3 Code the agent uses `schedule_task`, which runs even when no turn is active and posts each run back into the same thread. The prompt must be self-contained and carry the finish condition, because the run sees nothing else. Pause it with `update_scheduled_task` and `enabled: false`, and delete it when the finish condition holds. The [T3 Code page](../t3code.md#orchestration-overlap) lists what else changes there.
- The escape hatch lets it stop at a genuine dead end and write up why, which beats eight hours of creative goal reinterpretation.

Because you'll review this work after stepping away, `/meta-mode` routes it through [`/figure-it-out`](../../skills/figure-it-out/SKILL.md), which designs the run's phases before any code and wires in the decision log.
Expand Down
22 changes: 13 additions & 9 deletions docs/t3code.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,24 +109,28 @@ T3 reads `t3.json` at the repository root. An invalid file is ignored as a whole

## Orchestration overlap

When a provider session has the app's `t3-code` MCP server, T3 adds its own instructions to the first prompt or system prompt. They cover delegation (`orchestrator_capabilities`, `delegate_task`, `task_status`, `task_cancel`), launching threads (`t3_thread_launch`, `create_threads`), scheduling (`schedule_task`), and pull requests (`link_pull_request`, `watch_pull_request`, `unwatch_pull_request`). Two mstack features do the same job outside T3's view.
When a provider session has the app's `t3-code` MCP server, T3 adds its own instructions to the first prompt or system prompt. They cover delegation (`orchestrator_capabilities`, `delegate_task`, `task_status`, `task_cancel`), launching threads (`t3_thread_launch`, `create_threads`), scheduling (`schedule_task`), and pull requests (`link_pull_request`, `watch_pull_request`, `unwatch_pull_request`). Without a binding, three mstack features would do the same jobs outside T3's view: `run-role` children, the `watch-pr` watcher under `/loop`, and transcript-file history.

**Child agents.** `run-role` starts a provider CLI with `execFile` or `spawnSync`. T3 does not know about that process, so it has no entry in T3's agent views, `task_status` cannot see it, and T3's docs say Stop also stops the subagents T3 delegated, which does not cover processes an agent started itself. I did not check whether interrupting a turn also kills a `run-role` child that is still running. Inside T3:
**How mstack binds to T3.** The skills stay portable and name capabilities. Where a playbook delegates, watches a pull request, schedules a wake, reads history, or collects browser evidence, it tells an agent on a host with native primitives to read that host's reference first. For T3 these are `references/hosts/t3code.md` in `meta-mode`, `recall`, and `create-verification-skill`. Each maps the capability to the T3 tool and lists the limits and the rules that do not change. The agent applies a reference only when the `t3-code` tools are present in the session, probing `orchestrator_capabilities` once if they are not listed, and otherwise follows the generic text unchanged. `scripts/validate.mjs` fails when a T3 tool name appears anywhere under `skills/` outside a `references/hosts/` directory. The references were checked against the T3 source at the commit named above, not against a running T3.

- Prefer the provider's native subagent tools for same-provider work they can run with the chosen model, and `delegate_task` for cross-provider work you want T3 to track. T3's own instructions say the same.
- Take provider instance and model names from `orchestrator_capabilities`. T3 lists its own catalog, which can differ from the names in `~/.config/mstack/models.json`.
- Use `run-role` when the `t3-code` tools are not available in the session, or for a harness T3 does not run. Expect its output in the transcript only.
**Child agents.** `run-role` starts a provider CLI with `execFile` or `spawnSync`. T3 does not know about that process, so it has no entry in T3's agent views, `task_status` cannot see it, and T3's docs say Stop also stops the subagents T3 delegated, which does not cover processes an agent started itself. I did not check whether interrupting a turn also kills a `run-role` child that is still running. Inside T3 the `meta-mode` reference sends delegation through T3 instead:

**Pull request watching.** The `babysit` playbook runs `bun "<meta-mode-tools>/watch-pr/watch-pr"` under `/loop`. T3's `watch_pull_request` polls the pull request every two minutes and wakes the agent when a check fails, required checks pass, someone else comments, or the branch conflicts. Running both gives two wake sources for one PR.
- Prefer the provider's native subagent tools for same-provider work they can run with the chosen model, and `delegate_task` for models they lack or cross-provider work you want T3 to track. T3's own instructions say the same.
- Take provider instance and model names from `orchestrator_capabilities`, and pass them in `delegate_task`'s `target`. T3 lists its own catalog, which can differ from the names in `~/.config/mstack/models.json`.
- Every round is a new `delegate_task` call with the full brief and its own `clientRequestId`. A child cannot run with broader permissions than its parent.
- `run-role` remains the path when the `t3-code` tools are not available in the session, or for a harness T3 does not run. Expect its output in the transcript only.

- When `watch_pull_request` is available, use it instead of the Bun watcher loop and end the turn; T3 wakes the agent. Handle existing comments first, because only comments posted after the call wake it.
**Pull request watching.** The `babysit` playbook otherwise runs `bun "<meta-mode-tools>/watch-pr/watch-pr"` under `/loop`. T3's `watch_pull_request` polls the pull request every two minutes and wakes the agent when a check fails, required checks pass, someone else comments, or the branch conflicts. Running both would give two wake sources for one PR, so the reference replaces the watcher and loop and keeps every stop condition.

- The agent arms `watch_pull_request` and ends the turn; T3 wakes it. It handles existing comments first, because only comments posted after the call wake it.
- A wake is news and not a merge decision. The mstack rule stays: do not merge or arm auto-merge unless the user asked.
- T3's watch ends when the PR merges or closes, after 8 failed reads in a row, after 10 wakes that bring only comments, or when the user presses Stop. Call `unwatch_pull_request` before handing the work back.
- T3's watch ends when the PR merges or closes, after 8 failed reads in a row, after 10 wakes that bring only comments, or when the user presses Stop. A merge ends it silently (a close does wake the agent), so a turn ended on a green wake is never woken by the merge. While `shipping` or an owner waits for an armed merge, the reference adds a `schedule_task` confirmation wake titled `mstack merge-confirm <owner>/<repo>#<n>`. T3 scheduled tasks have no expiry, and nothing cleans up after a Stop or crash, so the task's prompt carries a 6-hour deadline and a run counter and deletes itself when the PR merges or closes or either bound passes. Later Shipping, Babysit, and session-pickup runs sweep leftover tasks with that title prefix, and the shipping reply names the task and how to delete it. Without `schedule_task` the agent keeps the portable watcher. The agent calls `unwatch_pull_request` before handing the work back.
- A delegated child cannot watch a pull request, because its parent owns it. An owner agent that T3 delegated therefore keeps the portable watcher or reports back to its parent.
- `watch-pr --status-only` is still a fine one-shot status read. T3 reports its own wake events, not the watcher's `READY`, `WAITING`, `ADVANCE`, or `COMPLETE` verdicts, so where `babysit` names a verdict, follow the T3 wake message instead.

T3 also tells the agent to call `link_pull_request` for every PR it creates. That works alongside `file-pr`; the link is how T3 shows PR status on the thread.

For long unattended work, the `autonomous-run` playbook picks "the wake mechanism exposed by the active harness". In T3 that can be `schedule_task`, which keeps the schedule in T3's scheduler.
**Scheduling, history, and evidence.** For long unattended work, the `autonomous-run`, `autopilot-full`, and `multi-phase-plan` playbooks pick "the wake mechanism exposed by the active harness". In T3 that is `schedule_task`, which keeps the schedule in T3's scheduler; see [Run work while you sleep](./guide/07-overnight.md). `recall` and `session-pickup` can search and read T3 threads with `t3_thread_search` and `t3_thread_read`. These cover T3's own thread store, not provider transcript files, so the bundled history helper is still needed for threads run outside T3. `create-verification-skill` can use the `preview_*` browser tools and the `device_*` simulator tools as drivers and evidence sources.

## T3's own safety rules

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"install-skills": "node scripts/install.mjs",
"optimize-context": "node scripts/optimize-context.mjs",
"reconcile-context": "node scripts/reconcile-context.mjs",
"test": "node scripts/validate.mjs && node scripts/skill-baseline.mjs --check && node --test scripts/install.test.mjs scripts/install-migration.test.mjs scripts/migration-integration.test.mjs scripts/skill-discovery.test.mjs scripts/harness-targets.test.mjs scripts/remote-discovery.test.mjs scripts/context.test.mjs scripts/model-config.test.mjs scripts/model-budget.test.mjs scripts/audit-context.test.mjs scripts/worktree-audit.test.mjs tools/meta-mode/check-plan.test.mjs scripts/sync-upstream.test.mjs scripts/runtime.test.mjs scripts/environment.test.mjs scripts/skill-integrity.test.mjs scripts/skill-baseline.test.mjs scripts/version-integrity.test.mjs scripts/agent-format.test.mjs scripts/history.test.mjs scripts/harness-policy.test.mjs scripts/harness-project.test.mjs scripts/check-upstream-adaptations.test.mjs scripts/check-playbooks.test.mjs scripts/pack-claude-skills.test.mjs scripts/session-hook.test.mjs scripts/skill-compat.test.mjs"
"test": "node scripts/validate.mjs && node scripts/skill-baseline.mjs --check && node --test scripts/install.test.mjs scripts/install-migration.test.mjs scripts/migration-integration.test.mjs scripts/skill-discovery.test.mjs scripts/harness-targets.test.mjs scripts/remote-discovery.test.mjs scripts/context.test.mjs scripts/model-config.test.mjs scripts/model-budget.test.mjs scripts/audit-context.test.mjs scripts/worktree-audit.test.mjs tools/meta-mode/check-plan.test.mjs scripts/sync-upstream.test.mjs scripts/runtime.test.mjs scripts/environment.test.mjs scripts/skill-integrity.test.mjs scripts/skill-baseline.test.mjs scripts/version-integrity.test.mjs scripts/agent-format.test.mjs scripts/history.test.mjs scripts/harness-policy.test.mjs scripts/harness-project.test.mjs scripts/check-upstream-adaptations.test.mjs scripts/check-playbooks.test.mjs scripts/pack-claude-skills.test.mjs scripts/session-hook.test.mjs scripts/skill-compat.test.mjs scripts/host-binding.test.mjs"
},
"bin": {
"mstack": "scripts/install.mjs",
Expand Down
37 changes: 26 additions & 11 deletions profiles/skill-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@
"skills/create-verification-skill/references/harness-paths.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "62705c0e0ae6832c20c1f1b53bb91b05c036dd6879f789de6bc4499815c99ab4"
"targetDigest": "c61e7975c210bef5424c67ec28e68774437ec24ea0d73ed007485db35d4a850b"
},
"skills/create-verification-skill/references/hosts/t3code.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "6c044eb60006fa393d5ef9264a9bca7a95bd7cf6ff6217e2dedb8b02483ab7c7"
},
"skills/create-verification-skill/SKILL.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -212,13 +217,13 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/autonomous-run.md",
"sourceDigest": "15e54ad3ac92565613980772d8708de6e19cc4690bfd4bb3fb8836522407377b",
"targetDigest": "ccfacb171d67c4a2b2ec8aec87c78ecba00234ccd99a15e4fe088f43413b1e60"
"targetDigest": "280bc69056d1e4c5c5df85821e191719483e1f5475b445eaae205dc242882d0e"
},
"skills/meta-mode/playbooks/autopilot-full.md": {
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/autopilot-full.md",
"sourceDigest": "05ca30a16242c19d0c78ba1e88cca66f858d75252cb154fd740099fe292de802",
"targetDigest": "d7ef34b2d3bd55294d237fc71325f1c1d878337fd2c418e63d98c41f6d57e497"
"targetDigest": "84f3c21ea3af7f3d7b30d800e067e552f0e5db047c7553229a7b2fb5559dfdab"
},
"skills/meta-mode/playbooks/autopilot-stack.md": {
"upstream": "pstack",
Expand All @@ -230,7 +235,7 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/babysit.md",
"sourceDigest": "a0346c37c2313f36a863b80f66ee7b98059c2242adf74fc7b3e48abdb9ec6f5a",
"targetDigest": "d52fed9c782e79df75e2e0f4f6344bc764e7aded1e5b8ac880ffdcc69dc9768f"
"targetDigest": "679067250cf57da21cdc8b0bd3215b1149ec9a1e72ffe92955c3dd34a0d1c8e7"
},
"skills/meta-mode/playbooks/bug-fix.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -266,7 +271,7 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/multi-phase-plan.md",
"sourceDigest": "27d310e3fc3937a60b8fcbe1318f9d249a7477a722907bf85b3e4eb3dc436b11",
"targetDigest": "2eb71a5ddd294add838ca5d4bde67c431a925a6c6f3cfe686228b2fbc3b03cf9"
"targetDigest": "bef154d16534d0af83f5742285b3d354f2aa337ff50bca7e3e169343edcab002"
},
"skills/meta-mode/playbooks/opening-a-pr.md": {
"upstream": "pstack",
Expand All @@ -278,7 +283,7 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/orchestrate.md",
"sourceDigest": "d42b4375f1bd4ce23da0b575a198571a2117df7eea10c3c9fc6d92ae1053f7be",
"targetDigest": "01d014c9693e4214ef56ab95f0bbc864a47efddcdcb53eda629319cb63766c3f"
"targetDigest": "9e898ebeb4225b6b819d93c5b198d9c4bf84e8a5fd9b5d60977854237f5d296e"
},
"skills/meta-mode/playbooks/pause-safely.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -314,13 +319,13 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/session-pickup.md",
"sourceDigest": "1604fb463f7c7410d43fa024ca76c1c1824c166a01fd69d61f073d06fdca2a47",
"targetDigest": "5bbf52a3e43524aca7f474962a9e9a6a25d8cd2cc96569dcddccd5bf35466ac8"
"targetDigest": "e141647ec8951307806f0c5d25f6f540171770e81851bc0bebf0aed2540ee8b8"
},
"skills/meta-mode/playbooks/shipping.md": {
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/shipping.md",
"sourceDigest": "19f3f6803a7bbe9ff04f624b03e3b55f07ac0a05e991aa00d5fe51239b920b2a",
"targetDigest": "d898c5b32402a3e22a213311d33527423c57cb81b050c8e1e36d42cd2d85a24c"
"targetDigest": "bd144d61ab82bb3cf4b0a2c9bc0310e8fdfa98e74baccce3528d5141895c5796"
},
"skills/meta-mode/playbooks/trace-forensics.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -354,13 +359,18 @@
"skills/meta-mode/references/capability-matrix.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "2b57fe4aef9b300ea5b5e5a8ae93c1a5dbc266d6b9e47bd1ba26c84f1f7f7d39"
"targetDigest": "0e24ed2b7de416a39640a1f71a20196ad1bf56c8f131a091ddff1bee720d8830"
},
"skills/meta-mode/references/hosts/t3code.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "4ba5740a7b1a890f404252af59eeb00c645a4f1310b85266ade7f15d4a4d4ef3"
},
"skills/meta-mode/SKILL.md": {
"upstream": "pstack",
"source": "skills/poteto-mode/SKILL.md",
"sourceDigest": "404c0ef4a78e93451b2ab555ca532e7197b5cf87de29205b6f7109dbee5d9c4d",
"targetDigest": "08d339fcc5315f9e24bf2f810d3b3505bd98efb6930e30a2a4d4769575197024"
"targetDigest": "1bd904d7163d624d390c09e7bd1079bb5dcf3435828ee72fa34882e06f347c52"
},
"skills/no-comments/SKILL.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -515,7 +525,12 @@
"skills/recall/references/history-sources.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "22f657e947e100c6c1e65877029579eaf21638321e6d580246a5ea6c4492087b"
"targetDigest": "181e7a56f8ef5514a1cae4841366bf62c708fd44be8bcee3c129c50182e0b3bc"
},
"skills/recall/references/hosts/t3code.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "117b8254d1ecff93fbd04d317f5dcc3e2ec239d0083173462766ddc29fd7afda"
},
"skills/recall/scripts/history.mjs": {
"upstream": null,
Expand Down
7 changes: 6 additions & 1 deletion profiles/upstream-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
"meta-mode": {
"source": "2e09a945cbe289dd85448f4a51eeac8c0c3893904decaab9413a33babf96ca08",
"target": "08d339fcc5315f9e24bf2f810d3b3505bd98efb6930e30a2a4d4769575197024"
"target": "1bd904d7163d624d390c09e7bd1079bb5dcf3435828ee72fa34882e06f347c52"
},
"no-comments": {
"source": "5c5b0882297d704c3a9720c52b7a793c68b013eaf717989f0945624efdfe2b05",
Expand Down Expand Up @@ -264,6 +264,11 @@
"target": "5fd91e770e7805455668b44d4f39f767498dc5ff6d4f10a9cfbe9de9d0631ac5",
"reason": "Document one canonical verification contract and the mixed pstack/mstack project workflow."
},
"docs/guide/07-overnight.md": {
"source": "b66d8726a888fa8ed2f1b488fc1ca14ac67eab892ff655878bd09bacdcdefabc",
"target": "b7e45bde8b8e383ca2eeaf97296da9d409a7b13214c26a9f815ff83f4ed1a67e",
"reason": "Offer a host scheduler as an alternative to a session loop for unattended runs."
},
"docs/guide/README.md": {
"source": "4b0d617c745e1ff33274bea1c1bc1274f3e23514455bec97affc9e9951f2350b",
"target": "234cc31995332fdc898f1814d611b7cbcd6b2c1915e793dbb75883dd31b8c030",
Expand Down
34 changes: 34 additions & 0 deletions scripts/host-binding-lib.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Host-native tool names belong in one dedicated reference per host. The portable
// workflow text may point at that reference but must not name the tools.
const HOST_TOOL_PATTERNS = [
[
"T3 Code orchestration tool",
/\b(?:orchestrator_capabilities|delegate_task|task_status|task_cancel|create_threads|request_secret|schedule_task|run_scheduled_task_now|list_scheduled_tasks|(?:update|delete)_scheduled_task|(?:link|unlink|unwatch|watch)_pull_request|list_thread_pull_requests|html_(?:preview|render))\b/,
],
["T3 Code thread tool", /\bt3_[a-z]+(?:_[a-z]+)+\b/],
["T3 Code preview tool", /\bpreview_[a-z]+(?:_[a-z]+)*\b/],
["T3 Code device tool", /\bdevice_[a-z]+(?:_[a-z]+)*\b/],
["T3 Code MCP server name", /\bt3-code\b|\bmcp__t3_code__/],
];

const HOST_REFERENCE_PATH = /^skills\/[^/]+\/references\/hosts\/[^/]+$/;

export function isHostReference(relativePath) {
return HOST_REFERENCE_PATH.test(relativePath.replaceAll("\\", "/"));
}

export function hostBindingProblems(relativePath, content) {
if (isHostReference(relativePath)) return [];
const problems = [];
for (const [label, pattern] of HOST_TOOL_PATTERNS) {
const match = content.match(pattern);
if (match) {
problems.push(
`${relativePath} names the ${label} \`${match[0]}\` outside skills/*/references/hosts/`,
);
}
}
return problems;
}

export const hostToolPatterns = HOST_TOOL_PATTERNS.map(([, pattern]) => pattern);
Loading
Loading