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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ The available installable artifacts are:
| `agents` | Codex: `$CODEX_HOME/agents/` as TOML; other harnesses: their native `agents/` directory as Markdown |
| `meta-mode-tools` | `tools/meta-mode/` beside the resolved skill root; shared consumers use `~/.agents/tools/meta-mode/` |
| `guide` | `docs/guide/` beside the resolved skill root |
| `session-context` | `session-context/` beside the resolved skill root; plain-text routing guidance, never implicit |

Codex skills default to `~/.agents/skills/`, while Codex agents default to
`~/.codex/agents/`. An unset or empty `CODEX_HOME` uses `~/.codex`.
Expand Down Expand Up @@ -155,7 +156,11 @@ reviewed and copied into a project repository's committed
`.cursor/automations/benny/` directory using its own setup instructions.
mstack does not ship portable `commands/`, `hooks/`, or `settings/` trees:
those are harness- and project-owned configuration surfaces and must be
written or merged explicitly by the user.
written or merged explicitly by the user. The optional `session-context`
artifact is plain-text guidance only; select it with `--artifact session-context`
and configure the harness's own session surface explicitly. It does not register
a startup hook, grant permissions, or make session routing implicit. Hooks remain
unsupported unless explicitly configured outside mstack.

## Choose installation directories

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/03-understand.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ When another agent (or you, last week) left a branch mid-flight:
/meta-mode take over this branch. read the decision log, figure out what's done, and continue from there. don't redo finished work.
```

The [Session pickup playbook](../../skills/meta-mode/playbooks/session-pickup.md) treats the prior trail as authoritative. It reconstructs the branch state and decisions, names the resume point, and verifies inherited claims against the original goal instead of re-deriving everything from scratch.
The [Session pickup playbook](../../skills/meta-mode/playbooks/session-pickup.md) treats the prior trail as authoritative. It first reads the latest project-local checkpoint with `node "<meta-mode-tools>/resume.mjs" read --project .`, follows its note and evidence paths, reconstructs the branch state and decisions, names the resume point, and verifies inherited claims against the original goal instead of re-deriving everything from scratch. Checkpoints live under Git metadata, so this workflow does not depend on a particular Harness or vendor path.

**Pitfall:** don't skip this page's skills because "the agent will read the code anyway." An agent that starts editing without a traced model tends to fix the symptom at the first plausible spot. `/how` first is cheaper than the second bug.

Expand Down
32 changes: 32 additions & 0 deletions docs/session-context/SESSION-CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Optional session context

This file is an explicit, user-selected routing artifact for sessions that should
start with mstack's `/meta-mode` workflow. Load or reference it from the active
harness configuration when you want that behavior; the mstack installer never
registers it as a hook, startup command, or implicit instruction.

## Opt-in contract

1. Select this artifact explicitly with `--artifact session-context`.
2. Configure the active harness to read this file using its documented,
user-owned session or project configuration surface.
3. Confirm the harness configuration and review the file before using it in a
sensitive repository.

When loaded, route the user's request through `/meta-mode` at session start.
Keep routing advisory: do not execute commands, modify files, install hooks, or
send data without the harness's normal approval and tool policy. If the file is
not explicitly selected and configured, do nothing.

## Security and portability boundary

This is plain text, not executable configuration. It does not grant tools,
permissions, network access, or persistence. Harnesses differ in whether they
support session context, startup instructions, or project configuration, so
mstack does not provide an adapter that silently wires this file into any of
them. A harness-specific integration must be configured and reviewed by the
user. Hooks remain unsupported unless explicitly configured outside mstack.

Do not put secrets, credentials, transcript contents, or machine-specific paths
in this file. Keep the canonical skill tree Harness-neutral; this artifact is a
separate optional boundary for users who choose session routing.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"model-budget": "node scripts/model-budget.mjs",
"check-upstream": "node scripts/check-upstream.mjs",
"check-playbooks": "node tools/meta-mode/check-playbooks.mjs",
"audit-worktrees": "node tools/meta-mode/worktree-audit.mjs",
"check-harness-policy": "node scripts/check-harness-policy.mjs",
"skill-baseline": "node scripts/skill-baseline.mjs",
"run-role": "node scripts/run-role.mjs",
Expand Down
5 changes: 5 additions & 0 deletions profiles/artifacts.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
"path": ["docs", "guide"],
"description": "The adapted mstack workflow guide and its images."
},
"session-context": {
"source": "docs/session-context",
"path": ["session-context"],
"description": "Optional plain-text session routing guidance; never installed implicitly or registered as a hook."
},
"benny": {
"source": "automations/benny",
"installable": false,
Expand Down
52 changes: 36 additions & 16 deletions profiles/skill-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,13 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/orchestrate.md",
"sourceDigest": "d42b4375f1bd4ce23da0b575a198571a2117df7eea10c3c9fc6d92ae1053f7be",
"targetDigest": "c25dcc2662e15ccb91ff19fbe1a156b7fb97d7d49d0c3478dcd9f001e643e398"
"targetDigest": "01d014c9693e4214ef56ab95f0bbc864a47efddcdcb53eda629319cb63766c3f"
},
"skills/meta-mode/playbooks/pause-safely.md": {
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/pause-safely.md",
"sourceDigest": "7d5fc10e144265f1b35f8157926541e738c1de64b6a85b3e61b51cf268c3dffd",
"targetDigest": "77968cfe5f4a71a8cd33e0ae8ffcdbd88dd693a212c240457773e6c40c96c21d"
"targetDigest": "50f1fa76fcdbf92db5a772a0470a128850c960c9eb68156846cc4f5a503f863b"
},
"skills/meta-mode/playbooks/perf-issue.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -302,13 +302,13 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/session-pickup.md",
"sourceDigest": "1604fb463f7c7410d43fa024ca76c1c1824c166a01fd69d61f073d06fdca2a47",
"targetDigest": "97a3d7b0fcecf53c5c3fce9ec17f105196745086911c363d2dc7841bc56e40e2"
"targetDigest": "5bbf52a3e43524aca7f474962a9e9a6a25d8cd2cc96569dcddccd5bf35466ac8"
},
"skills/meta-mode/playbooks/shipping.md": {
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/shipping.md",
"sourceDigest": "c301902136e0a9a0a55403c35374f6f5738e501aee66c27458dc197b87557550",
"targetDigest": "0102de98f44f1b9921352fe60dbd3789710985bed2a491fd033bf012a1a812b2"
"targetDigest": "d898c5b32402a3e22a213311d33527423c57cb81b050c8e1e36d42cd2d85a24c"
},
"skills/meta-mode/playbooks/trace-forensics.md": {
"upstream": "pstack",
Expand All @@ -326,7 +326,7 @@
"upstream": "pstack",
"source": "skills/poteto-mode/playbooks/worktree-cleanup.md",
"sourceDigest": "fc464dc4121926df1704f483c5feca83717c0a40b4651d3e11bd3aedd89441b6",
"targetDigest": "db0c8eeef5dc5054e79c1b3b8215159f48e12a4fb81225d551080f8773fe1b2c"
"targetDigest": "7a13c4a1e27e084f9bb9ce9f7c998d5584efeb3e4bfa15a6422f261f9db0bc77"
},
"skills/meta-mode/references/bugbot-triage.md": {
"upstream": "pstack",
Expand Down Expand Up @@ -721,27 +721,27 @@
"tools/meta-mode/check-playbooks.mjs": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "3a753d840c391cbf93979d6d474bc3965b387bc507de6925420ca78ff5db6aaf"
"targetDigest": "e962e30da22e1668b0036072b9f9f002664ac3fbc17c66a9161fd31163072282"
},
"tools/meta-mode/orch/orch.test.ts": {
"upstream": "pstack",
"source": "skills/poteto-mode/scripts/orch/orch.test.ts",
"sourceDigest": "174b86d21ff51ccd28d1a8c938cb2e0c6fa287b209d4ca6c03932fcb1b53372e",
"targetDigest": "913d5c03ba456de547ec609458a2b14c5a3894d33385b0597ee44315252f870b",
"targetDigest": "821c2cd328e441590bb236733ca48a6f889e13c7c49447c5a0c170ac999af5a5",
"reason": "Runtime tools are packaged separately from portable skill instructions."
},
"tools/meta-mode/orch/orch.ts": {
"upstream": "pstack",
"source": "skills/poteto-mode/scripts/orch/orch.ts",
"sourceDigest": "f091687df627a0b75fabd54af58945a9cd6c7039ef0622012ac9ed60cd8ec434",
"targetDigest": "f091687df627a0b75fabd54af58945a9cd6c7039ef0622012ac9ed60cd8ec434",
"targetDigest": "b820c51d3ed13fa62ef5fc969aacf2b0b3c7f471a518f6159d3c3a530a363cd7",
"reason": "Runtime tools are packaged separately from portable skill instructions."
},
"tools/meta-mode/orch/store.ts": {
"upstream": "pstack",
"source": "skills/poteto-mode/scripts/orch/store.ts",
"sourceDigest": "0eae7cf69282e827b1227166f2e32cee3560f2f3e65b3f1f2faf6fb83d3b4c5b",
"targetDigest": "39394893aa8191f411a5eee33a554a6232e4568ecf11d7b43f6a21752d4c97cd",
"targetDigest": "c879408105d96814345f9e15f9a909505fec1374036c01e58820a55374a194bb",
"reason": "Runtime tools are packaged separately from portable skill instructions."
},
"tools/meta-mode/package.json": {
Expand All @@ -751,10 +751,30 @@
"targetDigest": "c7ac7fd69bb925415cdc15cd636567304ee40f8d665986e45ed8c0ee658f6caf",
"reason": "Runtime tools are packaged separately from portable skill instructions."
},
"tools/meta-mode/pr-safety.mjs": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "1ce77cecdcb4be6c9622257f2e2efac790e47fbd35b1fd8dd93a4d7ef123f2cf"
},
"tools/meta-mode/pr-safety.test.mjs": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "46d00f3086850f82bf713d1fa91c60debde6623fe7bf3007a49eaafb42ddae3e"
},
"tools/meta-mode/README.md": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "5a2dcf51ad2a816941a116b0e4c9c4e113c9d2a721a15f5ac8ef7a4b1a9afeaf"
"targetDigest": "62e8431ec27bffa8ec911f6286ad183d16b6f451de34f53dd5ea63de5acd0088"
},
"tools/meta-mode/resume.mjs": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "2cdd3e939db59a68d847489c4eeec6a26674ec5bec2852c7e242959af5a5ff8c"
},
"tools/meta-mode/resume.test.mjs": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "6f1074ac94da0c4d1e9a6504acfac428ebc47a3f2656b260b374795d345abd63"
},
"tools/meta-mode/watch-pr/cli.test.ts": {
"upstream": "pstack",
Expand Down Expand Up @@ -840,17 +860,17 @@
"targetDigest": "d955603be6cc0e8b8ffcec722f635192b2261410b1f2929abea94480e47eb5d4",
"reason": "Runtime tools are packaged separately from portable skill instructions."
},
"tools/meta-mode/worktree-audit.mjs": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "ee7946ec0558ddeeb7466003d120124c6c884218f05d51e920c90d4fc010c20c"
},
"tools/meta-mode/worktree-audit.sh": {
"upstream": "pstack",
"source": "skills/poteto-mode/scripts/worktree-audit.sh",
"sourceDigest": "95b8530f3c0ccada8cabc4b0727c052fbc85c141531375aaace65c427af8aecc",
"targetDigest": "68df230b34f10558e021bb6cc9696e4653acc92645a17b35c6b953aa40837fc2",
"targetDigest": "6a87d48f5664868537d722e059d4a3807a1283cc0382ec01e7d5f764098dbdbf",
"reason": "Runtime tools are packaged separately from portable skill instructions."
},
"tools/meta-mode/worktree-audit.test.sh": {
"upstream": null,
"reason": "Local portability guidance or implementation; review alongside its owning skill.",
"targetDigest": "dfc8c11e867f5000a996e8b4aeafc630319964bb1b2946b1a626996dd4919e0f"
}
},
"omitted": {
Expand Down
5 changes: 5 additions & 0 deletions profiles/upstream-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@
"target": "b67fd0a7950464e1094225a2f85add0714849c1daab6c5289ad7bbc653baa536",
"reason": "Document one canonical verification contract and the mixed pstack/mstack project workflow."
},
"docs/guide/03-understand.md": {
"source": "5db58a1fc2cc7bf1843945fcc7d93eba4f73e26fde5cd097d006be641fe5883e",
"target": "1fd73edc1cdde214e82b4b116ba3b1d3ec1dcae18e1ef019de99ee12439c3cf1",
"reason": "Point session pickup at the portable project-local resume checkpoint."
},
"docs/guide/06-verify-and-ship.md": {
"source": "53a6bc8b3e850e34c4d8b1785a488eb7fbcbfe94ed588aeeaca252a5eb6e442c",
"target": "e99e7108a757eee96397ebb79c6bbbc6f30084a35eb32d98f8de2e2b9c1aad18",
Expand Down
34 changes: 33 additions & 1 deletion scripts/check-playbooks.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
import { checkPlaybooks } from "../tools/meta-mode/check-playbooks.mjs";
import { checkPlaybooks, checkPlaybooksDetailed } from "../tools/meta-mode/check-playbooks.mjs";

const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const script = join(repoRoot, "tools", "meta-mode", "check-playbooks.mjs");
Expand Down Expand Up @@ -107,3 +107,35 @@ test("leaves a repository without project playbooks valid", (t) => {
assert.deepEqual(checkPlaybooks(root, join(root, "missing-bundled")), []);
execFileSync(process.execPath, [script, "--root", root], { encoding: "utf8" });
});

test("classifies duplicate extends and anchors as warnings, with strict mode failing", (t) => {
const { root, bundledRoot } = fixture(t, {
"bug-fix.md": "---\nextends: bug-fix, bug-fix\nwhen: Use it for bugs.\n---\n- **In** \"Binary-search the cause.\": first.\n- **In** \"Binary-search the cause.\": second.\n",
}, { "bug-fix.md": "Binary-search the cause.\n" });
const detailed = checkPlaybooksDetailed(root, bundledRoot);
assert.deepEqual(detailed.errors, []);
assert.equal(detailed.warnings.length, 2);
assert.equal(checkPlaybooks(root, bundledRoot).length, 2);
const normal = run(root, bundledRoot);
assert.equal(normal.status, 0);
assert.match(normal.stderr, /warning:.*extends/);
const strict = run(root, bundledRoot, "--strict");
assert.equal(strict.status, 1);
const json = run(root, bundledRoot, "--json");
assert.equal(json.status, 0);
const output = JSON.parse(json.stdout);
assert.equal(output.ok, true);
assert.equal(output.errors.length, 0);
assert.equal(output.warnings.length, 2);
});

test("rejects an anchor found in more than one base playbook", (t) => {
const { root, bundledRoot } = fixture(t, {
"combined.md": "---\nextends: first, second\nwhen: Use it.\n---\n- **After** \"Shared step\": adjust.\n",
}, { "first.md": "Shared step\n", "second.md": "Shared step\n" });
const result = run(root, bundledRoot, "--json");
assert.equal(result.status, 1);
const output = JSON.parse(result.stdout);
assert.equal(output.errors[0].code, "ambiguous-anchor");
assert.match(output.errors[0].message, /ambiguous/);
});
29 changes: 29 additions & 0 deletions scripts/install.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,35 @@ test("rejects empty and whitespace-only environment targets", () => {
}
});

test("default installs do not add the opt-in session context artifact", () => {
const { root, env } = fixture();
try {
const result = run(["--harness", "codex"], env);
assert.equal(result.status, 0, result.stderr);
assert.equal(existsSync(join(env.HARNESS_SKILLS_CODEX_DIR, "session-context")), false);
assert.equal(existsSync(join(root, "codex skills", "..", "session-context")), false);
} finally {
rmSync(root, { recursive: true, force: true });
}
});

test("installs the session context artifact only when explicitly selected", () => {
const { root, env } = fixture();
try {
const result = run(
["--harness", "codex", "--no-skills", "--artifact", "session-context"],
env,
);
assert.equal(result.status, 0, result.stderr);
const target = join(env.HARNESS_SKILLS_CODEX_DIR, "..", "session-context", "SESSION-CONTEXT.md");
assert.equal(existsSync(target), true);
assert.match(readFileSync(target, "utf8"), /Hooks remain unsupported unless explicitly configured/);
assert.match(result.stdout, /Installed 0 skill copies and 1 artifact copies/);
} finally {
rmSync(root, { recursive: true, force: true });
}
});

test("installs selected optional artifacts without skills", () => {
const { root, env } = fixture();
try {
Expand Down
Loading
Loading