spexcode 0.4.0 → 0.4.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.
- package/README.md +37 -17
- package/package.json +9 -5
- package/spec-cli/README.md +23 -14
- package/spec-cli/hooks/dispatch.sh +7 -5
- package/spec-cli/hooks/harness.sh +19 -8
- package/spec-cli/src/anchors.ts +163 -30
- package/spec-cli/src/cli.ts +97 -42
- package/spec-cli/src/client.ts +34 -11
- package/spec-cli/src/doctor.ts +174 -36
- package/spec-cli/src/gateway-auth.ts +194 -0
- package/spec-cli/src/gateway-hub.ts +360 -0
- package/spec-cli/src/gateway.ts +31 -16
- package/spec-cli/src/git.ts +12 -5
- package/spec-cli/src/graph.ts +53 -36
- package/spec-cli/src/graphStream.ts +265 -34
- package/spec-cli/src/guide.ts +157 -76
- package/spec-cli/src/harness-select.ts +20 -6
- package/spec-cli/src/harness.ts +266 -67
- package/spec-cli/src/help.ts +84 -41
- package/spec-cli/src/host.ts +610 -0
- package/spec-cli/src/identity-presets.d.ts +13 -0
- package/spec-cli/src/identity-presets.js +128 -0
- package/spec-cli/src/index.ts +163 -86
- package/spec-cli/src/init.ts +53 -25
- package/spec-cli/src/layout.ts +5 -5
- package/spec-cli/src/lint.ts +115 -169
- package/spec-cli/src/login-page.ts +12 -5
- package/spec-cli/src/materialize.ts +39 -13
- package/spec-cli/src/mentions.ts +16 -11
- package/spec-cli/src/opencode.ts +145 -0
- package/spec-cli/src/pi-harness.ts +124 -0
- package/spec-cli/src/project-identity.ts +73 -0
- package/spec-cli/src/pty-bridge.ts +321 -521
- package/spec-cli/src/pty-helper.mjs +86 -0
- package/spec-cli/src/reaper.ts +16 -8
- package/spec-cli/src/reviewSnapshot.ts +23 -0
- package/spec-cli/src/reviews.ts +347 -0
- package/spec-cli/src/session-timeline.ts +162 -0
- package/spec-cli/src/sessions.ts +210 -63
- package/spec-cli/src/shim-runtime.ts +169 -0
- package/spec-cli/src/slash-commands.ts +76 -0
- package/spec-cli/src/source-files.ts +79 -0
- package/spec-cli/src/specs.ts +47 -24
- package/spec-cli/src/supervise.ts +37 -15
- package/spec-cli/src/tree.ts +8 -8
- package/spec-cli/src/uninstall.ts +56 -23
- package/spec-cli/templates/hooks/prepare-commit-msg +32 -13
- package/spec-cli/templates/spec/project/.plugins/{extract → commands/extract}/spec.md +24 -18
- package/spec-cli/templates/spec/project/.plugins/{regroup → commands/regroup}/spec.md +3 -3
- package/spec-cli/templates/spec/project/.plugins/commands/rename/spec.md +11 -0
- package/spec-cli/templates/spec/project/.plugins/commands/spec.md +30 -0
- package/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +8 -0
- package/spec-cli/templates/spec/project/.plugins/commands/tidy/spec.md +43 -0
- package/spec-cli/templates/spec/project/.plugins/core/idle/spec.md +1 -1
- package/spec-cli/templates/spec/project/.plugins/core/mark-active/spec.md +2 -0
- package/spec-cli/templates/spec/project/.plugins/core/session-fail/spec.md +1 -1
- package/spec-cli/templates/spec/project/.plugins/core/spec-first/spec-first.sh +28 -39
- package/spec-cli/templates/spec/project/.plugins/core/spec-first/spec.md +5 -3
- package/spec-cli/templates/spec/project/.plugins/core/spec-of-file/spec.md +1 -1
- package/spec-cli/templates/spec/project/.plugins/core/spec.md +2 -2
- package/spec-cli/templates/spec/project/.plugins/core/stop-gate/spec.md +7 -1
- package/spec-cli/templates/spec/project/.plugins/prompts/forge-link/spec.md +2 -2
- package/spec-cli/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +5 -5
- package/spec-cli/templates/spec/project/.plugins/prompts/spec.md +10 -6
- package/spec-cli/templates/spec/project/.plugins/skills/distill/spec.md +62 -0
- package/spec-cli/templates/spec/project/.plugins/skills/spec.md +19 -0
- package/spec-cli/templates/spec/project/.plugins/spec.md +17 -12
- package/spec-cli/templates/spec/project/spec.md +6 -5
- package/spec-cli/templates/spexcode.json +4 -2
- package/spec-dashboard/dist/assets/Dashboard-CiHh-gLD.js +27 -0
- package/spec-dashboard/dist/assets/EvalsPage-DmiX3rdU.js +2 -0
- package/spec-dashboard/dist/assets/IssuesPage-CIbVGRUJ.js +1 -0
- package/spec-dashboard/dist/assets/MobileApp-D-N9_eh0.js +2 -0
- package/spec-dashboard/dist/assets/Modal-DHMzSFJ4.js +1 -0
- package/spec-dashboard/dist/assets/PageScroll-C15adEYI.js +1 -0
- package/spec-dashboard/dist/assets/ProjectsPage-sQpzglp5.js +1 -0
- package/spec-dashboard/dist/assets/SessionInterface-6GBZ9nXN.css +32 -0
- package/spec-dashboard/dist/assets/SessionInterface-B8pGU7Rg.js +39 -0
- package/spec-dashboard/dist/assets/SessionWindow-CuDO_67z.js +13 -0
- package/spec-dashboard/dist/assets/Settings-C_N1wX1f.js +1 -0
- package/spec-dashboard/dist/assets/bindings-BC9vqpYU.js +1 -0
- package/spec-dashboard/dist/assets/index-DmWbmvCq.js +41 -0
- package/spec-dashboard/dist/assets/index-GGIVdKwH.css +1 -0
- package/spec-dashboard/dist/assets/terminalFont-DmTPNdbU.js +1 -0
- package/spec-dashboard/dist/index.html +10 -10
- package/spec-dashboard/src/reviewFilters.js +279 -0
- package/spec-dashboard/src/reviewQuery.js +174 -0
- package/spec-dashboard/src/session.js +167 -0
- package/spec-eval/src/cli.ts +80 -45
- package/spec-eval/src/evaltab.ts +4 -3
- package/spec-eval/src/humanok.ts +1 -1
- package/spec-eval/src/matrix.ts +693 -0
- package/spec-eval/src/scenarios.ts +116 -4
- package/spec-eval/src/sessioneval.ts +726 -66
- package/spec-cli/src/migrate-table.ts +0 -398
- package/spec-cli/src/migrate.ts +0 -386
- package/spec-cli/templates/spec/project/.plugins/distill/spec.md +0 -74
- package/spec-cli/templates/spec/project/.plugins/supervisor/spec.md +0 -8
- package/spec-cli/templates/spec/project/.plugins/tidy/spec.md +0 -25
- package/spec-dashboard/dist/assets/Dashboard-CTcH2eW9.js +0 -27
- package/spec-dashboard/dist/assets/EvalsPage-CJNKwHLN.js +0 -2
- package/spec-dashboard/dist/assets/FoldToggle-CVFbBpyW.js +0 -1
- package/spec-dashboard/dist/assets/IssuesPage-kULjonqj.js +0 -1
- package/spec-dashboard/dist/assets/MobileApp-B0ZJju8K.js +0 -1
- package/spec-dashboard/dist/assets/SessionInterface-BRKJqU2U.js +0 -71
- package/spec-dashboard/dist/assets/SessionInterface-DYP7pi_n.css +0 -32
- package/spec-dashboard/dist/assets/SessionWindow-CDhEL7wO.js +0 -9
- package/spec-dashboard/dist/assets/Settings-BL6FV_8S.js +0 -1
- package/spec-dashboard/dist/assets/index-DmQsNYKK.css +0 -1
- package/spec-dashboard/dist/assets/index-DulGPk6A.js +0 -41
- /package/spec-cli/templates/spec/project/.plugins/{distill → skills/distill}/digest.mjs +0 -0
|
@@ -10,6 +10,6 @@ block: false
|
|
|
10
10
|
---
|
|
11
11
|
A non-blocking per-edit annotation. The first time a session edits a given file, it names the spec node(s) that GOVERN that file — and, when a file is over-owned, flags that it is doing too much and points at the split — so the contract is in view at the very moment of the edit, not only later at commit or drift time.
|
|
12
12
|
|
|
13
|
-
It never renders a verdict: it only adds context, so it can inform without interrupting. It is deduplicated once per file via a session
|
|
13
|
+
It never renders a verdict: it only adds context, so it can inform without interrupting. Like [[spec-first]], spec-awareness is universal — it is NOT gated on `governed` and runs for any agent. It is deduplicated once per normalized repo-relative file via a ledger that lives as a sibling file in the session's global store dir (keyed by the payload's `session_id`), so a fifty-edit refactor annotates each file once rather than on every write — the discipline that keeps a pervasive signal from decaying into the noise it is meant to cure. It speaks only when there is something to say: a sanely-owned file draws silence, an over-owned or uncovered one draws the pointer. It only speaks for Git-relevant files inside the current repo: tracked files, plus new untracked files that are not ignored. Paths outside the repo, `.spec`, `.git`, and ignored artifacts stay silent.
|
|
14
14
|
|
|
15
15
|
This is the at-the-keystroke companion to the read-first gate [[spec-first]] and the commit-time checks: together they keep the [[core]] rule — code must not silently diverge from its spec — visible across the whole edit loop.
|
|
@@ -6,7 +6,7 @@ hue: 200
|
|
|
6
6
|
desc: A config plugin — the minimal spec-discipline contract folded into every launched agent.
|
|
7
7
|
code:
|
|
8
8
|
---
|
|
9
|
-
The CLI speaks ONE grammar: `spex <noun> <verb> [object] [flags]`. Six nouns — `spec` (the governance graph), `session` (the worktree state machine), `eval` (the measurement system), `issue` (concern threads), `remark` (resolvable pins), `evidence` (content-addressed bytes) — plus a few bare project verbs (`graph` · `init` · `materialize` · `doctor` · `serve` · `uninstall`) whose object is always this project. The verb is always the token right after its noun; a bare noun prints its drawer's help; a `--help` probe is always safe (it prints and exits before the verb runs). `SEL` = session id | unique id-prefix | node id | branch; `.` as a node argument = the node this worktree works on. When unsure of a spelling, ask the tool — `spex help`, `spex help <command>` — never guess from memory: removed spellings only report their replacement and exit.
|
|
9
|
+
The CLI speaks ONE grammar: `spex <noun> <verb> [object] [flags]`. Six nouns — `spec` (the governance graph), `session` (the worktree state machine), `eval` (the measurement system), `issue` (concern threads), `remark` (resolvable pins), `evidence` (content-addressed bytes) — plus a few bare project verbs (`graph` · `init` · `materialize` · `doctor` · `serve` · `uninstall`) whose object is always this project. The verb is always the token right after its noun; a bare noun prints its drawer's help; a `--help` probe is always safe (it prints and exits before the verb runs). `SEL` = session id | unique id-prefix | node id | branch; inside a session worktree, `.` as a session selector = that worktree's own session, while `.` as a node argument = the node this worktree works on. When unsure of a spelling, ask the tool — `spex help`, `spex help <command>` — never guess from memory: removed spellings only report their replacement and exit.
|
|
10
10
|
|
|
11
11
|
Four disciplines, non-negotiable:
|
|
12
12
|
|
|
@@ -16,6 +16,6 @@ Four disciplines, non-negotiable:
|
|
|
16
16
|
|
|
17
17
|
3. THE BODY IS A LIVING CURRENT-STATE DOCUMENT. It states the node's PRESENT intent and is rewritten in place. Never accrete a "## vN" changelog heading, and never add current-state or verdict sections — version history is git's job, not the body's.
|
|
18
18
|
|
|
19
|
-
4. KEEP THE LOSS SIGNAL HONEST for what you changed — eval readings are the signal the optimizer reads, so a gap is a blind spot. Changed a node that carries a `eval.md`? Re-measure it: run its scenario, compare to the expected, and file the result with `spex eval add <node>`.
|
|
19
|
+
4. KEEP THE LOSS SIGNAL HONEST for what you changed — eval readings are the signal the optimizer reads, so a gap is a blind spot. Changed a node that carries a `eval.md`? Re-measure it: run its scenario, compare to the expected, and file the result with `spex eval add <node>`. Match the evidence to the behaviour: a DYNAMIC scenario — anything that moves or is timed (terminal scroll/redraw, an animation or transition, media playback, a multi-step interaction flow) — records a video of the run and files it with `--video`; a STATIC end state screenshots with `--image`; a backend/CLI scenario files its transcript with `--result`. A still of a moving thing proves the wrong thing. File the reading only AFTER the change it measures is committed — a reading's `codeSha` anchors to HEAD at filing time, so verify on the working tree, commit the verified tree, then file; a dirty-tree filing names a commit that lacks your change. Made an obvious frontend change to a node with NO `eval.md`? Give it one — a scenario (description + expected) — so its loss can be measured. `spex eval lint --changed` shows the gaps in exactly the nodes you touched.
|
|
20
20
|
|
|
21
21
|
Don't reverse-engineer the file formats: `spex guide spec` and `spex guide eval` print the full spec.md and scenario schema on demand. This prompt is the clue; that manual carries the detail.
|
|
@@ -12,6 +12,12 @@ The blocking stop gate, with two jobs, each holding a hard loop-break so it neve
|
|
|
12
12
|
|
|
13
13
|
The COMMIT gate keeps a done/merge proposal honest: such a proposal is rejected while the branch still carries uncommitted work or is zero commits ahead of main, because the ritual commits the spec and code BEFORE proposing. Clean work is allowed to stop; a dirty proposal blocks once with the reason, and if the agent ignores it the gate escapes by downgrading to `asking` so a false "ready to merge" can never stand.
|
|
14
14
|
|
|
15
|
-
The DECLARE gate refuses to let a session stop in an undeclared `active` state, since a state is a claim the board and other agents act on, not a box ticked to end a turn. A declared state stops freely; an undeclared first stop
|
|
15
|
+
The DECLARE gate refuses to let a session stop in an undeclared `active` state, since a state is a claim the board and other agents act on, not a box ticked to end a turn. A declared state stops freely; an undeclared first stop emits `{"decision":"block"}` and the dispatcher exits 2 so the harness actually interrupts the stop and shows the reason; on the forced continuation it auto-declares a safe default — committed work becomes `awaiting`, otherwise `asking` — so the loop is guaranteed to end.
|
|
16
|
+
|
|
17
|
+
The block text is where the declaration ritual is taught, so it is written to be read at two depths. The FULL teaching text prints once per session: it names the PATH-independent CLI once as a shared prefix, lists the five choices as a compact menu each with its application condition (park policed hardest — a false park is the most damaging mislabel), and ends with the ordering discipline: declare LAST, then stop — a declaration followed by more tool calls honestly re-flips the record to active ([[mark-active]], by design), so making the declaration the turn's final call is what eliminates the park→block→re-park loop at its source. Every later undeclared stop in the same session gets a ONE-LINE version instead (a heavy session hits the gate 15-20 times a night; re-printing the full menu is token noise). The once-sentinel is a plain file beside the session record in the global store — the same per-session-sentinel mechanism as the CLI's note-truncation notice, never a second scheme. The terse line stays self-explanatory: it carries the command menu, the declare-LAST reminder, and the `spex help session` recovery entry, so an agent that never saw the full text (a compacted context) recovers every choice's condition from the entry rather than from memory — the whole full-to-terse information gap is closable from the line itself.
|
|
18
|
+
|
|
19
|
+
The clean-done eval nudge is advisory only and must never corrupt the Stop hook protocol. Claude-family hooks can receive it as `hookSpecificOutput.additionalContext`; Codex Stop allows are silent because Codex treats unsupported non-block stdout as invalid hook JSON. Blocking decisions stay shared across harnesses through `{"decision":"block"}` plus the dispatcher’s Codex stderr bridge.
|
|
20
|
+
|
|
21
|
+
Both gates act ONLY on a GOVERNED (dashboard-launched) session: the gate resolves the session's record in the global store from the payload's `session_id`, and on a non-governed (user-self-launched) record — or none — it exits 0 SILENTLY. A self-launched agent has no board to feed, so the declare-demand must never misfire on it. Its own state writes go through `spex session … --session <id>`, passing the id explicitly since there is no worktree file to read it from.
|
|
16
22
|
|
|
17
23
|
It is the enforcement edge of [[core]]: nothing leaves a session except as committed work under a truthful declaration. The freshness it reads is set by [[mark-active]].
|
|
@@ -3,7 +3,7 @@ title: forge-link
|
|
|
3
3
|
surface: system
|
|
4
4
|
status: active
|
|
5
5
|
hue: 280
|
|
6
|
-
desc: A config plugin — agents link an issue
|
|
6
|
+
desc: A config plugin — agents link an issue or change request opened through the resolved forge to the spec node it serves via one `Spec: <id>` body line.
|
|
7
7
|
code:
|
|
8
8
|
---
|
|
9
|
-
When you open
|
|
9
|
+
When you open an issue or change request through the repository's resolved forge, link it to the spec node(s) it serves by adding one line to its **body**: `Spec: <node-id>` (comma-separate several). The id is the node's **leaf** name — the folder under `.spec/…/<id>/spec.md`, e.g. `sessions`, never the slash-path. An unrecognized id silently links nothing, so use a real node id (`spex graph --json` lists them). This is the one linking marker on every forge.
|
|
@@ -3,16 +3,16 @@ title: reproduce-before-fix
|
|
|
3
3
|
surface: system
|
|
4
4
|
status: active
|
|
5
5
|
hue: 140
|
|
6
|
-
desc: A config plugin — a bug fix must first REPRODUCE the failure as a failing eval, then fix,
|
|
6
|
+
desc: A config plugin — a bug fix must first REPRODUCE the failure as a failing eval, then fix, verify, commit, and file the passing eval. The fail→pass pair on one scenario is the fix's proof (the A/B).
|
|
7
7
|
code:
|
|
8
8
|
---
|
|
9
9
|
## Reproduce before you fix — the fix's proof is a fail→pass pair
|
|
10
10
|
|
|
11
11
|
If your task is to FIX A BUG, reproduce it *first*, as a measurement — before you touch the fix. A claim that something is broken is worth nothing until the loss signal shows it broken; a claim that you fixed it is worth nothing until the same signal shows it passing. So a bug fix is bracketed by two readings of ONE scenario:
|
|
12
12
|
|
|
13
|
-
- **A — reproduce (fail).** Find the eval scenario whose expected the bug violates (if none fits, ADD one to the node's `eval.md` — a description + the expected correct behaviour), run it, and file the failing reading with evidence that SHOWS the bug: `spex eval add <node> --scenario <s> --fail --note "<what's wrong>"` plus an `--image`/`--video` of the actual broken behaviour. This is not ceremony — reproducing is how you learn what actually breaks, and a fix aimed at an unreproduced bug aims at a guess.
|
|
14
|
-
- **B — fix, then
|
|
13
|
+
- **A — reproduce (fail).** Find the eval-core scenario whose expected the bug violates (if none fits, ADD one to the node's `eval.md` — a description + the expected correct behaviour), run it, and file the failing reading with evidence that SHOWS the bug: `spex eval add <node> --scenario <s> --fail --note "<what's wrong>"` plus an `--image`/`--video` of the actual broken behaviour. This is not ceremony — reproducing is how you learn what actually breaks, and a fix aimed at an unreproduced bug aims at a guess.
|
|
14
|
+
- **B — fix, verify, commit, then file (pass).** Four moves, in order: make the code honor the spec; run the SAME scenario against your **working tree** until it actually passes — confidence is earned here, before any commit; **commit** the verified tree; only then file the passing reading, `spex eval add <node> --scenario <s> --pass`, so its `codeSha` names the very commit you measured (the sidecar append lands last, on top of it). Confidence and anchoring are two different acts: you test the uncommitted tree, but the reading's sha anchor can only land after the commit — this is NOT "commit first, then test" (blind commits with routine rollbacks are bad git). A git sha names only a commit and an uncommitted change has none, so a reading filed from a dirty tree is born mis-anchored — its `codeSha` is a HEAD that does not contain the change it claims to measure — and freshness later marking it stale is the mis-anchor being correctly exposed, not an engine bug. (A needs no such care: it measures the bug on the old, already-committed HEAD, so its anchor is honest as-is.)
|
|
15
15
|
|
|
16
|
-
The two readings on the same scenario are the **A/B** — the error→correct transition, the fix's proof-of-work. eval keeps per-scenario reading history, so the pair is durable and navigable end to end.
|
|
16
|
+
The two readings on the same scenario are the **A/B** — the error→correct transition, the fix's proof-of-work. eval already keeps per-scenario reading history, so the pair is durable and navigable end to end: the dashboard annotator flips between A (fail) and B (pass), and a trunk delivery (deliver-port) carries that pair as the evidence the fix is real. Don't skip A because the fix looks obvious — an obvious fix with no reproduced failure leaves the loss signal blind to exactly the regression you just closed.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
This does not apply to building new intent (there is no prior failure to reproduce) — it is the discipline for **repair**: keep the loss signal honest across a bug's whole lifecycle, not just at the end.
|
|
@@ -2,19 +2,23 @@
|
|
|
2
2
|
title: prompts
|
|
3
3
|
status: active
|
|
4
4
|
hue: 110
|
|
5
|
-
desc: Grouping shelf for the auxiliary `surface: system` prompt contracts — single-body always-on prose.
|
|
5
|
+
desc: Grouping shelf for the auxiliary `surface: system` prompt contracts — single-body always-on prose. Core is NOT a resident — the core contract subsystem is a direct `.plugins` child. A shelf, not a surface — routing stays field-driven per surface.
|
|
6
6
|
---
|
|
7
7
|
# prompts
|
|
8
8
|
|
|
9
9
|
The **auxiliary** `surface: system` prompt contracts live here: leaf plugins whose whole substance is one
|
|
10
10
|
prose body an agent must always carry — materialized (in name order, together with every other system
|
|
11
11
|
body) into the `<!-- spexcode -->` contract block — rather than a verb it invokes. Grouping them keeps
|
|
12
|
-
`.plugins/` legible at a glance: peripheral prompt contracts on this shelf; the
|
|
13
|
-
|
|
12
|
+
`.plugins/` legible at a glance: peripheral prompt contracts on this shelf; the command presets on
|
|
13
|
+
[[commands]], the skill plugins on [[skills]], and [[core]] as a flat child beside it.
|
|
14
14
|
|
|
15
15
|
The shelf boundary is **leafness, not surface**: a single-body prose contract shelves here, while a
|
|
16
|
-
contract that anchors its own subtree outranks the shelf —
|
|
17
|
-
are the `surface: hook` gates, is a *peer* of this shelf, never a resident.
|
|
16
|
+
contract that anchors its own subtree outranks the shelf — [[core]], the dev-flow contract subsystem
|
|
17
|
+
whose children are the `surface: hook` gates, is a *peer* of this shelf, never a resident.
|
|
18
18
|
|
|
19
19
|
This node is a **shelf, not a surface**: it declares no `surface` field and gathers nothing itself.
|
|
20
|
-
Discovery is recursive and field-driven, so residents plug in exactly as they would at the
|
|
20
|
+
Discovery is recursive and field-driven (surface), so residents plug in exactly as they would at the
|
|
21
|
+
root — nothing about materialization order (name order, unchanged names) or gathering changes with the
|
|
22
|
+
path. The init templates mirror this layout — a fresh `spex init` (per init-preset) seeds `core`
|
|
23
|
+
flat and its auxiliary system plugins under the same `prompts/` shelf. The shelf stays pure presentation:
|
|
24
|
+
changing this path changes neither a plugin's identity nor its gathered surface.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: distill
|
|
3
|
+
surface: skill, command
|
|
4
|
+
status: active
|
|
5
|
+
hue: 210
|
|
6
|
+
desc: Use when the user wants to inherit a finished, dead, or abandoned session — "distill session X / 继承那个 session 的经验 / 接手它的工作 / harvest or salvage a session". Given a SpexCode session id, harness thread id, or transcript path, read it without resuming, extract decisions, traps, and next actions, salvage unmerged work, retire only resources proven safe to remove, then rename the inheriting session to mark the handoff.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# distill
|
|
10
|
+
|
|
11
|
+
Inherit a finished session's **mind and desk** without waking it: mind is its transcript; desk is its
|
|
12
|
+
worktree and branch. **Never resume, reopen, send to, or otherwise re-prompt the old session.** Read files
|
|
13
|
+
and git state only until its work has landed.
|
|
14
|
+
|
|
15
|
+
## Resolve and digest
|
|
16
|
+
|
|
17
|
+
Accept a SpexCode session id, a Claude/Codex thread id, or a transcript `.jsonl` path.
|
|
18
|
+
|
|
19
|
+
- For a SpexCode id, find `~/.spexcode/projects/*/sessions/<id>/session.json` (a unique prefix is enough).
|
|
20
|
+
Keep its prompt, `worktree_path`, `branch`, `harness`, and `harness_session_id`; Claude uses the session
|
|
21
|
+
id as its transcript id, while Codex uses `harness_session_id`.
|
|
22
|
+
- Otherwise pass the harness id or transcript path directly. The digest header supplies its `cwd` and branch
|
|
23
|
+
when recorded; those locate the desk even when it belongs to another repository.
|
|
24
|
+
|
|
25
|
+
From the repository root run the plugin's co-located digest:
|
|
26
|
+
|
|
27
|
+
`node .spec/*/.plugins/skills/distill/digest.mjs <id-or-path>`
|
|
28
|
+
|
|
29
|
+
It searches the harness's normal local transcript stores and prints human prompts, agent text, concise tool
|
|
30
|
+
calls, errors, metadata, edited files, and the raw path. A miss fails loudly; never recover by waking the old
|
|
31
|
+
session. For output above about 100 KB, have a subagent return only the distillation below.
|
|
32
|
+
|
|
33
|
+
## Distill forward
|
|
34
|
+
|
|
35
|
+
Do not paste the transcript or retell changes git already records. Preserve what git does not:
|
|
36
|
+
|
|
37
|
+
- goal, actual stopping point, and whether anything landed;
|
|
38
|
+
- decisions and rejected alternatives, with reasons;
|
|
39
|
+
- failures, dead ends, and user corrections;
|
|
40
|
+
- unfinished work and next actions;
|
|
41
|
+
- edited files, relevant spec nodes, and the raw transcript path.
|
|
42
|
+
|
|
43
|
+
## Salvage, then retire
|
|
44
|
+
|
|
45
|
+
Use the record or digest to inspect the old repository's worktree, branch, merge base, commits, dirty files,
|
|
46
|
+
and untracked files. Cross-check the digest's edited-file list because some work may live outside that
|
|
47
|
+
worktree. Distinguish an already-merged branch from a branch equal to its merge base, which never committed.
|
|
48
|
+
|
|
49
|
+
Carry unmerged commits onto the current branch with `git cherry-pick <base>..<branch>`; if replay is
|
|
50
|
+
unsuitable, apply the branch diff. Apply dirty changes and copy needed untracked files, then commit them
|
|
51
|
+
with the source session named. Keep authorship and `Session:` trailers where possible.
|
|
52
|
+
|
|
53
|
+
Only after verifying the salvage is present (or the branch truly merged), retire a SpexCode session with
|
|
54
|
+
`spex session close <id>`, or remove a bare worktree and then its branch. If proof is incomplete, keep the
|
|
55
|
+
resources and report why.
|
|
56
|
+
|
|
57
|
+
## Rename yourself
|
|
58
|
+
|
|
59
|
+
Last step: mark the inheritance on the board. If you run as a SpexCode session (inside a session
|
|
60
|
+
worktree), `spex session rename . "<name>"` — `.` selects this worktree's own session. Name what this
|
|
61
|
+
session now carries — the inherited goal going forward, not the old session's id and no `distill:`
|
|
62
|
+
prefix. Outside a SpexCode session there is nothing to rename; skip this step.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: skills
|
|
3
|
+
status: active
|
|
4
|
+
hue: 280
|
|
5
|
+
desc: Grouping shelf for the `surface: skill` plugins — the harness skills an agent invokes on demand. A shelf, not a surface — routing stays field-driven per surface.
|
|
6
|
+
---
|
|
7
|
+
# skills
|
|
8
|
+
|
|
9
|
+
The invocable **skill** plugins live here: leaf plugins that materialize into the harness's skill dir,
|
|
10
|
+
where an agent invokes them on demand, each carrying `surface: skill`. Grouping them keeps `.plugins/`
|
|
11
|
+
legible at a glance — the skill plugins on this shelf, the command presets on [[commands]], the auxiliary
|
|
12
|
+
system contracts on [[prompts]], with [[core]] a flat child beside them.
|
|
13
|
+
|
|
14
|
+
This node is a **shelf, not a surface** (the [[prompts]] shape): it declares no `surface` field and
|
|
15
|
+
gathers nothing itself. Discovery is recursive and field-driven (surface), so a resident plugs in
|
|
16
|
+
exactly as it would at the root. A plugin that serves BOTH surfaces — [[distill]] is skill and command —
|
|
17
|
+
shelves here by its primary (skill) identity and still gathers as a command through its field. The init
|
|
18
|
+
templates mirror this layout. The shelf stays pure presentation: moving a resident beneath it changes
|
|
19
|
+
neither that plugin's identity nor the surfaces gathered from its frontmatter.
|
|
@@ -2,17 +2,22 @@
|
|
|
2
2
|
title: .plugins
|
|
3
3
|
status: active
|
|
4
4
|
hue: 110
|
|
5
|
-
desc: The instance home —
|
|
5
|
+
desc: The instance home — SpexCode's DIY dev-flow plugins live here as skill-shaped plugin nodes.
|
|
6
6
|
---
|
|
7
|
-
`.plugins/` is the **instance** of the plugin system: the concrete dev-flow plugins
|
|
8
|
-
working in
|
|
9
|
-
co-located scripts) — carrying a `surface: command|system|…` field that names where it plugs in
|
|
10
|
-
Discovery is recursive
|
|
11
|
-
`surface: system` prompt contracts live under
|
|
12
|
-
|
|
13
|
-
children
|
|
7
|
+
`.plugins/` is the **instance** of the plugin system: the concrete dev-flow plugins SpexCode ships for
|
|
8
|
+
working in this repo. Each plugin is a skill-shaped node — its folder *is* the unit (a `spec.md` plus any
|
|
9
|
+
co-located scripts) — carrying a `surface: command|system|…` field that names where it plugs in, per
|
|
10
|
+
plugin-system's surface field-driven routing. Discovery is recursive, so a plugin may sit under a
|
|
11
|
+
grouping shelf: the auxiliary `surface: system` prompt contracts live under [[prompts]], the `surface:
|
|
12
|
+
command` presets under [[commands]], the `surface: skill` plugins under [[skills]], the `surface: review`
|
|
13
|
+
remark presets under review, while [[core]] — the dev-flow contract subsystem whose children are the
|
|
14
|
+
`surface: hook` gates — sits as a flat child beside them.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
`/api/plugins` and the launcher's system gather read from here, not from plugin-system (which holds the
|
|
17
|
+
*spec of the plugin system* itself). Only **built/active** plugins gather — a `pending` node is declared
|
|
18
|
+
intent, not yet an active plugin, so it renders on the board but is neither offered as a command preset nor
|
|
19
|
+
materialized into the agent's contract.
|
|
20
|
+
|
|
21
|
+
Which plugins `spex init` ships is the init-preset rule. `seed: false` excludes a plugin subtree; shared
|
|
22
|
+
plugins have one body and one helper set — there is no separately authored adopter variant. Dogfood eval
|
|
23
|
+
scenarios/readings remain with the implementation and git history they measure.
|
|
@@ -12,8 +12,9 @@ made it. This node is the founding spec everything else hangs from — **rewrite
|
|
|
12
12
|
your own project**, then grow child package/feature nodes beneath it (each its own directory with a
|
|
13
13
|
`spec.md`).
|
|
14
14
|
|
|
15
|
-
`.plugins/` holds the dev-flow plugins this instance ships —
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
remove plugins by editing those
|
|
15
|
+
`.plugins/` holds the dev-flow plugins this instance ships — spec-shaped child nodes whose `surface`
|
|
16
|
+
field says how they enter the product. The initialized set includes always-on `system` contracts,
|
|
17
|
+
lifecycle `hook` handlers, new-session `command` presets, and an on-demand `skill`; one plugin may serve
|
|
18
|
+
more than one surface. Grouping shelves carry no surface themselves, and discovery is recursive, so the
|
|
19
|
+
folder layout stays readable without deciding behavior. Add, edit, or remove plugins by editing those
|
|
20
|
+
spec nodes.
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
},
|
|
5
5
|
"sessions": {
|
|
6
6
|
"launchers": {
|
|
7
|
-
"claude": { "harness": "claude", "cmd": "claude
|
|
8
|
-
"codex": { "harness": "codex", "cmd": "codex
|
|
7
|
+
"claude": { "harness": "claude", "cmd": "claude" },
|
|
8
|
+
"codex": { "harness": "codex", "cmd": "codex" },
|
|
9
|
+
"opencode": { "harness": "opencode", "cmd": "opencode" },
|
|
10
|
+
"pi": { "harness": "pi", "cmd": "pi" }
|
|
9
11
|
},
|
|
10
12
|
"defaultLauncher": "claude"
|
|
11
13
|
}
|