@aacombarro89/praxis 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +34 -20
  2. package/dist/codex-marketplace.d.ts +19 -0
  3. package/dist/codex-marketplace.js +113 -0
  4. package/dist/codex-marketplace.js.map +1 -0
  5. package/dist/codex-security.d.ts +11 -0
  6. package/dist/codex-security.js +144 -0
  7. package/dist/codex-security.js.map +1 -0
  8. package/dist/emit.d.ts +38 -2
  9. package/dist/emit.js +167 -13
  10. package/dist/emit.js.map +1 -1
  11. package/dist/init.d.ts +16 -6
  12. package/dist/init.js +47 -10
  13. package/dist/init.js.map +1 -1
  14. package/dist/manifest.d.ts +2 -2
  15. package/dist/manifest.js +1 -1
  16. package/dist/manifest.js.map +1 -1
  17. package/dist/packages.d.ts +1 -1
  18. package/dist/plugins.d.ts +14 -0
  19. package/dist/plugins.js +9 -0
  20. package/dist/plugins.js.map +1 -1
  21. package/dist/program.d.ts +8 -0
  22. package/dist/program.js +93 -30
  23. package/dist/program.js.map +1 -1
  24. package/dist/shared-instructions.d.ts +21 -0
  25. package/dist/shared-instructions.js +63 -0
  26. package/dist/shared-instructions.js.map +1 -0
  27. package/dist/sync.d.ts +8 -1
  28. package/dist/sync.js +210 -7
  29. package/dist/sync.js.map +1 -1
  30. package/package.json +1 -1
  31. package/packages/external/ponytail/plugins.yaml +4 -1
  32. package/packages/layer1/instruction-upkeep/commands/instructions.md +14 -5
  33. package/packages/layer1/instruction-upkeep/rules.md +11 -23
  34. package/packages/layer1/onboarding/commands/onboard.md +42 -24
  35. package/packages/layer1/onboarding/rules.md +6 -10
  36. package/packages/layer1/safe-permissions/permissions.yaml +2 -2
  37. package/packages/layer1/session-handoff/commands/handoff.md +5 -5
  38. package/packages/layer1/session-handoff/rules.md +10 -57
  39. package/packages/layer1/upkeep/commands/upkeep.md +8 -5
  40. package/packages/layer1/upkeep/rules.md +12 -15
  41. package/packages/layer1/wiki-memory/commands/wiki.md +6 -6
  42. package/packages/layer1/wiki-memory/rules.md +11 -49
  43. package/packages/layer2/node-recipes/rules.md +4 -3
  44. package/packages/layer2/node-testing/rules.md +4 -0
  45. package/packages/layer2/python-backend-recipes/rules.md +4 -4
  46. package/packages/layer2/python-testing/rules.md +4 -0
  47. package/packages/layer2/react-components/rules.md +4 -0
  48. package/packages/layer2/react-testing/rules.md +4 -0
package/dist/sync.js CHANGED
@@ -1,7 +1,10 @@
1
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
- import { applyOp, planEmit } from "./emit.js";
3
+ import { applyOp, BLOCK_FILE, planEmit } from "./emit.js";
4
4
  import { loadManifest } from "./manifest.js";
5
+ import { blockStatus, findBlocks } from "./merge.js";
6
+ import { reconcileCodexConfig } from "./codex-security.js";
7
+ import { CODEX_MARKETPLACE_PATH, CODEX_MARKETPLACE_STATE_PATH, reconcileCodexMarketplace, } from "./codex-marketplace.js";
5
8
  export function runSync(opts) {
6
9
  const manifestPath = opts.manifestPath ?? join(opts.cwd, "praxis.yaml");
7
10
  return applyManifest(loadManifest(manifestPath), opts.cwd, opts.write);
@@ -14,19 +17,151 @@ export function runSync(opts) {
14
17
  export function applyManifest(manifest, cwd, write) {
15
18
  const ops = planEmit(manifest);
16
19
  const files = [];
20
+ const handledPaths = new Set();
17
21
  for (const op of ops) {
22
+ handledPaths.add(op.path);
23
+ if (op.kind === "codex-marketplace") {
24
+ handledPaths.add(op.statePath);
25
+ const marketplaceAbs = join(cwd, op.path);
26
+ const stateAbs = join(cwd, op.statePath);
27
+ const marketplaceExisting = readFileIfExists(marketplaceAbs) ?? "";
28
+ const stateExisting = readFileIfExists(stateAbs) ?? "";
29
+ const result = reconcileCodexMarketplace(marketplaceExisting, stateExisting, op.plugins);
30
+ for (const output of [
31
+ { path: op.path, abs: marketplaceAbs, existing: marketplaceExisting, text: result.marketplaceText, changed: result.marketplaceChanged, conflicts: result.conflicts },
32
+ { path: op.statePath, abs: stateAbs, existing: stateExisting, text: result.stateText, changed: result.stateChanged, conflicts: [] },
33
+ ]) {
34
+ const existed = existsSync(output.abs);
35
+ const status = !existed ? "created" : output.changed ? "updated" : "unchanged";
36
+ const written = write && output.changed;
37
+ if (written) {
38
+ mkdirSync(dirname(output.abs), { recursive: true });
39
+ writeFileSync(output.abs, output.text, "utf8");
40
+ }
41
+ files.push({ path: output.path, status, conflicts: output.conflicts, written });
42
+ }
43
+ continue;
44
+ }
18
45
  const abs = join(cwd, op.path);
19
46
  const existing = readFileIfExists(abs);
20
47
  const result = applyOp(op, existing ?? "");
21
- const status = existing === undefined ? "created" : result.changed ? "updated" : "unchanged";
22
- // Write safe changes only: never in check mode, never a pure no-op. result.text
48
+ let text = result.text;
49
+ let changed = result.changed;
50
+ let conflicts = result.conflicts;
51
+ // Prune orphan blocks in the same pass: a block-target file (e.g. AGENTS.md)
52
+ // may still carry a managed block for a package the manifest no longer
53
+ // selects. Splice those out of the already-reconciled text so the file
54
+ // report and the single write below cover both concerns together.
55
+ if (op.kind === "block") {
56
+ const pruned = pruneOrphanBlocks(text, new Set(Object.keys(op.blocks)));
57
+ text = pruned.text;
58
+ changed = changed || pruned.changed;
59
+ conflicts = [...conflicts, ...pruned.conflicts];
60
+ }
61
+ const status = existing === undefined ? "created" : changed ? "updated" : "unchanged";
62
+ // Write safe changes only: never in check mode, never a pure no-op. `text`
23
63
  // already preserves any conflicted block, so writing it honors D10.
24
- const written = write && (status === "created" || (status === "updated" && result.changed));
64
+ const written = write && (status === "created" || status === "updated");
25
65
  if (written) {
26
66
  mkdirSync(dirname(abs), { recursive: true });
27
- writeFileSync(abs, result.text, "utf8");
67
+ writeFileSync(abs, text, "utf8");
28
68
  }
29
- files.push({ path: op.path, status, conflicts: result.conflicts, written });
69
+ files.push({ path: op.path, status, conflicts, written });
70
+ }
71
+ // Block orphans in a file the manifest no longer emits ANY block for (e.g. the
72
+ // last rules package for a target was removed): no "block" op exists this run
73
+ // to carry the pruning above, so sweep the known block-owned files directly.
74
+ for (const path of new Set(Object.values(BLOCK_FILE))) {
75
+ if (handledPaths.has(path))
76
+ continue;
77
+ const abs = join(cwd, path);
78
+ const existing = readFileIfExists(abs);
79
+ if (existing === undefined)
80
+ continue;
81
+ const pruned = pruneOrphanBlocks(existing, new Set());
82
+ if (!pruned.changed && pruned.conflicts.length === 0)
83
+ continue;
84
+ const written = write && pruned.changed;
85
+ if (written)
86
+ writeFileSync(abs, pruned.text, "utf8");
87
+ files.push({
88
+ path,
89
+ status: pruned.changed ? "updated" : "unchanged",
90
+ conflicts: pruned.conflicts,
91
+ written,
92
+ });
93
+ }
94
+ // A removed Codex permissions package/target removes only Praxis's protected
95
+ // TOML block; unrelated project configuration remains byte-for-byte intact.
96
+ const codexConfigPath = ".codex/config.toml";
97
+ if (!handledPaths.has(codexConfigPath)) {
98
+ const abs = join(cwd, codexConfigPath);
99
+ const existing = readFileIfExists(abs);
100
+ if (existing !== undefined) {
101
+ const result = reconcileCodexConfig(existing, false);
102
+ if (result.changed || result.conflicts.length > 0) {
103
+ const written = write && result.changed;
104
+ if (written)
105
+ writeFileSync(abs, result.text, "utf8");
106
+ files.push({
107
+ path: codexConfigPath,
108
+ status: result.changed ? "updated" : "unchanged",
109
+ conflicts: result.conflicts,
110
+ written,
111
+ });
112
+ }
113
+ }
114
+ }
115
+ // Marketplace ownership lives in a committed sidecar. Without that state,
116
+ // removal is deliberately conservative: Praxis cannot prove an entry is its own.
117
+ if (!handledPaths.has(CODEX_MARKETPLACE_PATH)) {
118
+ const marketplaceAbs = join(cwd, CODEX_MARKETPLACE_PATH);
119
+ const stateAbs = join(cwd, CODEX_MARKETPLACE_STATE_PATH);
120
+ const marketplaceExisting = readFileIfExists(marketplaceAbs);
121
+ const stateExisting = readFileIfExists(stateAbs);
122
+ if (marketplaceExisting !== undefined && stateExisting !== undefined) {
123
+ const result = reconcileCodexMarketplace(marketplaceExisting, stateExisting, []);
124
+ for (const output of [
125
+ { path: CODEX_MARKETPLACE_PATH, abs: marketplaceAbs, text: result.marketplaceText, changed: result.marketplaceChanged, conflicts: result.conflicts },
126
+ { path: CODEX_MARKETPLACE_STATE_PATH, abs: stateAbs, text: result.stateText, changed: result.stateChanged, conflicts: [] },
127
+ ]) {
128
+ if (!output.changed && output.conflicts.length === 0)
129
+ continue;
130
+ const written = write && output.changed;
131
+ if (written)
132
+ writeFileSync(output.abs, output.text, "utf8");
133
+ files.push({
134
+ path: output.path,
135
+ status: output.changed ? "updated" : "unchanged",
136
+ conflicts: output.conflicts,
137
+ written,
138
+ });
139
+ }
140
+ }
141
+ else if (stateExisting !== undefined) {
142
+ // marketplace.json is gone (hand-deleted or never re-created) but the
143
+ // Praxis-owned sidecar remains — it now describes nothing and would
144
+ // otherwise orphan forever. Prune it (D46: manifest expresses absence).
145
+ if (write)
146
+ unlinkSync(stateAbs);
147
+ files.push({ path: CODEX_MARKETPLACE_STATE_PATH, status: "deleted", conflicts: [], written: write });
148
+ }
149
+ }
150
+ // Owned-file orphans: `.claude/rules/praxis-*.md` / `.claude/commands/praxis-*.md`
151
+ // on disk that the current manifest no longer implies (the package that used to
152
+ // own them was removed, or its target was). The `praxis-` prefix is the
153
+ // ownership convention; a user's own file with that prefix would be flagged too
154
+ // — acceptable because deletion is always previewed here, never silent.
155
+ const impliedOwnedPaths = new Set(ops.filter((op) => op.kind === "owned").map((op) => op.path));
156
+ for (const path of findOwnedOrphans(cwd, impliedOwnedPaths)) {
157
+ if (write) {
158
+ const abs = join(cwd, path);
159
+ unlinkSync(abs);
160
+ const parent = dirname(abs);
161
+ if (path.startsWith(".agents/skills/") && readdirSync(parent).length === 0)
162
+ rmdirSync(parent);
163
+ }
164
+ files.push({ path, status: "deleted", conflicts: [], written: write });
30
165
  }
31
166
  return {
32
167
  files,
@@ -42,4 +177,72 @@ function readFileIfExists(path) {
42
177
  return undefined;
43
178
  }
44
179
  }
180
+ // Directories whose contents are Praxis-owned by naming convention alone — see
181
+ // `planEmit` in src/emit.ts; files in these directories are owned by prefix.
182
+ const OWNED_ORPHAN_DIRS = [".claude/rules", ".claude/commands", ".codex/rules"];
183
+ /** Praxis-owned files on disk (by the `praxis-` prefix convention) whose path is
184
+ * not in `impliedPaths` — the current manifest no longer emits them. */
185
+ function findOwnedOrphans(cwd, impliedPaths) {
186
+ const orphans = [];
187
+ for (const dir of OWNED_ORPHAN_DIRS) {
188
+ const abs = join(cwd, dir);
189
+ if (!existsSync(abs))
190
+ continue;
191
+ for (const entry of readdirSync(abs, { withFileTypes: true })) {
192
+ const suffix = dir === ".codex/rules" ? ".rules" : ".md";
193
+ if (!entry.isFile() || !entry.name.startsWith("praxis-") || !entry.name.endsWith(suffix))
194
+ continue;
195
+ const path = `${dir}/${entry.name}`;
196
+ if (!impliedPaths.has(path))
197
+ orphans.push(path);
198
+ }
199
+ }
200
+ const skillsDir = join(cwd, ".agents/skills");
201
+ if (existsSync(skillsDir)) {
202
+ for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
203
+ if (!entry.isDirectory() || !entry.name.startsWith("praxis-"))
204
+ continue;
205
+ const path = `.agents/skills/${entry.name}/SKILL.md`;
206
+ if (existsSync(join(cwd, path)) && !impliedPaths.has(path))
207
+ orphans.push(path);
208
+ }
209
+ }
210
+ return orphans;
211
+ }
212
+ /** Remove one managed block (both markers + content) from `text`, absorbing the
213
+ * blank-line separator and trailing newline that `appendBlock` (src/merge.ts)
214
+ * introduces when a block is first added — so removing an orphan restores the
215
+ * surrounding prose to exactly what it was before the block ever existed. */
216
+ function spliceOutBlock(text, block) {
217
+ let start = block.start;
218
+ let end = block.end;
219
+ if (text.slice(end, end + 1) === "\n")
220
+ end += 1;
221
+ if (text.slice(Math.max(0, start - 2), start) === "\n\n")
222
+ start -= 1;
223
+ return text.slice(0, start) + text.slice(end);
224
+ }
225
+ /** Splice every managed block out of `text` whose id is not in `keepIds` — the
226
+ * block-file analogue of `findOwnedOrphans`. Mirrors `reconcile`'s conflict rule
227
+ * (D10): a block whose content hash no longer matches its recorded marker was
228
+ * user-edited, so it is reported as a conflict and left untouched, never deleted. */
229
+ function pruneOrphanBlocks(text, keepIds) {
230
+ let out = text;
231
+ let changed = false;
232
+ const conflicts = [];
233
+ const skip = new Set();
234
+ for (;;) {
235
+ const orphan = findBlocks(out).find((b) => !keepIds.has(b.id) && !skip.has(b.id));
236
+ if (!orphan)
237
+ break;
238
+ if (blockStatus(orphan) === "user-edited") {
239
+ conflicts.push(orphan.id);
240
+ skip.add(orphan.id);
241
+ continue;
242
+ }
243
+ out = spliceOutBlock(out, orphan);
244
+ changed = true;
245
+ }
246
+ return { text: out, changed, conflicts };
247
+ }
45
248
  //# sourceMappingURL=sync.js.map
package/dist/sync.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAiB,MAAM,eAAe,CAAC;AAoC5D,MAAM,UAAU,OAAO,CAAC,IAAiB;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACxE,OAAO,aAAa,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,QAAkB,EAAE,GAAW,EAAE,KAAc;IAC3E,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE/B,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;QAE3C,MAAM,MAAM,GACV,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;QAEhF,gFAAgF;QAChF,oEAAoE;QACpE,MAAM,OAAO,GACX,KAAK,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9E,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO;QACL,KAAK;QACL,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;QACpD,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aacombarro89/praxis",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "A CLI that installs an AI methodology layer into a codebase.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,7 +2,7 @@
2
2
  # Praxis never executes anything here — this is committable config that Claude
3
3
  # Code itself reads on folder-trust to offer installing/enabling the plugin.
4
4
  # Verified against github.com/DietrichGebert/ponytail (tag v4.7.0 exists).
5
- targets: [claude-code]
5
+ targets: [claude-code, codex]
6
6
  marketplace:
7
7
  name: ponytail
8
8
  source:
@@ -11,3 +11,6 @@ marketplace:
11
11
  ref: v4.7.0
12
12
  enable:
13
13
  - ponytail@ponytail
14
+ codex:
15
+ name: ponytail
16
+ category: Developer Tools
@@ -1,14 +1,16 @@
1
1
  ---
2
- description: Keep the authored instruction files (CLAUDE.md, .claude/rules) current with the project's state and complete against the standard rubric.
2
+ description: Keep the project's authored agent instruction files current with its state and complete against the standard rubric.
3
3
  ---
4
4
 
5
- Scope: $ARGUMENTS
5
+ Scope: {{arguments}}
6
6
 
7
- This updates the **authored instruction layer** — `CLAUDE.md` and
8
- `.claude/rules` not the tool's native auto-memory and not any 3rd-party
7
+ This updates the **authored agent instruction layer** — project-owned prose in
8
+ the selected tool's instruction surfaces — not native auto-memory and not any 3rd-party
9
9
  agent-memory system. Those are out of scope.
10
10
 
11
- 1. Read `CLAUDE.md` and every file under `.claude/rules`. Identify any
11
+ 1. Read `praxis.yaml`, then read every project instruction surface selected by
12
+ its first-class targets (`CLAUDE.md` for Claude Code, `AGENTS.md` for Codex).
13
+ Identify any
12
14
  canonical doc they point to (architecture doc, decision log, design doc).
13
15
  2. Compare what the instruction files claim against that canonical doc and
14
16
  against recent git history (`git log`, changed files) and the current
@@ -21,6 +23,11 @@ agent-memory system. Those are out of scope.
21
23
  - always-do rules (the few non-negotiable habits)
22
24
 
23
25
  Flag any rubric section that's entirely absent, citing where it should go.
26
+ When Claude Code and Codex are both selected, inspect the project-owned
27
+ `praxis:shared-project` block in both native files. Their contents must match
28
+ exactly (apart from line endings), while prose outside the blocks may differ.
29
+ Treat a missing, duplicate, or mismatched block reported by `praxis check` as
30
+ authored instruction drift — never choose one file as the automatic winner.
24
31
  3. **Ask the user before editing anything.** Present the list from step 2 and
25
32
  confirm which items to fix.
26
33
  4. For approved items, update only project-owned sections of the instruction
@@ -28,6 +35,8 @@ agent-memory system. Those are out of scope.
28
35
  code, or the user's answer. Where an instruction file currently restates a
29
36
  fact that lives in a canonical doc, prefer replacing the restatement with a
30
37
  link to that doc (reference, don't duplicate) so it can't drift again.
38
+ In a dual-target repo, apply approved shared-fact changes to both shared blocks
39
+ together and preserve all target-specific content outside them.
31
40
  5. If an instruction file carries `praxisAnchors` frontmatter, revalidate and
32
41
  update the anchors for any changed source reference. Phase-2 anchors are
33
42
  deterministic only:
@@ -1,26 +1,14 @@
1
1
  ## Instruction upkeep
2
2
 
3
- The authored instruction layer (`CLAUDE.md`, `.claude/rules`) drifts as a
4
- project changes, and can be incomplete from the start. Keep it both current
5
- and complete:
3
+ The authored agent instruction layer drifts as a
4
+ project changes. When it goes stale, incomplete, or a misunderstanding
5
+ surfaces, fix it — checking coverage against: build/test/run commands ·
6
+ layout · conventions · always-do rules.
6
7
 
7
- - When the project changes in a way that makes an instruction stale, or a
8
- misunderstanding surfaces that's worth encoding, update the instruction
9
- files rather than letting the gap persist.
10
- - An instruction file should document, for any project: build/test/run
11
- commands, project layout, key conventions, and always-do rules. If one of
12
- these is missing, fill it by discovery and asking the user — never invent
13
- a fact that isn't backed by the code, config, or the user's answer.
14
- - Prefer linking a canonical source (e.g. an architecture doc) over restating
15
- its facts — restated facts drift independently of their source.
16
- - If a *derived overview* like `README.md` exists, check it hasn't drifted from
17
- its canonical sources — being a restatement of them, it drifts by
18
- construction; reconcile it to the source rather than the reverse.
19
- - When instruction files include `praxisAnchors` frontmatter, keep those anchors
20
- resolving. `praxis check` hard-fails broken `path`, `command`, and `section`
21
- anchors; staleness signals are future advisory work.
22
- - Make instruction-layer changes through `/praxis-instructions`, not ad-hoc edits — run
23
- it when unsure whether the instruction files still match the project, or whether
24
- they cover the sections above. When this is part of reconciling the methodology
25
- layer after a change, enter through the `/praxis-upkeep` front gate (which
26
- delegates here) instead of running this pass alone.
8
+ When multiple first-class targets are selected, audit every native project
9
+ instruction surface. Shared project sections must remain consistent; native
10
+ target-specific sections may differ.
11
+
12
+ Make changes through `{{workflow:praxis-instructions}}`, not ad-hoc edits. When
13
+ reconciling the methodology layer after a change, enter through
14
+ `{{workflow:praxis-upkeep}}` (which delegates here) instead of running this pass alone.
@@ -1,24 +1,37 @@
1
1
  ---
2
- description: Author the project-owned sections of CLAUDE.md for a fresh Praxis install build/run/test commands, layout, conventions, and always-do rules. One-shot: deletes .praxis-setup-pending when done.
2
+ description: Author project-owned agent instructions for a fresh Praxis install—build/run/test commands, layout, conventions, and always-do rules. One-shot: deletes .praxis-setup-pending when done.
3
3
  ---
4
4
 
5
- Scope: $ARGUMENTS
5
+ Scope: {{arguments}}
6
6
 
7
7
  This is the **first-run front gate** — the single entry point for a fresh Praxis
8
- install, symmetric to `/praxis-upkeep` (the ongoing front gate). It authors the
9
- **project-owned** sections of `CLAUDE.md`, then seeds the installed methodology
10
- packages, then hands off to `/praxis-upkeep` so the full baseline is established
8
+ install, symmetric to `{{workflow:praxis-upkeep}}` (the ongoing front gate). It authors
9
+ the **project-owned** agent instructions, then seeds the installed methodology
10
+ packages, then hands off to `{{workflow:praxis-upkeep}}` so the full baseline is established
11
11
  in one pass.
12
12
 
13
- Praxis never calls an LLM (D12); never edits `CLAUDE.md` directly (D13). The
13
+ Praxis never calls an LLM (D12) or authors project facts directly (D13). The
14
14
  **agent** writes the facts, guided by the steps below, asking the user for
15
15
  anything it cannot infer.
16
16
 
17
- 1. **Bulk discovery lean on the tool's native `/init` first.** If `CLAUDE.md`
18
- does not yet exist (or is empty), suggest running the tool's built-in `/init`
19
- command so the model can auto-discover repository facts (files, build config,
20
- README). Incorporate any useful output into the project-owned sections below,
21
- rather than restating it from scratch.
17
+ 1. **Choose the project instruction surfaces from `praxis.yaml`.** For a Codex-only
18
+ install, author project facts as free prose outside managed blocks in `AGENTS.md`.
19
+ For Claude-only, retain the existing `CLAUDE.md` flow. When both are selected,
20
+ maintain both native files as peers never make either import or replace the
21
+ other. Put facts shared by both tools inside exactly one project-owned block in
22
+ each file, with identical content and these marker lines:
23
+
24
+ ```markdown
25
+ <!-- praxis:shared-project begin -->
26
+ ...shared project facts...
27
+ <!-- praxis:shared-project end -->
28
+ ```
29
+
30
+ The markers declare a parity contract, not Praxis ownership: the project owns
31
+ the prose and both native files remain complete if Praxis is removed. Guidance
32
+ outside this block may differ by target. If the active tool offers a native
33
+ repository initialization workflow, suggest it for bulk discovery and
34
+ incorporate useful output rather than re-deriving it.
22
35
 
23
36
  2. **Check detected stacks (if known).** Read `praxis.yaml` for the `stacks:`
24
37
  field. If stacks are declared, tailor the sections below to those stacks (e.g.
@@ -44,30 +57,35 @@ anything it cannot infer.
44
57
  short; a long always-do list is never read.
45
58
 
46
59
  4. **Ask the user for anything not inferable.** If a section can't be filled from
47
- config files, git history, or the `/init` output, ask a targeted question
48
- rather than inventing a plausible answer. Content inclusion bar: a fact only
49
- enters if it's backed by the code, config, a canonical doc, or the user.
60
+ config files, git history, or the native initialization workflow's output, ask
61
+ a targeted question rather than inventing a plausible answer. Content
62
+ inclusion bar: a fact only enters if it's backed by the code, config, a
63
+ canonical doc, or the user.
50
64
 
51
65
  5. **Write only project-owned content.** Never put content inside a Praxis
52
- managed block (a `<!-- praxis-start … -->` / `<!-- praxis-end … -->` region).
53
- Project facts belong in the free-prose sections the author controls; Praxis
54
- owns only its own managed blocks.
66
+ managed block (a `<!-- praxis:begin … -->` / `<!-- praxis:end … -->` region).
67
+ Project facts belong in the free-prose sections the author controls; the
68
+ unhashed `praxis:shared-project` block is also project-owned. Praxis owns only
69
+ its hashed managed blocks. When both native files are selected, write the four
70
+ rubric sections to both shared blocks in one edit and keep their content exact.
55
71
 
56
72
  6. **Run each installed companion bootstrap action** (each seeds part of the
57
- methodology), then hand off to `/praxis-upkeep`:
73
+ methodology), then hand off to `{{workflow:praxis-upkeep}}`:
58
74
 
59
75
  <!-- praxis:bootstrap-delegations -->
60
76
 
61
- After the bootstrap actions above complete, run `/praxis-upkeep` to confirm
62
- the full methodology baseline is in sync. If `/praxis-upkeep` is not
77
+ After the bootstrap actions above complete, run `{{workflow:praxis-upkeep}}` to confirm
78
+ the full methodology baseline is in sync. If `{{workflow:praxis-upkeep}}` is not
63
79
  installed, skip this step.
64
80
 
65
81
  7. **Delete `.praxis-setup-pending`** to make this one-shot. Once the rubric
66
- sections are authored and the user is satisfied, remove the sentinel file
67
- from the repo root. This prevents the bootstrap rule (`.claude/rules/
68
- praxis-onboarding.md`) from re-offering onboarding on the next session.
82
+ sections are authored, the bootstrap actions and upkeep pass above have run,
83
+ and the user is satisfied, remove the sentinel file from the repo root. This
84
+ prevents the bootstrap rule from re-offering onboarding on the next session
85
+ deleting it any earlier would leave an interrupted session with no re-offer
86
+ and an unseeded baseline.
69
87
 
70
88
  8. **Report what was written / left.** Summarise which rubric sections were
71
89
  filled, which were left empty (and why — e.g. "no build step detected"), and
72
90
  any follow-up items for the user. The baseline is now established; from here
73
- `/praxis-upkeep` keeps the methodology layer current.
91
+ `{{workflow:praxis-upkeep}}` keeps the methodology layer current.
@@ -1,14 +1,10 @@
1
1
  ## First-run onboarding
2
2
 
3
3
  At the start of work, check for the `.praxis-setup-pending` sentinel file in
4
- the repo root. Its presence means this is a fresh Praxis install and the
5
- project-owned sections of `CLAUDE.md` haven't been authored yet.
4
+ the repo root: present means a fresh Praxis install whose project-owned agent
5
+ instruction sections aren't authored yet.
6
6
 
7
- - **If the sentinel is present:** offer to run `/praxis-onboard`. Once the
8
- skill completes it deletes the sentinel — making this check one-shot and
9
- self-terminating. Never nag when the sentinel is absent.
10
- - **If the sentinel is absent:** do nothing here. The ongoing front gate
11
- (`/praxis-upkeep`) handles currency after initial setup.
12
-
13
- Cross-references: `/praxis-onboard` (first-run front gate),
14
- `/praxis-upkeep` (ongoing front gate — D29/D31, [onboarding](../../../docs/wiki/onboarding.md)).
7
+ - **Present:** offer to run `{{workflow:praxis-onboard}}`; it deletes the sentinel on
8
+ completion, making this check one-shot. Never nag when absent.
9
+ - **Absent:** do nothing here `{{workflow:praxis-upkeep}}` (ongoing front gate, D29/D31)
10
+ handles currency after initial setup.
@@ -1,7 +1,7 @@
1
1
  # Neutral permission policy — the enforcement side of the rails
2
2
  # (docs/wiki/emitters.md, D18/D19). Tool-agnostic INTENT expressed as capabilities; per-tool emitters
3
- # translate to concrete rule strings (Claude Code today; tools without a
4
- # permission model emit nothing). Edit your own settings to tune — Praxis owns
3
+ # translate to target-native Claude Code and Codex controls; tools without a
4
+ # permission model emit nothing. Edit your own settings to tune — Praxis owns
5
5
  # only the rules it emits and never clobbers rules you add.
6
6
  #
7
7
  # Posture: allow common local dev (smooth); prompt before anything that leaves the
@@ -46,10 +46,10 @@ single-doc flow below.
46
46
 
47
47
  Read the clock so the name sorts chronologically (do not guess the time):
48
48
 
49
- - Timestamp: !`date +%Y-%m-%d_%H%M`
49
+ - Timestamp: {{shell:date +%Y-%m-%d_%H%M}}
50
50
 
51
51
  Build the filename `YYYY-MM-DD_HHMM_HANDOFF_<topic>.md`:
52
- - `<topic>` is a short kebab-case slug for the work. Use `$ARGUMENTS` if
52
+ - `<topic>` is a short kebab-case slug for the work. Use {{arguments}} if
53
53
  provided; otherwise derive it from the task.
54
54
  - Date-and-time first means a plain alphabetical listing is chronological.
55
55
 
@@ -73,9 +73,9 @@ references* section below. Don't re-derive them; you already paid for them.
73
73
  If in a git repo, capture current branch, staged/unstaged changes, and recent
74
74
  commits from this session:
75
75
 
76
- - Branch: !`git branch --show-current 2>/dev/null`
77
- - Status: !`git status --short 2>/dev/null`
78
- - Recent commits: !`git log --oneline -10 2>/dev/null`
76
+ - Branch: {{shell:git branch --show-current 2>/dev/null}}
77
+ - Status: {{shell:git status --short 2>/dev/null}}
78
+ - Recent commits: {{shell:git log --oneline -10 2>/dev/null}}
79
79
 
80
80
  Capture verification state too: identify the project's own build/test/lint
81
81
  commands (from its config / docs / CI) and record their current result — what
@@ -1,62 +1,15 @@
1
1
  ## Session handoff
2
2
 
3
- Work outlives a single session: context windows fill, tasks switch, phases
4
- close. Before that state is lost, capture it so a fresh session, with none of
5
- the current conversation in memory, can resume without guessing or re-deriving.
6
-
7
- - Hand off at a natural boundary in a verified state — not mid-edit. Stop where
8
- the build and tests are green, or where any breakage is understood and noted.
9
- - Write handoffs by running `/praxis-handoff`, not by hand — it produces a
10
- self-contained, chronologically-named document. Treat it as the next session's
11
- only briefing.
12
- - Make it actionable: what's done, what's pending, the single most important
13
- next step, verification status, and any open decisions.
14
- - Carry the context forward, don't just summarize it. Reference the load-bearing
15
- files (`path:line`), the relevant design-doc sections, the prior-art to mirror,
16
- and the exact commands — so the next session skips re-running discovery.
17
- - Note instruction-layer follow-up: if the session changed the project in a way
18
- that makes the authored instruction files stale or incomplete, say so.
19
- - Keep handoffs together in one directory so they sort in chronological order;
20
- don't scatter them into the codebase.
3
+ Work outlives a single session: at a natural boundary in a verified state —
4
+ never mid-edit capture context before it's lost. Write handoffs by running
5
+ `{{workflow:praxis-handoff}}`, not by hand; it's the next session's only briefing.
21
6
 
22
7
  ## Delegated execution
23
8
 
24
- A handoff brief is not only for the *next* session it is also the briefing an
25
- execution agent needs to do scoped work *now*. The reason to delegate is to keep
26
- in the orchestrator's context only what it needs — the *result*, not the
27
- execution detail and to match each piece of work to the cheapest tier that can
28
- do it. Delegate when that holds; do the work inline when it doesn't.
29
-
30
- - Delegate when you need the result, not the detail. Two triggers, often
31
- combined — **neither requires parallelism**:
32
- - *Independent workstreams* — parts specifiable up front and runnable without
33
- coordination mid-flight (concurrently, where the tool allows). If two parts
34
- must talk constantly, they are one workstream.
35
- - *Context or budget isolation* — a context-heavy or mechanical run (a wide
36
- refactor, a multi-step migration, a long grind) worth executing in an
37
- execution agent's *own* context window, on a lighter/faster tier, so the
38
- orchestrator's context stays clean. This holds for a *single sequential*
39
- stream: size and cost justify delegating on their own.
40
- - Name the split at plan time. When a plan's steps form independent or
41
- context-heavy workstreams, surface the delegation split *as part of the plan* —
42
- what each execution agent runs and how its result returns — rather than only
43
- deciding to delegate mid-execution.
44
- - Brief each workstream as a self-contained context cache — the same discipline
45
- as a handoff. An execution agent starts cold: give it the load-bearing files
46
- (`path:line`), the prior art to mirror, the exact build/test commands, and a
47
- crisp success/verify criterion. A vague brief gets vague work back.
48
- - Keep the tiers to their jobs. The orchestrator plans, decomposes, verifies, and
49
- integrates; execution agents do bounded, fully-specified work and return the
50
- result, not the intermediate detail. Match the tier to the work — execution
51
- agents can be lighter/faster than the orchestrator. (Stated by role, not by
52
- model name, so it survives model releases.)
53
- - Verify on return; trust nothing unread. Each returned workstream is checked
54
- against its stated success criterion (build, tests, a read of the diff) before
55
- it is integrated — the orchestrator owns correctness of the whole.
56
- - Produce the briefs with `/praxis-handoff` (run it per workstream), not by hand,
57
- so each is self-contained. Dispatch a subagent per brief where the tool
58
- supports subagents; where it does not, run the briefs inline in sequence or
59
- hand them to a fresh session — same brief, different venue.
60
- - Use judgment on whether to delegate at all. It pays off for multi-workstream or
61
- context-heavy work; for a small single-thread change the briefing cost exceeds
62
- the savings — just do it inline.
9
+ Delegate when you need the result, not the execution detail. Two triggers,
10
+ neither requiring parallelism: **independent workstreams** (specifiable up
11
+ front, no mid-flight coordination) and **context/budget isolation** (a
12
+ context-heavy or mechanical run worth its own context and a lighter tier
13
+ holds even for one sequential stream). Name the split at plan time. Produce
14
+ each brief with `{{workflow:praxis-handoff}}`, not by hand, and verify a returned
15
+ workstream against its success criterion before integrating it.