A notebook's lessons survive only if they are written into a tracked home before the decision lands, so landing a change now has three pieces. The contract: a "Landing a change" section in MAINTAINING.md and a fifth item in the UI definition of done. The labor: a harvest skill that inventories the notebook, names each file's kind and routes findings to the owning docs page, reasoning to the change's design.md, problems to issues.md and reusable tools to a tracked home. The gate: scripts/notebook-citations.sh, a git grep over what git would commit for the notebook's directory shape, which make lint runs after the program's own lint, and scripts/archive-gate.sh, which refuses an mv into the archive or an openspec archive while the check reports hits. The gate is one script that any harness calls with the command it is about to run; Claude Code reaches it through a PreToolUse hook and opencode through a plugin. Both checks live in scripts/ rather than the lint subcommand because they are repository hygiene, not part of the shipped program. The generated openspec-archive-change skill is not edited; the post-archive reminder carries the harvest step instead.
19 lines
849 B
TypeScript
19 lines
849 B
TypeScript
// opencode adapter for scripts/archive-gate.sh: before the bash tool runs,
|
|
// hand it the command and refuse the call with the gate's message when the
|
|
// gate refuses. The rule and the message live in the script, so every
|
|
// harness refuses the same archive for the same reason; Claude Code's
|
|
// adapter is .claude/hooks/archive-gate.sh.
|
|
import type { Plugin } from "@opencode-ai/plugin"
|
|
|
|
export const ArchiveGate: Plugin = async ({ $, directory }) => ({
|
|
"tool.execute.before": async (input, output) => {
|
|
if (input.tool !== "bash") return
|
|
const command = String(output.args?.command ?? "")
|
|
if (command === "") return
|
|
const result = await $`${directory}/scripts/archive-gate.sh ${command}`.nothrow().quiet()
|
|
if (result.exitCode !== 0) {
|
|
throw new Error(result.stderr.toString() || result.stdout.toString())
|
|
}
|
|
},
|
|
})
|