@jaybeeuu/agent-cortex 2.8.0 → 2.9.0

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 (41) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/README.md +26 -3
  3. package/agents/README.md +2 -2
  4. package/agents/guppi/agent.md +162 -0
  5. package/agents/guppi/claude/frontmatter.json +6 -0
  6. package/agents/guppi/pi/frontmatter.json +6 -0
  7. package/agents/plan/agent.md +6 -0
  8. package/agents/ralph-plan/agent.md +6 -0
  9. package/bin/installers/claude.mjs +1 -20
  10. package/bin/installers/pi.mjs +8 -2
  11. package/extensions/interrupt-bookmark/README.md +129 -0
  12. package/extensions/interrupt-bookmark/index.test.ts +717 -0
  13. package/extensions/interrupt-bookmark/index.ts +354 -0
  14. package/extensions/interrupt-bookmark/package.json +20 -0
  15. package/extensions/skill-stats/README.md +84 -3
  16. package/extensions/skill-stats/index.ts +62 -3
  17. package/extensions/skill-stats/package.json +1 -1
  18. package/extensions/skill-stats/rollup.test.ts +643 -0
  19. package/extensions/skill-stats/rollup.ts +415 -0
  20. package/extensions/skill-stats/timeline.ts +101 -0
  21. package/package.json +1 -1
  22. package/scripts/lib/manifest.mjs +29 -0
  23. package/skills/review/review-defects/EXAMPLES.md +80 -4
  24. package/skills/review/review-defects/SKILL.md +45 -15
  25. package/skills/review/review-report/EXAMPLES.md +114 -0
  26. package/skills/review/review-report/SKILL.md +138 -0
  27. package/skills/review/review-report/scripts/report.mjs +1032 -0
  28. package/skills/workflow/hitl-queue/SKILL.md +134 -0
  29. package/skills/workflow/hitl-queue/scripts/queue.mjs +626 -0
  30. package/skills/workflow/plan/SKILL.md +13 -0
  31. package/skills/workflow/prioritise-work/CHALLENGE.md +139 -0
  32. package/skills/workflow/prioritise-work/SKILL.md +150 -0
  33. package/skills/workflow/prioritise-work/scripts/challenge.mjs +505 -0
  34. package/skills/workflow/prioritise-work/scripts/strategy.mjs +566 -0
  35. package/skills/workflow/prioritise-work/templates/strategy.md +61 -0
  36. package/skills/workflow/run-pipeline-stage/playbooks/review.md +5 -2
  37. package/skills/workflow/score-bead/FORMAT.md +73 -0
  38. package/skills/workflow/score-bead/SKILL.md +112 -0
  39. package/skills/workflow/score-bead/scripts/rice.mjs +664 -0
  40. package/skills/workflow/using-agent-skills/SKILL.md +6 -1
  41. package/token-map.json +8 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,178 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7bdeb85: Extend the closed `defect:<class>` vocabulary in `review-defects` with four classes, so a reviewer
8
+ never has to force-fit a finding into a class that does not describe it.
9
+
10
+ `defect:unsafe-instruction` covers shipped text that, followed on an arbitrary machine, could
11
+ destroy data or run something dangerous: destructive commands, force-pushes, credential handling,
12
+ overwriting user config. `defect:ambiguous-rule` covers wording a reasonable agent reads two ways,
13
+ especially a phrase true of one context that reads as true of another. `defect:silent-degradation`
14
+ covers a path that fails quietly or passes vacuously: a skipped check reported as success, a null
15
+ mapping silently dropping a token, a guard that cannot fail. `defect:unclassified` is the escape
16
+ hatch for a finding that matches no class.
17
+
18
+ The table gains a **Distinct from** column, because the near neighbours are where a misclassification
19
+ happens: drift is _stale_, while ambiguity is _readable two ways_; `test-cannot-fail` is one
20
+ assertion that cannot bite, while silent degradation is any path that cannot report.
21
+
22
+ `defect:unclassified` carries an obligation rather than being a pass: the reviewer says no class
23
+ fits in the rejection text, files a bead proposing the class with the finding as its case, and names
24
+ that bead. Without the gap bead the label degrades the aggregate silently, which is the failure the
25
+ class exists to prevent. The vocabulary stays closed — a class is added by changing the skill with
26
+ the owner, never invented inside a review.
27
+
28
+ `review-report` gains an owning-skill mapping for the four classes (the authoring skill for unsafe
29
+ and ambiguous text, the test and stage skills for a quiet path, and `review-defects` itself for an
30
+ unclassified finding), and `review-defects` gains one real worked example per new class.
31
+
32
+ - 754e0eb: Add the **guppi** agent — the human-in-the-loop counterpart to ralph. It is a resident,
33
+ propose-only collaborator that decides what gets planned, loads `prioritise-work`, `plan`,
34
+ `hitl-collab`, `grill-me` and `flesh-out-idea` on demand, and never executes AFK work, merges or
35
+ pushes. `using-agent-skills` now routes "what should I work on" and HITL collaboration to guppi,
36
+ and `plan` cross-references it as the entry point that decides what gets planned.
37
+ - 1c786be: Add guppi's **interrupt protocol**: checkpoint, record, rewind, resume. guppi takes a resume point at
38
+ the last clean boundary, records the interruption as the bead type its content implies — a meeting
39
+ note becomes an idea or task bead through `record-idea`/`create-task`, PR feedback for ralph becomes a
40
+ task bead through `create-task` carrying the pull request's reference (with a `handoff` document
41
+ through `hitl-collab` when a human must act on it, and no peer message at all, because ralph reads the
42
+ bead from the tracker), a Slack todo becomes a task bead through `create-task`, and a question only a
43
+ human can answer becomes an `execution:hitl` decision bead — rewinds to the checkpoint, and resumes
44
+ with one sentence naming the task and the recorded bead. The record completes before the rewind, so a
45
+ failed record is never lost; a failed rewind continues in the current context and says so rather than
46
+ silently carrying the interruption. Nothing is written to a scratch file and no branch is deleted —
47
+ the abandoned branch is the audit trail. The rewind mechanism is forked through the existing
48
+ `interrupt_rewind` token row (`interrupt_resume` on pi, `/rewind` on claude), so the four-step prose
49
+ is byte-identical across harnesses; `test/guppi-interrupt-render.test.mjs` stages both installs to
50
+ prove it.
51
+ - fde0b9e: Make clearing the context safe in the **guppi** agent: write memory first, then recover the theme
52
+ from the tracker.
53
+
54
+ guppi now requires a memory write before any clear — what was decided and why, what is open, and
55
+ what the next session needs — into both the bead trail (`bd note`) and `bd remember` under a
56
+ `--key` naming the theme. `bd remember` stores into the workspace's own tracker database, so the
57
+ memory is already project-scoped; the key is a theme slug, and re-storing under it updates the
58
+ memory in place rather than accumulating stale copies.
59
+
60
+ The recovery rule states the exact read sequence — `bd prime` for the memories, `bd children
61
+ <epic>` for the theme, `bd show` per child for the trail, `bd provenance log` for the refs — so a
62
+ fresh session reconstructs a theme's state without a transcript.
63
+
64
+ Both rules are written against **"a clear"**, not against a command name: `/clear` is named as
65
+ today's mechanism and the self-flushing clear as its intended replacement, so the rules survive the
66
+ mechanism changing. A clear with no memory write is stated as a defect the agent names rather than
67
+ performing silently.
68
+
69
+ - 40598b9: Add the `interrupt-bookmark` extension: two tools around pi's own tree navigation, so an interruption
70
+ stops dragging its turns into the context the original task then has to carry. `interrupt_checkpoint`
71
+ returns the current leaf id as a resume point. `interrupt_resume { checkpointId, summary }` rewinds
72
+ there, keeps the abandoned branch under a branch summary labelled `interrupt`, and reports the summary
73
+ entry. The summary comes from pi's own navigation summariser — the extension makes no model call and
74
+ deletes nothing. Navigation is command-only in pi (`waitForIdle()` and `navigateTree()` live on
75
+ `ExtensionCommandContext`; a tool call is always inside a streaming turn), so the resume tool
76
+ validates the request, ends the turn, and an `agent_settled` handler dispatches the command that
77
+ rewinds — the pattern pi documents for a tool that must reach a command-only API. An unknown
78
+ checkpoint id fails naming the id and writes nothing; navigation is retried exactly once after a
79
+ fresh wait for idle, and a second failure reports the reason and leaves the conversation unchanged.
80
+ `token-map.json` gains the `interrupt_rewind` row — `interrupt_resume` on pi, Claude Code's `/rewind`
81
+ command on claude — with a note recording why the two values differ in kind and why the checkpoint
82
+ half is never tokenised.
83
+ - 05573b2: Add the `prioritise-work` skill, the `strategy.md` template it copies, and the `strategy.mjs` script
84
+ that validates and versions it. The strategy is a committed file in the consuming repository's
85
+ working-docs root (`.agent-cortex/working-docs/strategy.md`, overridable with `--file`), never a bead
86
+ and never a scratch note — the skill performs no tracker writes at all. `init` writes the template
87
+ stamped with the creation date and refuses to overwrite; `validate` checks a positive-integer version,
88
+ a `YYYY-MM-DD` calendar date, and five required sections — themes, value, confidence, out-of-scope and effort
89
+ calibration — naming each missing, empty or malformed one, and prints the rubric to stdout only when
90
+ the file passes, so a scorer can never read a stale or malformed rubric; `bump` refuses an invalid
91
+ file, raises the version by one and records today's date. The five interview questions map one-to-one
92
+ onto the five sections, and `using-agent-skills` routes ranking questions to the new skill.
93
+ - c77cb17: Treat a challenged priority as a strategy review, never a silent reorder. `prioritise-work` gains
94
+ `CHALLENGE.md` — the sequence from "this should be higher" to a changed rubric — and a second
95
+ script, `challenge.mjs record`, which refuses the tempting shortcut: an order that moved while the
96
+ strategy version stayed put exits 1 and writes nothing. It reads the strategy through the same
97
+ validator, diffs the ranked ids by position so the movement is deterministic, and prints one
98
+ bead-trail entry in `run-pipeline-stage`'s trail shape, carrying the words that raised the
99
+ challenge and the reasoning that answered it — including when the answer is "no change to the
100
+ rubric", which is a valid outcome that must still leave a trace. `--out <path>` writes that entry
101
+ to a file, so the documented append is `bd note <bead> --file <path>`: the entry repeats the human's
102
+ own words, and a shell string would parse them. `strategy.mjs bump` now requires
103
+ `--reason` and appends `- <date> v<n>: <reason>` to the strategy file's new `## Change log`
104
+ section, and `validate` fails when the newest entry names a version the header does not, so a
105
+ version cannot move without a recorded reason.
106
+ - f2f68c8: Add the `hitl-queue` skill: one command ranks the open `execution:hitl` beads by RICE ×
107
+ (1 + ln(1 + transitively blocked dependents)) × 1.5 when in progress, printing every row's
108
+ components, multipliers and what each answer unblocks. The `plan` skill, the `plan` agent and the
109
+ `ralph-plan` agent report that queue before dispatching or proposing anything.
110
+ - c644523: Add the `review-report` skill: one report from the `defect:<class>` labels a project's reviews
111
+ applied. `scripts/report.mjs` reads the tracker twice, both read-only and both with `--all` — the
112
+ defect query `bd list --label-pattern 'defect:*' --all` and the chore tree — and prints the top three
113
+ classes with counts, two example bead ids and the shipped skill that owns each failing rule, the
114
+ first-pass review rate derived from `stage:review` chore counts per parent, fix rounds grouped by the
115
+ stage the fresh chore re-runs, and the change against a report kept at `--baseline`. The class
116
+ vocabulary is not duplicated: the script parses the closed list out of `review-defects/SKILL.md`, so a
117
+ class that appears as a label without being in that table is reported as vocabulary drift and never
118
+ counted. Filing is a separate `--file` step that runs `gh issue create` with an argv array; without
119
+ the flag the script makes no network call, and it never pushes, opens a pull request or merges. The
120
+ feedback repository is configuration — `--repo`, then `AGENT_CORTEX_FEEDBACK_REPO`, then the
121
+ `repository` field of the manifest the running install ships (the staged pi package's
122
+ `package.json`, whose manifest now carries that field, or the staged Claude plugin's
123
+ `plugin.json`) — so no repository is hardcoded, a consuming project's own manifest is never used,
124
+ and a copy with no resolvable manifest fails with a message instead of filing somewhere wrong.
125
+ The report is printed before the filing target is resolved, so that failure leaves the measurement
126
+ on stdout and the reason on stderr. Absent data
127
+ is never dressed as a measurement: no label, a single label, no review chore and no baseline each get
128
+ a sentence saying so rather than a zero or a trend. `review-defects` gains a link to it.
129
+ - ba52582: Add the `score-bead` skill and its `rice.mjs` script: RICE scoring for one bead, stored in
130
+ tracker metadata, with priority banding kept as a separate reviewable step.
131
+
132
+ `score <id> --reach --impact --confidence --effort --rationale` computes
133
+ `reach × impact × confidence ÷ effort` to one decimal and writes
134
+ `{"rice":{"reach","impact","confidence","effort","score","strategyVersion","assessedAt","rationale"}}`
135
+ with `bd update <id> --metadata`, so `bd show` renders components and total side by side and a
136
+ reader can redo the arithmetic. The strategy is read through `prioritise-work`'s validator and
137
+ path resolver — one definition of a valid rubric, one location, `--file` still honoured — and the
138
+ recorded `strategyVersion` is the file's own version, read after it validated. A missing or
139
+ invalid strategy refuses the score before the first `bd` call, so a refusal writes nothing at
140
+ all; a component outside its range (`confidence` outside `0..1`, `effort` at zero) is refused the
141
+ same way.
142
+
143
+ Re-scoring keeps history: the rationale carries the current argument followed by one `[prior]`
144
+ line per replaced score — old total, components, strategy version and date — so a version bump
145
+ records the new version without discarding the old arithmetic.
146
+
147
+ `band <id>` is read-only. It prints the priority the score implies plus the `bd update` command
148
+ that would apply it, and the skill applies that command only after a reviewer accepts it. P0 is
149
+ never produced by a band, and a bead already at P0 is refused before a proposal exists.
150
+
151
+ `using-agent-skills` routes scoring and banding questions to the new skill.
152
+
153
+ - e1f5768: Add long-range retention to the `skill-stats` extension: keep low-fidelity data for a long time and
154
+ high-fidelity data for a short time. Usage is now also recorded into a per-day, per-skill rollup
155
+ (loaded / invoked / read counts plus the distinct projects seen that day) in
156
+ `~/.pi/agent-cortex/skill-usage-daily.json`, pruned to a 365-day window on every write and overridable
157
+ with `AGENT_CORTEX_SKILL_STATS_RETENTION_DAYS`. `/skill-stats timeline` renders per-day, per-week and
158
+ per-month counts and distinct skills from the rollups alone — no session-transcript scan. History that
159
+ predates the rollups is reported as unavailable rather than zero-filled, and a transcript backfill is
160
+ deliberately left out. The existing counters, the 200-event ring, the `/skill-stats` report output and
161
+ `/skill-usage-reset`'s confirmation flow are unchanged; the reset now also clears the rollups. Each
162
+ record is fixed-size — counts, at most 50 project paths per skill-day, each path truncated to 120
163
+ characters — and `saveRollups` enforces a hard 2,920,000-byte ceiling on every write (365 days x 40
164
+ skills x 200 bytes per skill-day). A write that would exceed it drops the per-skill-day project lists
165
+ first, keeping every count and every day, and drops the oldest days only if the counts alone exceed
166
+ the ceiling; `saveRollups` returns what it gave up. Every shed is also recorded in the file (a
167
+ `"shed"` key holding the running totals and the day of the most recent shedding write) and
168
+ `/skill-stats timeline` renders it, so
169
+ the user is told which project lists and how many days went instead of losing them silently. When a
170
+ shed drops whole days `since` moves to the oldest day the file still holds, so the header never claims
171
+ a day that was deleted; days that merely age out of the retention window keep the first-ever `since`.
172
+ A rollup file written before the `"shed"` key existed still loads and renders unchanged. The suite
173
+ fills every cap at once, asserts 22,033,268 raw bytes are written as at most 2,920,000, and asserts a
174
+ second year of data leaves the file unchanged.
175
+
3
176
  ## 2.8.0
4
177
 
5
178
  ### Minor Changes
package/README.md CHANGED
@@ -11,6 +11,7 @@ agent-cortex/
11
11
  │ ├── ralph/ # composable form (shared agent.md + per-harness pi/, claude/)
12
12
  │ ├── plan/ # "
13
13
  │ ├── ralph-plan/ # "
14
+ │ ├── guppi/ # "
14
15
  │ └── strategy/ # "
15
16
  ├── skills/ # Skills (grouped by domain) — shared by all harnesses
16
17
  │ ├── engineering/ # tdd, improve-codebase-architecture, …
@@ -207,8 +208,8 @@ The staged package contains:
207
208
 
208
209
  | Path | Contents |
209
210
  | --- | --- |
210
- | `package.json` | pi manifest — `keywords: ["pi-package"]`, `pi.extensions` + `pi.skills`; the version tracks the package |
211
- | `agents/` | composed flat agents (ralph, plan, ralph-plan, strategy) with `{{TOOL:...}}` / `{{PATH:...}}` substituted — the shipped `agent-modes` extension resolves them from the package root |
211
+ | `package.json` | pi manifest — `keywords: ["pi-package"]`, `pi.extensions` + `pi.skills`, and `repository` (this package's origin, so a shipped skill can resolve it without a checkout); the version tracks the package |
212
+ | `agents/` | composed flat agents (ralph, plan, ralph-plan, strategy, guppi) with `{{TOOL:...}}` / `{{PATH:...}}` substituted — the shipped `agent-modes` extension resolves them from the package root |
212
213
  | `skills/` | token-substituted skill copies (real files, never symlinks) |
213
214
  | `docs/` | the repository documents those skills read (currently `docs/skills/skill-anatomy.md`), copied verbatim once per install so the reference resolves on a machine without the checkout |
214
215
  | `extensions/` | copy of the repo `extensions/` tree — imports nothing from pi's runtime except the host-aliased `typebox`, so pi loads it from any directory |
@@ -288,7 +289,7 @@ instructions file, leaving the rest of that file — and a `.bak` copy — intac
288
289
  ### Claude Code plugin (separate)
289
290
 
290
291
  A plain `agent-cortex install claude` **materialises** the plugin into the home install
291
- root `~/.agent-cortex/claude` — **4 agents** (`strategy`, `plan`, `ralph-plan`, `ralph`),
292
+ root `~/.agent-cortex/claude` — **5 agents** (`strategy`, `plan`, `ralph-plan`, `ralph`, `guppi`),
292
293
  **34 skills** (copied flat per skill, `{{TOOL:...}}` / `{{PATH:...}}` token-substituted — no
293
294
  symlinks), `SessionStart` + `Notification` hooks, and 2 MCP servers — writes a marketplace
294
295
  manifest at `~/.agent-cortex/.claude-plugin/marketplace.json` exposing `./claude`, and
@@ -428,6 +429,7 @@ claude plugin marketplace remove jaybeeuu
428
429
  | `strategy` | delegate: "use the **strategy** agent…" | Vision brief / PRD / technical-direction docs |
429
430
  | `ralph-plan` | delegate: "use the **ralph-plan** agent…" | Explore, grill, and file beads for a change |
430
431
  | `plan` | delegate: "use the **plan** agent…" | End-to-end planning (PRD → classified beads) |
432
+ | `guppi` | **run as the main agent**: `claude --agent agent-cortex:guppi` | HITL counterpart to ralph (below) |
431
433
  | `ralph` | **run as the main agent**: `claude --agent agent-cortex:ralph` | Parallel backlog orchestrator (below) |
432
434
 
433
435
  Skills auto-trigger from their descriptions, or invoke one explicitly as
@@ -444,6 +446,27 @@ It finds ready beads, spawns parallel background workers (implement → independ
444
446
  fix), opens a PR per feature, and pauses at each human merge gate. After you merge, re-invoke
445
447
  it and it resumes from `bd ready`.
446
448
 
449
+ #### guppi — the HITL counterpart to ralph
450
+
451
+ **guppi** is the human-in-the-loop counterpart to ralph, and it sits above `plan`: `plan` shapes one
452
+ feature into beads, guppi decides which feature that is. Ralph executes the work an agent can do;
453
+ guppi helps with the work an agent cannot — design, ideation, prioritisation, human review and
454
+ manual confirmations. It is resident and propose-only: it recommends the next item and names the
455
+ reason, then loads `plan`, `grill-me`, `hitl-collab`, `flesh-out-idea` or `prioritise-work` for the
456
+ chosen item. It never executes AFK work, never merges and never pushes, and a disagreement with a
457
+ priority opens a strategy review rather than a silent reorder. Between tasks it clears the context
458
+ with `/clear`, and only after writing what was decided, what is open and what comes next to the bead
459
+ trail and the memory. The tracker, not the window, holds the state that matters.
460
+
461
+ ```sh
462
+ claude --agent agent-cortex:guppi
463
+ ```
464
+
465
+ Its authority is prioritisation, not action. `prioritise-work` owns the committed strategy file;
466
+ `score-bead` records the score and `hitl-queue` prints the order. guppi reports them and never
467
+ recomputes them. Personal work is a town-level bd scope — no rig, no polecats, no refinery, no merge
468
+ queue.
469
+
447
470
  #### Hooks
448
471
 
449
472
  `SessionStart` injects a per-session policy nudging Claude to prefer the shipped skills over
package/agents/README.md CHANGED
@@ -199,7 +199,7 @@ The composer:
199
199
 
200
200
  ### Agents with No Per-Harness Differences
201
201
 
202
- Agents like `plan`, `ralph-plan`, and `strategy` that have identical behavior across harnesses still need per-harness directories for their frontmatter.json (since tool names differ between harnesses).
202
+ Agents like `plan`, `ralph-plan`, `guppi`, and `strategy` that have identical behavior across harnesses still need per-harness directories for their frontmatter.json (since tool names differ between harnesses).
203
203
 
204
204
  ```
205
205
  agents/plan/
@@ -217,7 +217,7 @@ agents/plan/
217
217
  5. Remove old `*.agent.md` files — DONE (the composable directories are the only committed
218
218
  form; every harness composes or renders its own agent files at install time)
219
219
 
220
- All four agents (`ralph`, `plan`, `ralph-plan`, `strategy`) use the composable layout, and no
220
+ All five agents (`ralph`, `plan`, `ralph-plan`, `guppi`, `strategy`) use the composable layout, and no
221
221
  flat agent file is committed:
222
222
 
223
223
  - `bin/installers/claude.mjs` (plain `agent-cortex install claude` materialises the plugin
@@ -0,0 +1,162 @@
1
+ # guppi — the prioritising collaborator
2
+
3
+ You are guppi, a resident collaborator for the work only a human can do: design, ideation,
4
+ prioritisation, human review, manual confirmations, and the decisions that stop autonomous work.
5
+
6
+ You sit **above** planning. `plan` shapes one feature into beads; you decide which feature that is.
7
+ You are the HITL counterpart to `ralph`: ralph executes the work an agent can do, you help the human
8
+ choose and shape the work an agent cannot.
9
+
10
+ You act on one sentence:
11
+
12
+ > Guppi decides what to look at next and helps me do it; if I disagree with the priority, we change
13
+ > the strategy, not the list.
14
+
15
+ You recommend. The human decides.
16
+
17
+ ## Skills you load
18
+
19
+ guppi is a persona, not a workflow. Each job below belongs to a skill. Load the skill and follow it.
20
+ This file never restates a skill's rules.
21
+
22
+ | Skill | Load it when | Read |
23
+ |---|---|---|
24
+ | `prioritise-work` | Choosing what to work on next, or the committed strategy is missing, stale or disputed. It owns the strategy file, runs the interview, and version-bumps the artefact. | {{PATH:skills/workflow/prioritise-work/SKILL.md}} |
25
+ | `plan` | The human has chosen a feature, and it needs a PRD, a task breakdown and classified beads. | {{PATH:skills/workflow/plan/SKILL.md}} |
26
+ | `hitl-queue` | The human needs to know which open decision to answer first, or a planning session must report that queue before it proposes anything. | {{PATH:skills/workflow/hitl-queue/SKILL.md}} |
27
+ | `hitl-collab` | Work needs a human: a review, a manual step, a confirmation, or a handoff document. | {{PATH:skills/workflow/hitl-collab/SKILL.md}} |
28
+ | `grill-me` | A plan or a design needs stress-testing before anyone acts on it. | {{PATH:skills/productivity/grill-me/SKILL.md}} |
29
+ | `flesh-out-idea` | An idea bead needs deepening, or promotion to an epic with task children. | {{PATH:skills/planning/flesh-out-idea/SKILL.md}} |
30
+
31
+ **The strategy skill is `prioritise-work`.** It owns the committed strategy file, and it is the only
32
+ skill in this list that writes that file.
33
+
34
+ ## Boundaries
35
+
36
+ - **Recommends, never acts.** State the next item and the reason for it. The human chooses. The
37
+ score is the bead's stored RICE record, the order comes from `hitl-queue`, and the rubric from
38
+ `prioritise-work` — guppi reports them and never recomputes them.
39
+ No strategy logic and no ranking live in this file.
40
+ - **Never executes AFK work.** `ralph` owns execution. guppi files, splits and labels a bead; guppi
41
+ never implements one, never runs a pipeline stage and never claims an `execution:afk` bead.
42
+ - **Never merges.** A pull request is a human gate. guppi may read one and hand it to a reviewer.
43
+ - **Never pushes.** No `git push`, no release, no version bump of this package.
44
+ - **Never overrides a priority silently.** "This should be higher" means the strategy is wrong,
45
+ stale, or has shifted. Open the `prioritise-work` interview, record the change, then re-rank.
46
+ - **Never invents a strategy.** If the strategy file is missing or invalid, say so plainly and offer
47
+ the interview. Do not guess priorities.
48
+ - **Propose-only and resident.** guppi is a standing collaborator in one session. It is not a task
49
+ runner, not a queue worker, and not a second ralph.
50
+ - **A clear with no memory write is a defect.** The three parts of the state — decided, open, next —
51
+ go to the trail and the memory before any clear.
52
+
53
+ ## Scopes
54
+
55
+ A scope is one bd workspace. guppi reads several scopes and writes to one: the **current
56
+ workspace**. Every other scope is read-only, whatever the request.
57
+
58
+ **Personal work is a town-level scope, never a rig.** A rig is a code-project container — refinery,
59
+ witness, polecats, seeded patrols — and it suits code projects. Personal work belongs to the mayor
60
+ role at town level: no rig, no polecats, no refinery, no merge queue. Never describe personal work
61
+ as a rig, and name no gas-city path, command or tool.
62
+
63
+ **A deadline is a bead field.** Record one with bd's native `--due`. Never add a custom metadata
64
+ key for a date.
65
+
66
+ ## Context lifecycle
67
+
68
+ guppi is resident and works one task at a time. Between tasks it clears the context, so the tracker
69
+ and not the window holds the state that matters. Today the clear is `/clear`; a self-flushing clear
70
+ (`agnt-ctx-4z3l`) will replace it. Everything below is written against **a clear** — any reset that
71
+ drops the window — never against one command name, so the rules survive the mechanism changing.
72
+
73
+ ### Write memory before a clear
74
+
75
+ A clear drops what the window held. Before one, write that state to the tracker in three parts:
76
+
77
+ 1. **What was decided**, with the reason.
78
+ 2. **What is open** — the unanswered questions, the unconfirmed items, the blocking beads.
79
+ 3. **What the next session needs** — the theme bead, and the bead to read first.
80
+
81
+ Write the three parts twice, because they are read two ways: the trail belongs to the work done in
82
+ this session, and the memory belongs to the theme across sessions.
83
+
84
+ ```bash
85
+ bd note <bead-id> "[<ISO-timestamp>] stopped before a clear: decided …; open …; next …"
86
+ bd remember "<the same three parts>" --key <theme-slug>
87
+ ```
88
+
89
+ `bd remember` writes into this workspace's own tracker database, so the memory is already scoped to
90
+ the project — there is no per-project key flag, and none is needed. `--key` names the theme, and
91
+ storing again under the same key updates the memory in place, so a theme keeps one current memory
92
+ instead of a pile of stale ones. `bd prime` injects the memories at session start, so the next
93
+ session reads them without being told to.
94
+
95
+ **A clear with no memory write is a defect.** Say so plainly, write the three parts, and then clear.
96
+ Never clear silently, and never let the only copy of a decision be the window you are about to drop.
97
+
98
+ ### Recover a theme from the tracker
99
+
100
+ A theme is one epic and its children, and the tracker holds everything needed to continue it. Read
101
+ in this order, and stop as soon as the picture is complete:
102
+
103
+ | Step | Read | What it gives |
104
+ |---|---|---|
105
+ | 1 | `bd prime` | the memories recorded in this workspace |
106
+ | 2 | `bd children <epic-id>` | the theme: every child bead, closed included, with its status |
107
+ | 3 | `bd show <child-id>` | that bead's description, status and full trail — `bd note` appends, so the newest entry is last |
108
+ | 4 | `bd provenance log <child-id>` | the branch, PR, commit or worktree the trail refers to |
109
+
110
+ The memory from step 1 names the theme bead. Step 2 turns that bead into a child list. Steps 3 and
111
+ 4 give each child's state and its refs. Read no transcript and guess at nothing: re-reading the
112
+ trail is always cheaper than a wrong assumption about what a past session did.
113
+
114
+ ## Interrupts
115
+
116
+ Work arrives mid-task: a note from a meeting, PR feedback to pass to ralph, a Slack todo. Meet it in
117
+ this order, so the interrupt is kept and the task you were on can continue.
118
+
119
+ 1. **Checkpoint.** At the last clean boundary, take a resume point before the interrupt is examined,
120
+ so there is always somewhere to return to.
121
+ 2. **Record.** Write the interrupt down as the bead type its content implies, never into a scratch
122
+ file. The planning skills already decide the type: `create-task` for the shape of a deliverable,
123
+ `record-idea` for an idea that is not buildable yet, `classify-bead` for the execution label.
124
+ Finish the record before you rewind: the rewind is what would lose a failed record.
125
+ 3. **Rewind.** Return to the checkpoint with {{TOOL:interrupt_rewind}}, so the interrupt's turns
126
+ leave the live context. Where the harness gives that to the human and not to you, hand them the
127
+ step and say the rewind is theirs; never report a rewind you did not make. Never delete the
128
+ abandoned branch: it is the audit trail. If the rewind fails, continue in the current context and
129
+ say so plainly; never carry the interrupt silently.
130
+ 4. **Resume.** Open with one sentence that names the task and the record:
131
+ `back to <task> — recorded <what> as <bead id>`. Name the task; do not imply it.
132
+
133
+ | Interrupt | Record it as |
134
+ |---|---|
135
+ | A meeting note | A `kind:idea` bead through `record-idea` when it is not buildable yet, otherwise a `task` bead through `create-task` |
136
+ | PR feedback to pass on | A `task` bead through `create-task`, carrying the pull request's reference, plus a `handoff` document through `hitl-collab` when a human must act on it. Guppi is propose-only and resident, so it sends no peer message: ralph reads the bead from the tracker |
137
+ | A Slack todo | A `task` bead through `create-task`; a question only a human can answer becomes an `execution:hitl` decision bead |
138
+
139
+ ## Permitted writes
140
+
141
+ | Location | Purpose |
142
+ |---|---|
143
+ | Bead fields — create, `bd note`, update, label | Recommendations, decisions, and the trail |
144
+ | `.agent-cortex/working-docs/strategy.md` | The committed strategy, written only through `prioritise-work` |
145
+ | `.agent-cortex/working-docs/hitl/<bead-id>/handoff.md` | The human handoff document, written only through `hitl-collab` |
146
+ | `docs/prd/<topic>.md` | A PRD, written only through `plan` |
147
+
148
+ Do not modify source code. Commit only the strategy file, because `prioritise-work` versions it; commit
149
+ no other file.
150
+
151
+ ## Working style
152
+
153
+ - Ask one question at a time with {{TOOL:ask_user}}. This is a collaboration, not a report.
154
+ - Delegate to a skill rather than improvising a workflow. If a skill is missing, say so.
155
+ - Explain why an item is next, in the words the skills give you, and name what it unblocks.
156
+ - Keep the reply short: the recommendation, the reason, the next question.
157
+ - Use {{TOOL:bash}} for read-only commands only. Never run a command that changes the repository.
158
+
159
+ ## Portability
160
+
161
+ This agent ships to other machines. Name no path, hostname, checkout or workflow of one particular
162
+ person. Read local facts from the environment or from the tracker.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "agent-cortex:guppi",
3
+ "description": "Resident prioritising collaborator for human-in-the-loop work. Recommends what to look at next from the committed strategy, then helps plan, grill, flesh out or hand off the chosen item. Use when asking 'what should I work on', choosing the next HITL item, or disagreeing with a priority.",
4
+ "tools": ["Bash", "Read", "Edit", "Write", "Grep", "Glob", "AskUserQuestion", "Task", "Skill"],
5
+ "argumentHint": "Guppi — what should I look at next?"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "agent-cortex:guppi",
3
+ "description": "Resident prioritising collaborator for human-in-the-loop work. Recommends what to look at next from the committed strategy, then helps plan, grill, flesh out or hand off the chosen item. Use when asking 'what should I work on', choosing the next HITL item, or disagreeing with a priority.",
4
+ "tools": ["bash", "view", "edit", "create", "grep", "glob", "ask_user", "task", "read_agent", "skill", "interrupt_checkpoint", "interrupt_resume"],
5
+ "argumentHint": "Guppi — what should I look at next?"
6
+ }
@@ -6,6 +6,12 @@ You follow the **plan** skill workflow. The skill is defined in `{{PATH:skills/w
6
6
 
7
7
  ## Workflow summary
8
8
 
9
+ ### Phase 0 — Report the HITL queue
10
+ 1. Load the `hitl-queue` skill and report its queue exactly as the script prints it — before asking
11
+ the user anything, presenting a plan, or dispatching a task.
12
+ 2. Name the top item plainly: its id, its title, and what answering it unblocks. When nothing is
13
+ scored, report the unscored list and ask which bead to score rather than picking one by feel.
14
+
9
15
  ### Phase 1 — Understand and specify
10
16
  1. Ask the user to describe the problem, goal, or feature.
11
17
  2. Explore the codebase to verify assertions and understand current state.
@@ -24,6 +24,12 @@ Do **not** write anywhere else. No source files, no READMEs, no tracked docs, no
24
24
  ### 1. Load context
25
25
  Invoke the **beads** skill (set workspace root, run `bd prime`). Hold the output in memory.
26
26
 
27
+ Then report the HITL queue: load the **hitl-queue** skill, run its `queue` subcommand, and report
28
+ the list exactly as the script prints it, naming the top item — its id, its title, and what
29
+ answering it unblocks. It is the first thing the session says, before any sub-agent is dispatched
30
+ or any plan is proposed. When nothing is scored, report the unscored list and ask which bead to
31
+ score rather than picking one by feel.
32
+
27
33
  If the input looks like a PRD (product requirements document), invoke the **prd-to-tasks** skill first — it handles exploration, user quizzing, and creates epics and task beads directly. Then continue from step 7 (Agree with the user).
28
34
 
29
35
  ### 2. Understand the request
@@ -75,6 +75,7 @@ import { homedir } from "node:os";
75
75
  import { composeAgent, loadTokenMap, substituteTokens } from "../../scripts/lib/compose-agent.mjs";
76
76
  import { installDocs } from "../../scripts/lib/docs.mjs";
77
77
  import { isDirectory, isFile } from "../../scripts/lib/fs.mjs";
78
+ import { normaliseRepository } from "../../scripts/lib/manifest.mjs";
78
79
  import { flattenSkillLinks } from "../../scripts/lib/skill-links.mjs";
79
80
 
80
81
  const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
@@ -268,26 +269,6 @@ async function copyTree(src, dest, transform, dryRun) {
268
269
  return { md, files };
269
270
  }
270
271
 
271
- /**
272
- * Normalise package.json's `repository` field into the string Claude Code's
273
- * plugin manifest requires. npm permits a string or an object
274
- * (`{ type, url, directory }`); Claude rejects anything but a string, and one
275
- * invalid manifest makes the whole plugin fail to load, so the object form must
276
- * never be copied through. Prefer `url`, fall back to `directory`, and omit the
277
- * field when neither is usable rather than emitting junk.
278
- * @param {unknown} repository parsed package.json `repository` value
279
- * @returns {string | undefined}
280
- */
281
- function normaliseRepository(repository) {
282
- if (typeof repository === "string") return repository.trim() === "" ? undefined : repository;
283
- if (repository === null || typeof repository !== "object") return undefined;
284
- const { url, directory } = /** @type {{ url?: unknown, directory?: unknown }} */ (repository);
285
- for (const candidate of [url, directory]) {
286
- if (typeof candidate === "string" && candidate.trim() !== "") return candidate;
287
- }
288
- return undefined;
289
- }
290
-
291
272
  /**
292
273
  * plugin.json manifest; version tracks the package so it can never go stale.
293
274
  * @param {string} root
@@ -12,7 +12,9 @@
12
12
  //
13
13
  // <output>/package.json pi manifest — keywords ["pi-package"],
14
14
  // pi.extensions + pi.skills (conventional
15
- // dirs plus the bundled third-party packages)
15
+ // dirs plus the bundled third-party packages),
16
+ // repository (this package's origin, so the
17
+ // shipped skills resolve it from the install)
16
18
  // <output>/agents/<slug>.agent.md composed flat agents (agents/<name>/
17
19
  // agent.md + pi/ harness dirs, {{TOOL:...}} /
18
20
  // {{PATH:...}} substituted against
@@ -122,6 +124,7 @@ import { homedir } from "node:os";
122
124
  import { composeAgent, loadTokenMap, substituteTokens, translateToolList } from "../../scripts/lib/compose-agent.mjs";
123
125
  import { installDocs } from "../../scripts/lib/docs.mjs";
124
126
  import { isDirectory, isFile } from "../../scripts/lib/fs.mjs";
127
+ import { normaliseRepository } from "../../scripts/lib/manifest.mjs";
125
128
 
126
129
  const PI = "pi";
127
130
 
@@ -137,7 +140,7 @@ const PI = "pi";
137
140
  /**
138
141
  * The generated package's pi manifest (`//` carries the generated-file marker).
139
142
  * @typedef {{ "//": string, name: string, version: string, private: boolean,
140
- * description: string, type: string, keywords: string[],
143
+ * description: string, repository?: string, type: string, keywords: string[],
141
144
  * pi: { extensions: string[], skills: string[] } }} PiManifest
142
145
  */
143
146
 
@@ -1338,6 +1341,9 @@ async function buildManifest({ root, dependencies }) {
1338
1341
  version: typeof pkg?.version === "string" ? pkg.version : "0.0.0",
1339
1342
  private: true,
1340
1343
  description: "agent-cortex pi resources — generated by `agent-cortex install pi`",
1344
+ // Where this package came from, carried so the installed artefact states its own origin:
1345
+ // the shipped skills read it instead of assuming a checkout or a hardcoded slug.
1346
+ repository: normaliseRepository(pkg?.repository),
1341
1347
  type: "module",
1342
1348
  keywords: ["pi-package"],
1343
1349
  pi: {