dsh-pstack 0.2.0-beta.1 → 0.2.0-beta.3

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 (261) hide show
  1. package/LICENSE +2 -3
  2. package/README.md +135 -84
  3. package/README.zh.md +185 -0
  4. package/cordis.patch.yml +97 -27
  5. package/dist/host-contract-CUPSpeNk.d.mts +22 -0
  6. package/dist/index.d.mts +49 -238
  7. package/dist/index.mjs +250 -123
  8. package/dist/models.d.mts +44 -0
  9. package/dist/models.mjs +201 -0
  10. package/dist/paths-BT77khwm.mjs +48 -0
  11. package/dist/pstack/LICENSE +21 -0
  12. package/dist/pstack/README.md +291 -0
  13. package/dist/pstack/agents/poteto-agent.md +9 -0
  14. package/{assets → dist/pstack}/docs/guide/01-setup.md +13 -11
  15. package/{assets → dist/pstack}/docs/guide/02-poteto-mode.md +4 -4
  16. package/{assets → dist/pstack}/docs/guide/04-design.md +4 -4
  17. package/{assets → dist/pstack}/docs/guide/05-build-and-clean.md +2 -2
  18. package/{assets → dist/pstack}/docs/guide/06-verify-and-ship.md +13 -3
  19. package/{assets → dist/pstack}/docs/guide/07-overnight.md +15 -13
  20. package/{assets → dist/pstack}/docs/guide/09-make-it-yours.md +6 -2
  21. package/{assets → dist/pstack}/docs/guide/10-recipes-and-pitfalls.md +7 -5
  22. package/{assets → dist/pstack}/docs/guide/README.md +1 -1
  23. package/dist/pstack/docs/harness/dsh.md +98 -0
  24. package/{assets → dist/pstack}/skills/architect/SKILL.md +12 -12
  25. package/dist/pstack/skills/arena/SKILL.md +50 -0
  26. package/{assets → dist/pstack}/skills/automate-me/SKILL.md +14 -14
  27. package/{assets → dist/pstack}/skills/benchmark-checklist/SKILL.md +1 -1
  28. package/{assets → dist/pstack}/skills/blast-radius/SKILL.md +4 -6
  29. package/{assets → dist/pstack}/skills/correct/SKILL.md +1 -1
  30. package/{assets → dist/pstack}/skills/create-formal-verification-skill/SKILL.md +4 -2
  31. package/{assets → dist/pstack}/skills/create-verification-skill/SKILL.md +5 -5
  32. package/dist/pstack/skills/figure-it-out/SKILL.md +54 -0
  33. package/dist/pstack/skills/how/SKILL.md +38 -0
  34. package/{assets → dist/pstack}/skills/in-your-own-words/SKILL.md +1 -1
  35. package/dist/pstack/skills/interrogate/SKILL.md +33 -0
  36. package/{assets → dist/pstack}/skills/ketchup/SKILL.md +3 -5
  37. package/dist/pstack/skills/ketchup-video/SKILL.md +29 -0
  38. package/{assets → dist/pstack}/skills/maintain-formal-verification-skill/SKILL.md +1 -1
  39. package/{assets → dist/pstack}/skills/maintain-verification-skill/SKILL.md +3 -3
  40. package/dist/pstack/skills/make-bot-ui/SKILL.md +117 -0
  41. package/dist/pstack/skills/no-comments/SKILL.md +26 -0
  42. package/{assets → dist/pstack}/skills/poteto-help/SKILL.md +34 -31
  43. package/{assets → dist/pstack}/skills/poteto-help/references/prompting.md +1 -1
  44. package/{assets → dist/pstack}/skills/poteto-help/references/recipes.md +3 -3
  45. package/{assets → dist/pstack}/skills/poteto-mode/SKILL.md +20 -19
  46. package/dist/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  47. package/dist/pstack/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  48. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-full.md +25 -0
  49. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  50. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/babysit.md +4 -4
  51. package/dist/pstack/skills/poteto-mode/playbooks/bug-fix.md +15 -0
  52. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/eval.md +3 -3
  53. package/dist/pstack/skills/poteto-mode/playbooks/feature.md +21 -0
  54. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/hillclimb.md +3 -3
  55. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/investigation.md +2 -2
  56. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/multi-phase-plan.md +23 -23
  57. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/opening-a-pr.md +6 -6
  58. package/dist/pstack/skills/poteto-mode/playbooks/orchestrate.md +25 -0
  59. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/pause-safely.md +2 -2
  60. package/dist/pstack/skills/poteto-mode/playbooks/perf-issue.md +25 -0
  61. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/prototype.md +4 -4
  62. package/dist/pstack/skills/poteto-mode/playbooks/refactoring.md +16 -0
  63. package/dist/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  64. package/dist/pstack/skills/poteto-mode/playbooks/session-pickup.md +11 -0
  65. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/shipping.md +2 -2
  66. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/trace-forensics.md +2 -2
  67. package/dist/pstack/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  68. package/dist/pstack/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
  69. package/{assets → dist/pstack}/skills/poteto-mode/scripts/check-plan.mjs +6 -8
  70. package/dist/pstack/skills/poteto-mode/scripts/check-plan.test.mjs +128 -0
  71. package/{assets/skills/poteto-mode/scripts/check-plan.test.mjs → dist/pstack/skills/poteto-mode/scripts/expect.mjs} +12 -101
  72. package/dist/pstack/skills/poteto-mode/scripts/support.mjs +93 -0
  73. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.mjs +123 -0
  74. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +217 -0
  75. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.mjs +119 -0
  76. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.mjs +626 -0
  77. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.test.mjs +521 -0
  78. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.mjs +657 -0
  79. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +523 -0
  80. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/render.mjs +106 -0
  81. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/types.mjs +9 -0
  82. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +5 -0
  83. package/{assets → dist/pstack}/skills/poteto-mode/scripts/worktree-audit.mjs +15 -22
  84. package/dist/pstack/skills/poteto-mode/scripts/worktree-audit.test.mjs +134 -0
  85. package/{assets → dist/pstack}/skills/principle-attack-the-premise/SKILL.md +1 -1
  86. package/{assets → dist/pstack}/skills/principle-boundary-discipline/SKILL.md +1 -1
  87. package/{assets → dist/pstack}/skills/principle-encode-lessons-in-structure/SKILL.md +1 -1
  88. package/{assets → dist/pstack}/skills/principle-exhaust-the-design-space/SKILL.md +1 -1
  89. package/{assets → dist/pstack}/skills/principle-experience-first/SKILL.md +1 -1
  90. package/{assets → dist/pstack}/skills/principle-explain-the-number/SKILL.md +3 -2
  91. package/{assets → dist/pstack}/skills/principle-fix-root-causes/SKILL.md +1 -1
  92. package/{assets → dist/pstack}/skills/principle-laziness-protocol/SKILL.md +1 -1
  93. package/{assets → dist/pstack}/skills/principle-make-operations-idempotent/SKILL.md +1 -1
  94. package/{assets → dist/pstack}/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +1 -1
  95. package/{assets → dist/pstack}/skills/principle-minimize-reader-load/SKILL.md +1 -1
  96. package/{assets → dist/pstack}/skills/principle-model-the-domain/SKILL.md +1 -1
  97. package/{assets → dist/pstack}/skills/principle-never-block-on-the-human/SKILL.md +1 -1
  98. package/{assets → dist/pstack}/skills/principle-outcome-oriented-execution/SKILL.md +1 -1
  99. package/{assets → dist/pstack}/skills/principle-prove-it-works/SKILL.md +2 -2
  100. package/{assets → dist/pstack}/skills/principle-redesign-from-first-principles/SKILL.md +1 -1
  101. package/{assets → dist/pstack}/skills/principle-separate-before-serializing-shared-state/SKILL.md +1 -1
  102. package/{assets → dist/pstack}/skills/principle-sequence-verifiable-units/SKILL.md +1 -1
  103. package/{assets → dist/pstack}/skills/principle-subtract-before-you-add/SKILL.md +1 -1
  104. package/{assets → dist/pstack}/skills/principle-test-behavior-not-implementation/SKILL.md +1 -1
  105. package/{assets → dist/pstack}/skills/principle-type-system-discipline/SKILL.md +1 -1
  106. package/dist/pstack/skills/recall/SKILL.md +37 -0
  107. package/dist/pstack/skills/reflect/SKILL.md +71 -0
  108. package/{assets → dist/pstack}/skills/reflect/references/divergent-reviewer.md +4 -4
  109. package/{assets → dist/pstack}/skills/reflect/references/judgment-reviewer.md +2 -2
  110. package/{assets → dist/pstack}/skills/reflect/references/synthesizer.md +5 -5
  111. package/{assets → dist/pstack}/skills/reflect/references/tooling-reviewer.md +2 -2
  112. package/dist/pstack/skills/setup-pstack/SKILL.md +80 -0
  113. package/{assets → dist/pstack}/skills/sharpen/SKILL.md +1 -1
  114. package/{assets → dist/pstack}/skills/show-me-your-work/SKILL.md +8 -8
  115. package/{assets → dist/pstack}/skills/show-me-your-work/scripts/log.mjs +1 -3
  116. package/dist/pstack/skills/show-me-your-work/scripts/log.test.mjs +56 -0
  117. package/dist/pstack/skills/statechart/SKILL.md +82 -0
  118. package/dist/pstack/skills/statechart/references/render.md +93 -0
  119. package/dist/pstack/skills/statechart/scripts/backends/cfg.mjs +31 -0
  120. package/dist/pstack/skills/statechart/scripts/backends/mermaid.mjs +186 -0
  121. package/dist/pstack/skills/statechart/scripts/backends/plain-text.mjs +62 -0
  122. package/dist/pstack/skills/statechart/scripts/backends/report.mjs +84 -0
  123. package/dist/pstack/skills/statechart/scripts/frontends/config.mjs +268 -0
  124. package/dist/pstack/skills/statechart/scripts/frontends/dot.mjs +67 -0
  125. package/dist/pstack/skills/statechart/scripts/frontends/marks.mjs +94 -0
  126. package/dist/pstack/skills/statechart/scripts/frontends/messages.mjs +48 -0
  127. package/dist/pstack/skills/statechart/scripts/frontends/spec.mjs +101 -0
  128. package/dist/pstack/skills/statechart/scripts/frontends/trace.mjs +39 -0
  129. package/dist/pstack/skills/statechart/scripts/frontends/value.mjs +180 -0
  130. package/dist/pstack/skills/statechart/scripts/frontends/verdict.mjs +40 -0
  131. package/dist/pstack/skills/statechart/scripts/frontends/view.mjs +99 -0
  132. package/dist/pstack/skills/statechart/scripts/ir.mjs +277 -0
  133. package/dist/pstack/skills/statechart/scripts/passes/annotate.mjs +92 -0
  134. package/dist/pstack/skills/statechart/scripts/passes/label.mjs +210 -0
  135. package/dist/pstack/skills/statechart/scripts/passes/lift.mjs +84 -0
  136. package/dist/pstack/skills/statechart/scripts/passes/loop-check.mjs +47 -0
  137. package/dist/pstack/skills/statechart/scripts/passes/paths.mjs +72 -0
  138. package/dist/pstack/skills/statechart/scripts/passes/reach.mjs +135 -0
  139. package/dist/pstack/skills/statechart/scripts/passes/region-check.mjs +82 -0
  140. package/dist/pstack/skills/statechart/scripts/passes/regions.mjs +268 -0
  141. package/dist/pstack/skills/statechart/scripts/pipeline.mjs +72 -0
  142. package/dist/pstack/skills/statechart/scripts/run.mjs +440 -0
  143. package/dist/pstack/skills/statechart/scripts/statechart.mjs +155 -0
  144. package/dist/pstack/skills/statechart/scripts/statechart.test.mjs +198 -0
  145. package/dist/pstack/skills/statechart/scripts/worker.mjs +31 -0
  146. package/dist/pstack/skills/swarm/SKILL.md +43 -0
  147. package/{assets → dist/pstack}/skills/tdd/SKILL.md +1 -1
  148. package/{assets → dist/pstack}/skills/teach/SKILL.md +2 -2
  149. package/{assets → dist/pstack}/skills/technical-writing/SKILL.md +1 -1
  150. package/{assets → dist/pstack}/skills/typescript-best-practices/SKILL.md +3 -6
  151. package/{assets → dist/pstack}/skills/why/SKILL.md +8 -8
  152. package/dist/script.d.mts +9 -111
  153. package/dist/script.mjs +32 -329
  154. package/dist/skill.d.mts +38 -0
  155. package/dist/skill.mjs +183 -0
  156. package/dist/skills/authored/decision-audit/SKILL.md +99 -0
  157. package/dist/skills/authored/decision-audit/SKILL.zh.md +99 -0
  158. package/dist/skills/authored/decision-audit/references/recover-commit.md +17 -0
  159. package/dist/skills/authored/decision-audit/references/recover-commit.zh.md +17 -0
  160. package/dist/skills/authored/decision-write/SKILL.md +131 -0
  161. package/dist/skills/authored/decision-write/SKILL.zh.md +131 -0
  162. package/dist/skills/authored/decision-write/references/land.md +48 -0
  163. package/dist/skills/authored/decision-write/references/land.zh.md +48 -0
  164. package/dist/skills/authored/setup-project-docs/SKILL.md +58 -0
  165. package/dist/skills/authored/setup-project-docs/SKILL.zh.md +58 -0
  166. package/dist/skills/authored/setup-project-docs/references/decision-conventions.md +11 -0
  167. package/dist/skills/authored/setup-project-docs/references/decision-conventions.zh.md +11 -0
  168. package/dist/skills/vendored/retro/SKILL.md +44 -0
  169. package/dist/skills/vendored/retro/agents/openai.yaml +5 -0
  170. package/dist/skills/vendored/writing-for-agents/SKILL-MECHANICS.md +22 -0
  171. package/dist/skills/vendored/writing-for-agents/SKILL.md +81 -0
  172. package/dist/skills/vendored/writing-for-agents/agents/openai.yaml +3 -0
  173. package/dist/subagent.d.mts +56 -193
  174. package/dist/subagent.mjs +443 -741
  175. package/locale/en.json +3 -2
  176. package/locale/zh.json +3 -2
  177. package/package.json +63 -66
  178. package/assets/agents/poteto-agent.md +0 -8
  179. package/assets/docs/harness/dsh.md +0 -60
  180. package/assets/docs/pstack-models.example.md +0 -54
  181. package/assets/skills/arena/SKILL.md +0 -50
  182. package/assets/skills/figure-it-out/SKILL.md +0 -54
  183. package/assets/skills/how/SKILL.md +0 -38
  184. package/assets/skills/interrogate/SKILL.md +0 -71
  185. package/assets/skills/interrogate/references/code-quality-review.md +0 -47
  186. package/assets/skills/interrogate/references/lead-judgment.md +0 -39
  187. package/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  188. package/assets/skills/interrogate/references/rubric.md +0 -77
  189. package/assets/skills/no-comments/SKILL.md +0 -26
  190. package/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +0 -12
  191. package/assets/skills/poteto-mode/playbooks/autonomous-run.md +0 -15
  192. package/assets/skills/poteto-mode/playbooks/autopilot-full.md +0 -25
  193. package/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  194. package/assets/skills/poteto-mode/playbooks/bug-fix.md +0 -15
  195. package/assets/skills/poteto-mode/playbooks/feature.md +0 -21
  196. package/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  197. package/assets/skills/poteto-mode/playbooks/perf-issue.md +0 -25
  198. package/assets/skills/poteto-mode/playbooks/refactoring.md +0 -16
  199. package/assets/skills/poteto-mode/playbooks/runtime-forensics.md +0 -11
  200. package/assets/skills/poteto-mode/playbooks/session-pickup.md +0 -11
  201. package/assets/skills/poteto-mode/playbooks/visual-parity.md +0 -11
  202. package/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +0 -20
  203. package/assets/skills/poteto-mode/scripts/orch/orch.mjs +0 -4282
  204. package/assets/skills/poteto-mode/scripts/orch/orch.test.mjs +0 -2042
  205. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +0 -5101
  206. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.mjs +0 -1177
  207. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +0 -1441
  208. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +0 -4601
  209. package/assets/skills/recall/SKILL.md +0 -37
  210. package/assets/skills/reflect/SKILL.md +0 -69
  211. package/assets/skills/setup-pstack/SKILL.md +0 -67
  212. package/assets/skills/swarm/SKILL.md +0 -43
  213. package/dist/frontmatter-BQX3ekwP.mjs +0 -229
  214. package/dist/frontmatter-BQX3ekwP.mjs.map +0 -1
  215. package/dist/history.d.mts +0 -429
  216. package/dist/history.mjs +0 -1129
  217. package/dist/history.mjs.map +0 -1
  218. package/dist/host-contract-o47JH_r8.d.mts +0 -527
  219. package/dist/index.mjs.map +0 -1
  220. package/dist/paths-D_JlVmBk.mjs +0 -42
  221. package/dist/paths-D_JlVmBk.mjs.map +0 -1
  222. package/dist/script.mjs.map +0 -1
  223. package/dist/subagent.mjs.map +0 -1
  224. /package/{static/icon.png → assets/logo.png} +0 -0
  225. /package/{assets → dist/pstack}/agents/comment-sicko.md +0 -0
  226. /package/{assets → dist/pstack}/docs/guide/03-understand.md +0 -0
  227. /package/{assets → dist/pstack}/docs/guide/08-principles.md +0 -0
  228. /package/{assets → dist/pstack}/docs/guide/images/design.jpg +0 -0
  229. /package/{assets → dist/pstack}/docs/guide/images/overnight.jpg +0 -0
  230. /package/{assets → dist/pstack}/docs/guide/images/recipes.jpg +0 -0
  231. /package/{assets → dist/pstack}/docs/guide/images/router.jpg +0 -0
  232. /package/{assets → dist/pstack}/docs/guide/images/understanding.jpg +0 -0
  233. /package/{assets → dist/pstack}/docs/guide/images/verification.jpg +0 -0
  234. /package/{assets → dist/pstack}/skills/architect/references/design-red-flags.md +0 -0
  235. /package/{assets → dist/pstack}/skills/architect/references/rationale-template.md +0 -0
  236. /package/{assets → dist/pstack}/skills/architect/references/runner-prompt.md +0 -0
  237. /package/{assets → dist/pstack}/skills/bro/SKILL.md +0 -0
  238. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/README.md +0 -0
  239. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -0
  240. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/search.md +0 -0
  241. /package/{assets → dist/pstack}/skills/how/references/explainer-prompt.md +0 -0
  242. /package/{assets → dist/pstack}/skills/how/references/explorer-prompt.md +0 -0
  243. /package/{assets → dist/pstack}/skills/poteto-mode/references/bugbot-triage.md +0 -0
  244. /package/{assets → dist/pstack}/skills/principle-build-the-lever/SKILL.md +0 -0
  245. /package/{assets → dist/pstack}/skills/principle-foundational-thinking/SKILL.md +0 -0
  246. /package/{assets → dist/pstack}/skills/principle-guard-the-context-window/SKILL.md +0 -0
  247. /package/{assets → dist/pstack}/skills/show-me-your-work/references/decision-log-template.tsv +0 -0
  248. /package/{assets → dist/pstack}/skills/typescript-best-practices/references/patterns.md +0 -0
  249. /package/{assets → dist/pstack}/skills/unslop/SKILL.md +0 -0
  250. /package/{assets → dist/pstack}/skills/why/references/epistemics.md +0 -0
  251. /package/{assets → dist/pstack}/skills/why/references/investigator-prompt.md +0 -0
  252. /package/{assets → dist/pstack}/skills/why/references/source-playbook.md +0 -0
  253. /package/{assets → dist/pstack}/skills/why/references/sources/code-archaeology.md +0 -0
  254. /package/{assets → dist/pstack}/skills/why/references/sources/databricks.md +0 -0
  255. /package/{assets → dist/pstack}/skills/why/references/sources/datadog.md +0 -0
  256. /package/{assets → dist/pstack}/skills/why/references/sources/incident-postmortem.md +0 -0
  257. /package/{assets → dist/pstack}/skills/why/references/sources/linear.md +0 -0
  258. /package/{assets → dist/pstack}/skills/why/references/sources/notion.md +0 -0
  259. /package/{assets → dist/pstack}/skills/why/references/sources/sentry.md +0 -0
  260. /package/{assets → dist/pstack}/skills/why/references/sources/slack.md +0 -0
  261. /package/{assets → dist/pstack}/skills/why/references/synthesizer-prompt.md +0 -0
package/dist/skill.mjs ADDED
@@ -0,0 +1,183 @@
1
+ import { resolve, sep } from "node:path";
2
+ import { readFile } from "node:fs/promises";
3
+ // src/skill.ts
4
+ /**
5
+ * `pstack_skill`: the trusted skill loader for pstack's own instructions.
6
+ *
7
+ * pstack hides most of its skills from the model catalog: `how`, `why`, `architect`,
8
+ * `arena`, and the principle skills all declare `disable-model-invocation: true`, so
9
+ * `poteto-mode` cannot route to them through DSH's `skill` tool. The registry's
10
+ * `get()` is deliberately usable by trusted callers without that policy, which is the
11
+ * public seam this tool consumes. It accepts a skill name, not a path, so a call can
12
+ * only load a skill the package itself registered.
13
+ *
14
+ * The optional `resource` argument reads one file below the skill's directory. It is a
15
+ * convenience for the references and playbooks that live beside `SKILL.md`; the path is
16
+ * resolved and checked against the skill directory before reading, so `../` cannot
17
+ * escape it.
18
+ */
19
+ /** Model-facing tool name. */
20
+ const TOOL_NAME = "pstack_skill";
21
+ /** Cordis row name, used by Loader diagnostics. */
22
+ const name = "pstack-skill";
23
+ /** The tool registry and the skill registry. */
24
+ const inject = ["skills", "tools"];
25
+ const SKILL_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
26
+ /** Render one loaded skill in the canonical `<skill_content>` shape. */
27
+ function renderLoadedSkill(result) {
28
+ const lines = [`<skill_content name="${escapeAttr(result.name)}">`, "<skill_resources>"];
29
+ if (result.resourceBase === void 0) lines.push(`Resources for this skill are managed by provider "${escapeText(result.provider)}".`, "Load referenced resources only as needed.");
30
+ else if (result.resourceBase.kind === "directory") lines.push(`Base directory for this skill: ${escapeText(result.resourceBase.path)}`, "Resolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.");
31
+ else if (result.resourceBase.kind === "url") lines.push(`Base URL for this skill: ${escapeText(result.resourceBase.url)}`, "Resolve relative URLs mentioned by this skill against the base URL before using them. Load referenced resources only as needed.");
32
+ else lines.push(`Resources for this skill: ${escapeText(result.resourceBase.description)}`, "Load referenced resources only as needed.");
33
+ lines.push("</skill_resources>", "", "<skill_instructions>", result.content, "</skill_instructions>");
34
+ if (result.resource !== void 0) lines.push("", `<skill_resource path="${escapeAttr(result.resource.path)}">`, result.resource.content, "</skill_resource>");
35
+ lines.push("</skill_content>");
36
+ return lines.join("\n");
37
+ }
38
+ function escapeAttr(value) {
39
+ return value.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;");
40
+ }
41
+ function escapeText(value) {
42
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
43
+ }
44
+ /** Read one resource below a directory skill, refusing traversal and absolute paths. */
45
+ async function readSkillResource(definition, resource) {
46
+ const base = definition.resourceBase;
47
+ if (base === void 0 || base.kind !== "directory") throw new Error(`skill "${definition.name}" does not expose a directory resource base`);
48
+ if (resource.trim() === "" || resource.includes("\0")) throw new Error("resource must be a non-empty relative path");
49
+ if (resource.startsWith("/") || resource.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(resource)) throw new Error(`resource "${resource}" must be relative to the skill directory`);
50
+ const root = resolve(base.path);
51
+ const target = resolve(root, resource);
52
+ if (target !== root && !target.startsWith(root + sep)) throw new Error(`resource "${resource}" escapes the skill directory`);
53
+ try {
54
+ return {
55
+ path: resource,
56
+ content: await readFile(target, "utf8")
57
+ };
58
+ } catch (error) {
59
+ const code = error.code;
60
+ if (code === "ENOENT" || code === "EISDIR") throw new Error(`resource "${resource}" is not available for skill "${definition.name}"`);
61
+ throw error;
62
+ }
63
+ }
64
+ const OUTPUT_SCHEMA = {
65
+ type: "object",
66
+ additionalProperties: false,
67
+ properties: {
68
+ name: { type: "string" },
69
+ provider: { type: "string" },
70
+ resourceBase: { oneOf: [
71
+ {
72
+ type: "object",
73
+ additionalProperties: false,
74
+ properties: {
75
+ kind: {
76
+ type: "string",
77
+ const: "directory"
78
+ },
79
+ path: { type: "string" }
80
+ },
81
+ required: ["kind", "path"]
82
+ },
83
+ {
84
+ type: "object",
85
+ additionalProperties: false,
86
+ properties: {
87
+ kind: {
88
+ type: "string",
89
+ const: "url"
90
+ },
91
+ url: { type: "string" }
92
+ },
93
+ required: ["kind", "url"]
94
+ },
95
+ {
96
+ type: "object",
97
+ additionalProperties: false,
98
+ properties: {
99
+ kind: {
100
+ type: "string",
101
+ const: "opaque"
102
+ },
103
+ description: { type: "string" }
104
+ },
105
+ required: ["kind", "description"]
106
+ }
107
+ ] },
108
+ content: { type: "string" },
109
+ resource: {
110
+ type: "object",
111
+ additionalProperties: false,
112
+ properties: {
113
+ path: { type: "string" },
114
+ content: { type: "string" }
115
+ },
116
+ required: ["path", "content"]
117
+ }
118
+ },
119
+ required: [
120
+ "name",
121
+ "provider",
122
+ "content"
123
+ ]
124
+ };
125
+ const TOOL_DESCRIPTION = [
126
+ "Load the full instructions of any pstack skill by name, including skills hidden from the model catalog.",
127
+ "",
128
+ "Use this when a pstack skill tells you to route through another pstack skill (for example how, why, or architect) and the `skill` tool reports that it is unavailable because the skill disables model invocation.",
129
+ "",
130
+ "Pass `resource` with a path relative to the skill directory to read one reference or playbook beside its SKILL.md. The path cannot leave the skill directory."
131
+ ].join("\n");
132
+ /** Build the tool definition. Exported so tests can drive `execute` directly. */
133
+ function createPstackSkillTool(skills) {
134
+ return {
135
+ name: TOOL_NAME,
136
+ description: TOOL_DESCRIPTION,
137
+ parameters: {
138
+ type: "object",
139
+ additionalProperties: false,
140
+ properties: {
141
+ name: {
142
+ type: "string",
143
+ description: "Exact kebab-case skill name, such as `how` or `principle-prove-it-works`."
144
+ },
145
+ resource: {
146
+ type: "string",
147
+ description: "Optional path relative to the skill directory, such as `references/explorer-prompt.md`."
148
+ }
149
+ },
150
+ required: ["name"]
151
+ },
152
+ output: {
153
+ schema: OUTPUT_SCHEMA,
154
+ render: (_args, value) => [{
155
+ type: "text",
156
+ text: renderLoadedSkill(value)
157
+ }]
158
+ },
159
+ isConcurrencySafe: () => true,
160
+ async execute(rawArgs, exec) {
161
+ const args = rawArgs;
162
+ if (typeof args.name !== "string" || !SKILL_NAME.test(args.name)) throw new Error(`invalid skill name "${String(args.name)}"`);
163
+ if (args.resource !== void 0 && typeof args.resource !== "string") throw new Error("resource must be a string when present");
164
+ const definition = await skills.get(args.name, {
165
+ signal: exec.signal,
166
+ ...exec.agent === void 0 ? {} : { scope: exec.agent }
167
+ });
168
+ if (definition === void 0) throw new Error(`skill "${args.name}" is unknown or no longer available`);
169
+ return {
170
+ name: definition.name,
171
+ provider: definition.provider,
172
+ ...definition.resourceBase === void 0 ? {} : { resourceBase: definition.resourceBase },
173
+ content: definition.content,
174
+ ...args.resource === void 0 ? {} : { resource: await readSkillResource(definition, args.resource) }
175
+ };
176
+ }
177
+ };
178
+ }
179
+ /** Register `pstack_skill` on one row. */
180
+ function apply(ctx) {
181
+ ctx.tools.register(createPstackSkillTool(ctx.skills));
182
+ }
183
+ export { TOOL_NAME, apply, createPstackSkillTool, inject, name, readSkillResource, renderLoadedSkill };
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: decision-audit
3
+ description: Audit decision records against a change set or the whole repository; report routing, status, scope, anchor, supersession, and review findings with command evidence.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # Audit decision records
8
+
9
+ Produce a read-only report of records needing human attention, without judging whether code still honors a decision. Cite each finding with its command and observed output; leave every edit to `decision-write`.
10
+
11
+ ## 1. Resolve the inputs
12
+
13
+ Accept `mode` (`pr`, `local`, or `full`; default `pr`), optional `base`, and optional `scope` paths replacing the computed change set.
14
+
15
+ For `pr`, resolve the PR base; otherwise try `origin/main`. When absent, try `origin/master`, `main`, `master`, the newest tag, then `HEAD~20`. Report the selected ref, or stop and list every attempted ref.
16
+
17
+ Inspect `docs/decisions/`, `docs/adr/`, and `doc/adr/`:
18
+
19
+ - One exists: call it `<dir>` and report its path.
20
+ - Several exist: ask which is current and wait.
21
+ - None exists or it contains no records: report that normal result and stop.
22
+
23
+ ## 2. Collect the evidence
24
+
25
+ When `scope` is absent, compute the change set:
26
+
27
+ ```bash
28
+ # pr
29
+ git diff --name-only "$(git merge-base HEAD <base>)"..HEAD
30
+
31
+ # local: base-relative commits plus the working tree and index
32
+ git diff --name-only "$(git merge-base HEAD <base>)"..HEAD
33
+ git status --porcelain=v1 --untracked-files=all
34
+ ```
35
+
36
+ Decode `git status` paths, including the destination of a rename. For `full`, use all tracked files. Exclude lock files, generated files, snapshots, and pure assets from the computed set; record these exclusions and the final set.
37
+
38
+ Read `<dir>/AGENTS.md` and `<dir>/README.md` when present; these are conventions, not records. Apply their conventions to every other `*.md`. Parse each header through its first `## ` heading. List records missing any of `Status`, `Date`, `Scope`, `Implemented-by`, or `Review` separately as `Legacy`, exempt from all six checks.
39
+
40
+ Apply every applicable check to every current record; a record may have multiple findings.
41
+
42
+ ## 3. Apply all six checks
43
+
44
+ **A — Route.** For each non-`superseded` record whose `Scope` matches the change set, report its title, path, matched paths, and change-set evidence in one line.
45
+
46
+ **B — Status pair.** Use the anchor results below and report each matching row:
47
+
48
+ | Status | Anchor result | Finding |
49
+ |---|---|---|
50
+ | `proposed` | verified | Should be `accepted` |
51
+ | `accepted` | `-`, missing, pending, or unverified | Landing lacks verified evidence |
52
+
53
+ For `proposed`, `-` or a pending anchor is not a finding; an unverified anchor belongs in `Unverified`, outside B and C.
54
+
55
+ **B′ — Dead scope.** For each `accepted` record with no `Scope` glob matching an existing file, report its path and glob-check evidence. Ask whether the decision is obsolete or its scope is wrong.
56
+
57
+ **C — Broken anchor.** For each non-`superseded` `Implemented-by` value, classify it with evidence:
58
+
59
+ | Value | Verification | Result |
60
+ |---|---|---|
61
+ | `-` or missing | None | Pending |
62
+ | `PR #N` | `gh pr view N --json state,files` | `MERGED`: continue below; `OPEN`: pending; `CLOSED`: C; otherwise: unverified |
63
+ | `commit:SHA` | `git merge-base --is-ancestor SHA <base>` | Exit 0: continue below; exit 1: C; otherwise: unverified |
64
+ | Any value | Command unavailable, authentication fails, or object cannot be read | Unverified |
65
+
66
+ For a landed PR or ancestral commit, list its paths with `gh pr view N --json files --jq '.files[].path'` or `git show --pretty=format: --name-only SHA`. `Verified` requires a path matching `Scope` and at least one path outside `<dir>`; otherwise report C with the path evidence.
67
+
68
+ Before reporting a commit as lost, read [Recover a rewritten commit](references/recover-commit.md) and attempt patch-identity recovery while its object remains available.
69
+
70
+ **D — Overdue review.** In `full` mode only, report each record whose `Review` date is before the current date. Collect the changes since the decision date:
71
+
72
+ ```bash
73
+ date +%F
74
+ git log --since=<Date> --oneline -- <Scope paths>
75
+ ```
76
+
77
+ Include the count and latest subject when present; suggest human review and a new `Review` date.
78
+
79
+ **E — Superseded record.** For each current `superseded` record, report when `Superseded-by` is missing, does not resolve to a record in `<dir>`, or carries no ` — <reason>` text. Suggest adding the replacing record path and a one-line reason.
80
+
81
+ ## 4. Report and trim
82
+
83
+ Account for every current record as pending, clean, unverified, or carrying one or more findings. Order findings `C`, `B`, `B′`, `E`, `D`, `A`; within each class, put more matched files first.
84
+
85
+ - `pr`: at most 15 findings, followed by the omitted count.
86
+ - `local`: at most 8 findings, including at most 3 class-A findings.
87
+ - `full`: no trimming; report every class count, including zeroes.
88
+
89
+ Use this structure for findings; include `Evidence` for every class:
90
+
91
+ ```text
92
+ [C] Decision title
93
+ Record: docs/decisions/2026-08-14-use-postgres.md
94
+ Basis: commit:3f9a1c2 is not in history
95
+ Evidence: git merge-base --is-ancestor 3f9a1c2 origin/main -> exit 1
96
+ Suggest: replace the anchor with commit:8ff9f762 (matching patch-id d064e03f4e53)
97
+ ```
98
+
99
+ List `Legacy` and `Unverified` separately from findings. When nothing needs attention, say so in one line. An unavailable or unauthenticated `gh` leaves PR anchors unverified while the other checks continue.
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: decision-audit
3
+ description: 按改动集合或整个仓库审计决策记录,报告路由、状态、范围、锚点、取代与复核发现,并附命令证据。
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # 审计决策记录
8
+
9
+ 以只读方式报告需要人工关注的记录,不判断代码是否仍符合决策。每项发现都附上支持它的命令与实际输出;所有修改交给 `decision-write`。
10
+
11
+ ## 1. 确定输入
12
+
13
+ 接受 `mode`(`pr`、`local` 或 `full`,默认 `pr`)、可选的 `base`,以及用于替代计算所得改动集合的可选 `scope` 路径。
14
+
15
+ `pr` 解析 PR 基线,其他模式先尝试 `origin/main`。不存在时依次尝试 `origin/master`、`main`、`master`、最新 tag、`HEAD~20`。报告实际选中的 ref;全部无法解析时停止并列出每个尝试过的 ref。
16
+
17
+ 检查 `docs/decisions/`、`docs/adr/` 和 `doc/adr/`:
18
+
19
+ - 只有一个存在:记为 `<dir>` 并报告路径。
20
+ - 多个存在:询问哪个是当前目录并等待。
21
+ - 都不存在或没有记录:报告这一正常结果并停止。
22
+
23
+ ## 2. 收集证据
24
+
25
+ 未提供 `scope` 时计算改动集合:
26
+
27
+ ```bash
28
+ # pr
29
+ git diff --name-only "$(git merge-base HEAD <base>)"..HEAD
30
+
31
+ # local:相对基线的提交,加上工作区与暂存区
32
+ git diff --name-only "$(git merge-base HEAD <base>)"..HEAD
33
+ git status --porcelain=v1 --untracked-files=all
34
+ ```
35
+
36
+ 解析 `git status` 中的路径,重命名取目标路径。`full` 使用所有受 Git 跟踪的文件。从计算结果中剔除锁文件、生成文件、快照和纯资源文件;记录这些排除项与最终集合。
37
+
38
+ 存在 `<dir>/AGENTS.md` 和 `<dir>/README.md` 时读取;它们是约定而非记录。将其约定应用到其他所有 `*.md`。读取每条记录至第一个 `## ` 标题并解析头部。缺少 `Status`、`Date`、`Scope`、`Implemented-by`、`Review` 中任一项的记录单列为 `Legacy`,不参与以下六项检查。
39
+
40
+ 对每条现行记录执行所有适用的检查;同一记录可以产生多项发现。
41
+
42
+ ## 3. 执行全部六项检查
43
+
44
+ **A——路由。** 对每条非 `superseded` 且 `Scope` 匹配改动集合的记录,用一行报告标题、路径、匹配路径及改动集合证据。
45
+
46
+ **B——状态成对。** 使用下方的锚点结果,报告每个匹配行:
47
+
48
+ | Status | 锚点结果 | 发现 |
49
+ |---|---|---|
50
+ | `proposed` | 已核验 | 应改为 `accepted` |
51
+ | `accepted` | `-`、缺失、待落地或未核验 | 落地状态缺少已核验证据 |
52
+
53
+ `proposed` 带 `-` 或待落地锚点不是发现;带未核验锚点时归入 `Unverified`,不归入 B 或 C。
54
+
55
+ **B′——范围失效。** 对 `Scope` 中所有 glob 都不匹配现存文件的每条 `accepted` 记录,报告路径与 glob 检查证据,并询问是决策已过时还是范围写错。
56
+
57
+ **C——锚点断裂。** 对每条非 `superseded` 记录的每个 `Implemented-by` 值,按证据分类:
58
+
59
+ | 值 | 校验 | 结果 |
60
+ |---|---|---|
61
+ | `-` 或缺失 | 无 | 待落地 |
62
+ | `PR #N` | `gh pr view N --json state,files` | `MERGED`:继续下方检查;`OPEN`:待落地;`CLOSED`:C;其他:未核验 |
63
+ | `commit:SHA` | `git merge-base --is-ancestor SHA <base>` | 退出码 0:继续下方检查;1:C;其他:未核验 |
64
+ | 任意值 | 命令不可用、认证失败或对象无法读取 | 未核验 |
65
+
66
+ 对已合并 PR 或祖先提交,用 `gh pr view N --json files --jq '.files[].path'` 或 `git show --pretty=format: --name-only SHA` 列出路径。“已核验”要求至少一个路径匹配 `Scope`,且至少一个路径在 `<dir>` 之外;否则附路径证据报告 C。
67
+
68
+ 报告提交丢失前,读取[恢复被改写的提交](references/recover-commit.zh.md);只要其对象仍可用,就尝试恢复 patch 标识。
69
+
70
+ **D——复核逾期。** 仅在 `full` 模式,报告 `Review` 日期早于当前日期的每条记录,并收集决策日期以来的改动:
71
+
72
+ ```bash
73
+ date +%F
74
+ git log --since=<Date> --oneline -- <Scope paths>
75
+ ```
76
+
77
+ 附上提交数量和最新主题(如有),建议人工复核并更新 `Review` 日期。
78
+
79
+ **E——取代记录。** 对每条现行 `superseded` 记录,在 `Superseded-by` 缺失、无法解析到 `<dir>` 内的记录,或没有 ` — <原因>` 文本时报告。建议补上替代记录路径和一句原因。
80
+
81
+ ## 4. 报告与裁剪
82
+
83
+ 每条现行记录都必须归为待落地、无发现、未核验,或带一项或多项发现。按 `C`、`B`、`B′`、`E`、`D`、`A` 排列;同类中匹配文件更多的在前。
84
+
85
+ - `pr`:最多 15 项,随后给出省略数量。
86
+ - `local`:最多 8 项,其中 A 类最多 3 项。
87
+ - `full`:不裁剪,报告每类计数,包括零。
88
+
89
+ 各项发现使用以下结构;每一类都要包含 `Evidence`:
90
+
91
+ ```text
92
+ [C] Decision title
93
+ Record: docs/decisions/2026-08-14-use-postgres.md
94
+ Basis: commit:3f9a1c2 is not in history
95
+ Evidence: git merge-base --is-ancestor 3f9a1c2 origin/main -> exit 1
96
+ Suggest: replace the anchor with commit:8ff9f762 (matching patch-id d064e03f4e53)
97
+ ```
98
+
99
+ `Legacy` 与 `Unverified` 分别单列,不计为发现。无需关注时用一行说明。`gh` 缺失或未认证时,将 PR 锚点标为未核验,继续其他检查。
@@ -0,0 +1,17 @@
1
+ # Recover a rewritten commit
2
+
3
+ When an `Implemented-by: commit:SHA` is outside `<base>` but its object remains available, recover its patch identity before reporting it as lost:
4
+
5
+ ```bash
6
+ git show <dead-sha> | git patch-id --stable
7
+ ```
8
+
9
+ Search plausible replacements within the record's date and scope:
10
+
11
+ ```bash
12
+ git log --since=<Date> --format=%H -- <Scope paths> |
13
+ while read -r sha; do git show "$sha" | git patch-id --stable; done |
14
+ grep -F "<patch-id>"
15
+ ```
16
+
17
+ A match supports suggesting the replacement SHA; otherwise leave replacement to a human. Prefer PR anchors in squash-merged repositories.
@@ -0,0 +1,17 @@
1
+ # 恢复被改写的提交
2
+
3
+ `Implemented-by: commit:SHA` 不在 `<base>` 中、但其对象仍可用时,先恢复 patch 标识,再报告提交丢失:
4
+
5
+ ```bash
6
+ git show <dead-sha> | git patch-id --stable
7
+ ```
8
+
9
+ 在记录的日期与范围内搜索可能的替代提交:
10
+
11
+ ```bash
12
+ git log --since=<Date> --format=%H -- <Scope paths> |
13
+ while read -r sha; do git show "$sha" | git patch-id --stable; done |
14
+ grep -F "<patch-id>"
15
+ ```
16
+
17
+ 命中可支持建议改用替代 SHA;未命中则留给人判断替代项。使用 squash 合并的仓库优先采用 PR 锚点。
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: decision-write
3
+ description: Write, update, land, or supersede a decision record. Use for resolved alternatives, missing design rationale, reversed decisions, or any record-file change. Land discovers and verifies the implementation.
4
+ ---
5
+
6
+ # Write or update a decision record
7
+
8
+ Deliver one settled choice as a verified record and evidence report. All record edits go through this skill; `decision-audit` only reports.
9
+
10
+ ## Entry rule
11
+
12
+ Use this procedure for every change to `Status`, `Implemented-by`, `Superseded-by`, `Review`, body, or links. If it cannot run, stop and report; this rule overrides `<dir>/AGENTS.md` conventions permitting direct edits.
13
+
14
+ ## Locate the records
15
+
16
+ Inspect `docs/decisions/`, `docs/adr/`, and `doc/adr/`:
17
+
18
+ - One exists: call it `<dir>`, follow its naming convention, and read its `AGENTS.md` when present.
19
+ - Several exist: ask which is current and wait.
20
+ - None exists: report that this repository keeps no decision records, suggest `/setup-project-docs`, and stop.
21
+
22
+ `AGENTS.md` and `README.md` are conventions, not records; exclude both from searches, classification, and updates.
23
+
24
+ ## Choose the mode
25
+
26
+ - **Draft:** no record owns this decision, a new record replaces an old one, or an existing record needs substantive body or relationship updates. Duplicate and overlapping dispositions stay in Draft; explicit status-field updates use Land. Do steps 1–5, present the approval gate in step 6, then write only after confirmation and report with step 7.
27
+ - **Land:** the user explicitly asks to mark an existing record `accepted` or update its status fields. Do steps 4, 5, and 7. A record path plus `accepted` is sufficient input; never enter Land autonomously. Without a path, list records whose `Scope` matches the landed change and ask which to update.
28
+
29
+ ## 1. Establish the choice
30
+
31
+ Obtain all three from the change and discussion; ask only about missing items and wait:
32
+
33
+ - **Goal:** the problem this decision answers.
34
+ - **Constraint:** the boundary that eliminates an option.
35
+ - **Alternative:** an option actually rejected, or the explicit fact that only one candidate was considered.
36
+
37
+ ## 2. Find related records
38
+
39
+ Search for distinctive terms from the topic, affected modules, and alternatives:
40
+
41
+ ```bash
42
+ grep -ril --exclude=AGENTS.md --exclude=README.md \
43
+ -e "<keyword-1>" -e "<keyword-2>" <dir>/*.md
44
+ ```
45
+
46
+ Read each hit through its first `## ` heading; read the body only when the header cannot distinguish its disposition or cannot supply the content needed for an update. Tighten broad searches rather than reading the whole directory. Classify every hit:
47
+
48
+ - **Duplicate:** the existing record owns this decision. Update it instead of writing a second one.
49
+ - **Replaced:** draft the new record and cross-link both records. Include the old record's supersession in the approval gate.
50
+ - **Overlapping:** keep both, cross-link them, and reconcile changed facts.
51
+ - **Unrelated:** leave it unchanged.
52
+ - **Unresolved:** carry the relationship and human question into the report.
53
+
54
+ This step is complete when every hit has a disposition and every resulting edit is explicit.
55
+
56
+ ## 3. Draft the record
57
+
58
+ Follow `<dir>/AGENTS.md`, including heading language. In its absence, use:
59
+
60
+ ```markdown
61
+ # Decision: <one-line title>
62
+
63
+ Status: proposed | accepted | superseded
64
+ Date: YYYY-MM-DD
65
+ Scope: <glob>[, <glob>...]
66
+ Implemented-by: <PR #N | commit:SHA | ->
67
+ Review: YYYY-MM-DD
68
+ Superseded-by: <record path> — <one-line reason> (only when Status is superseded)
69
+
70
+ ## Background
71
+ ## Decision
72
+ ## Alternatives
73
+ ## Consequences
74
+ ```
75
+
76
+ Write `Background` independently of the chosen solution. For an accepted record, write `Decision` in the present tense. Give every considered alternative its own paragraph and rejection reason; when there was only one candidate, state that fact.
77
+
78
+ ## 4. Set status and verify the anchor
79
+
80
+ `Status` and `Implemented-by` are one pair. Select the row supported by evidence and write both fields together:
81
+
82
+ | Evidence | Status | Implemented-by |
83
+ |---|---|---|
84
+ | No verified landing anchor | `proposed` | `-` |
85
+ | `PR #N` is `MERGED` | `accepted` | `PR #N` |
86
+ | `commit:SHA` is an ancestor of the default branch | `accepted` | `commit:SHA` |
87
+ | Confirmed record-only exception | `accepted` | `commit:<record-commit>` |
88
+ | Replaced by a newer draft | `superseded` | Keep the existing value |
89
+
90
+ A new record stays `proposed` until it lands. `Implemented-by` identifies the implementing change, including an earlier implementation for a retrospective record; a record-only commit requires the confirmed exception. Prefer a merged PR in a squash-merged repository.
91
+
92
+ For Land without an anchor, or the record-only exception, read [Find and verify the implementation](references/land.md) before editing. For any other proposed anchor, use that reference's verification procedure without its discovery steps.
93
+
94
+ Resolve `<base>` as the repository's default branch and report the selected ref. Verify every anchor; unavailable evidence or an unresolved base leaves a new record `proposed` + `-`. If an existing `accepted` record's anchor fails verification, stop and report it rather than silently demoting it. Change only fields required by evidence; advancing `Review` alone leaves status unchanged.
95
+
96
+ When a new draft replaces an old record, set the old record to `superseded` in the same approved edit set, even when it was `accepted`. Keep its body and anchor, add the cross-link, and write `Superseded-by: <new record path> — <one-line reason>` below `Review`. Ask for a missing reason and wait. A `proposed` old record keeps `Implemented-by: -`.
97
+
98
+ ## 5. Check scope covers the change
99
+
100
+ Use caller-supplied `scope` paths when present. For Land with a verified implementing change, list its paths with:
101
+
102
+ ```bash
103
+ gh pr view N --json files --jq '.files[].path'
104
+ git show --pretty=format: --name-only SHA
105
+ ```
106
+
107
+ For the confirmed record-only fallback, skip this check and report the exception. For every other mode, collect base-relative commits and uncommitted changes:
108
+
109
+ ```bash
110
+ git diff --name-only "$(git merge-base HEAD <base>)"..HEAD
111
+ git status --porcelain=v1 --untracked-files=all
112
+ ```
113
+
114
+ Decode `git status` paths, including the destination of a rename. Require each new or updated record to match at least one selected path to a `Scope` glob. When none matches, ask whether to widen the glob or omit the record. Record matched paths for the report.
115
+
116
+ ## 6. Draft approval gate
117
+
118
+ For every Draft write, including a Duplicate update, present the complete resulting content of every new or updated record and every related-record disposition. Include each proposed supersession with its `Superseded-by` path and reason. Request explicit confirmation and wait. After confirmation, apply exactly the approved edits; a declined draft leaves every file unchanged.
119
+
120
+ ## 7. Report
121
+
122
+ Account for every search hit, changed record, relationship, anchor verification, scope match, and unresolved question. A `proposed` record awaiting landing needs a Land update after merge. Name any discovered implementation and its changed paths; mark a record-only anchor as a confirmed exception. Include every `Superseded-by` path and reason.
123
+
124
+ ```text
125
+ Record: docs/decisions/2026-10-27-use-postgres.md
126
+ Status: accepted
127
+ Related: 2026-03-02-mysql-setup.md -> overlapping, cross-linked
128
+ Anchor: PR #412 -> MERGED (gh pr view 412 --json state,files)
129
+ Scope: src/db/** matched src/db/client.ts
130
+ Open: none
131
+ ```