@gtrabanco/pi-agentic-workflow 0.30.0 → 0.34.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.
- package/README.md +41 -0
- package/dist/config/defaults.js +3 -0
- package/dist/config/merge.js +5 -0
- package/dist/config/schema.d.ts +0 -5
- package/dist/config/schema.js +31 -1
- package/dist/config/types.d.ts +15 -0
- package/dist/extension/engram.d.ts +119 -0
- package/dist/extension/engram.js +187 -0
- package/dist/extension/index.js +70 -3
- package/dist/settings/console.js +68 -22
- package/package.json +1 -1
- package/skills/audit-pr/SKILL.md +1 -1
- package/skills/audit-pr/references/03_AUDIT_PROCESS.md +3 -2
- package/skills/execute-phase/SKILL.md +22 -8
- package/skills/execute-phase/references/EXECUTION_CONTRACT.md +15 -9
- package/skills/execute-phase/references/FOLDING.md +11 -8
- package/skills/execute-phase/references/PREFLIGHT.md +7 -3
- package/skills/fold-findings/SKILL.md +28 -17
- package/skills/fold-findings/references/FOLD_PROCESS.md +5 -3
- package/skills/init-workspace/SKILL.md +13 -2
- package/skills/init-workspace/references/BOOTSTRAP_WRITE.md +11 -5
- package/skills/init-workspace/references/ENGRAM.md +107 -0
- package/skills/log-session/SKILL.md +17 -1
- package/skills/orchestration-envelope/references/TURN_CONTRACT.md +2 -1
- package/skills/pre-execution-review/SKILL.md +1 -1
- package/skills/pre-execution-review/references/LEDGERS.md +30 -2
- package/skills/review-change/SKILL.md +1 -1
- package/skills/review-change/references/OUTPUT_AND_GUARDRAILS.md +2 -1
- package/skills/review-change/references/PERSIST_AND_DECIDE.md +30 -9
- package/skills/review-change/references/REVIEW_PROCESS.md +14 -6
- package/skills/review-implementation/SKILL.md +10 -2
- package/skills/review-implementation/references/CLASSIFY.md +21 -4
- package/skills/triage-issue/SKILL.md +18 -12
- package/skills/triage-issue/references/FOLD_LEDGER.md +11 -3
- package/skills/triage-issue/references/ISSUE_PROCESS.md +3 -2
- package/skills/triage-issue/references/REVIEW_FINDING_PROCESS.md +17 -8
- package/skills/unit-lane/SKILL.md +23 -5
- package/skills/unit-lane/references/DESIGN.md +1 -1
- package/skills/unit-lane/references/EVIDENCE.md +7 -3
- package/skills/unit-lane/references/MEMORY.md +179 -0
- package/skills/unit-lane/references/PLAN.md +11 -1
- package/skills/unit-lane/references/RESEARCH.md +3 -3
- package/skills/verification-contract/SKILL.md +9 -7
- package/skills/workflow-status/SKILL.md +4 -2
- package/skills/workflow-status/references/ENVELOPE_FIELDS.md +3 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Memory protocol — save and recall at unit boundaries
|
|
2
|
+
|
|
3
|
+
Engram is this workflow's required cross-session memory substrate (owner
|
|
4
|
+
decision 2026-09-24, feature 66). **Required substrate is not a hard
|
|
5
|
+
dependency:** the committed docs stay authoritative, and a memory layer that is
|
|
6
|
+
down is reported once and recorded — it never blocks a unit.
|
|
7
|
+
|
|
8
|
+
This file is the protocol's single home. `execute-phase` and `log-session` carry
|
|
9
|
+
a thin instruction plus a pointer here; they never restate it.
|
|
10
|
+
|
|
11
|
+
## 1. Probe before the first memory read
|
|
12
|
+
|
|
13
|
+
Run the bounded health probe once per session, before the first read:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
agentic-workflow memory probe # human block
|
|
17
|
+
agentic-workflow memory probe --json # memory-probe@1 verdict
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
It is bounded (4 s / 10 s per check, 30 s ceiling), writes nothing, issues no
|
|
21
|
+
MCP tool call, and **always exits 0**. Paste its verdict into the unit doc's
|
|
22
|
+
Evidence section — one row, `verified-by` naming the session:
|
|
23
|
+
|
|
24
|
+
- `ok` → memory is trustworthy for this session.
|
|
25
|
+
- `degraded` → say **once** which checks failed, record the verdict, and keep
|
|
26
|
+
working. Never re-probe in a loop, never ask the user to fix it first.
|
|
27
|
+
|
|
28
|
+
A `degraded` verdict is an answer, not a blocker: the degraded path in §7 is the
|
|
29
|
+
documented response.
|
|
30
|
+
|
|
31
|
+
## 2. Boundary saves — what, when, and under which key
|
|
32
|
+
|
|
33
|
+
Save at **three boundaries**, always under a stable per-unit topic key:
|
|
34
|
+
|
|
35
|
+
| Boundary | topic_key | Payload |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| unit start (after triage) | `unit/<NN-slug>/doc` | goal, the numbered acceptance criteria verbatim, the triaged step list |
|
|
38
|
+
| each phase transition | `unit/<NN-slug>/doc` | the phase id, what it changed, its Evidence outcome, new discoveries |
|
|
39
|
+
| unit close | `unit/<NN-slug>/doc` | final Evidence outcomes, decisions taken, the gotchas worth recalling |
|
|
40
|
+
|
|
41
|
+
One payload, four parts — the same four a later session needs to resume without
|
|
42
|
+
re-reading the docs:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
memory-payload@1
|
|
46
|
+
goal: <one line — the unit's objective>
|
|
47
|
+
ac: 1. <numbered AC verbatim, one per line>
|
|
48
|
+
evidence: <phase> <command> → <exit/digest> → <outcome>
|
|
49
|
+
learned: <gotcha, edge case, or decision a fresh session would get wrong>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Call `mem_save` with `topic_key: "unit/<NN-slug>/doc"` and an explicit
|
|
53
|
+
`project`; on a write surface that exposes `session_id`, pass it too (§5). Later
|
|
54
|
+
boundaries reuse the same `topic_key` so the record **upserts** instead of
|
|
55
|
+
fragmenting into one row per phase.
|
|
56
|
+
|
|
57
|
+
**What is saved is a summary for recall, never the artifact.** The unit doc, its
|
|
58
|
+
Evidence rows and `docs/LOGS.md` stay authoritative; a memory record that
|
|
59
|
+
disagrees with them is wrong by definition.
|
|
60
|
+
|
|
61
|
+
## 3. Recall — the fixed order
|
|
62
|
+
|
|
63
|
+
Resume in this order, and stop as soon as the unit is reconstructable:
|
|
64
|
+
|
|
65
|
+
1. **`mem_context`** — scoped explicitly (`project: "<name>"`, and `scope` when
|
|
66
|
+
you mean one).
|
|
67
|
+
2. **`mem_search`** — a scoped search with an **explicit `project`**. Never rely
|
|
68
|
+
on an omitted selector for a global read; a default is not a decision.
|
|
69
|
+
3. **One retry** — if the project-scoped search misses, retry **once** with
|
|
70
|
+
**`all_projects: true`** passed explicitly. A second miss is a miss.
|
|
71
|
+
4. **`mem_get_observation`** — fetch the full untruncated body of the hit that
|
|
72
|
+
matters.
|
|
73
|
+
5. **Read the unit doc** and reconcile: the file wins on every conflict, and the
|
|
74
|
+
difference is worth recording as a discovery (§2 `learned:`).
|
|
75
|
+
|
|
76
|
+
Only when `mem_context` and both searches miss does a fresh session fall back to
|
|
77
|
+
reading the docs cold — and that fallback is recorded, because it means the
|
|
78
|
+
recall path failed, not that nothing was ever saved.
|
|
79
|
+
|
|
80
|
+
When the cwd is ambiguous (several repos under it), call **`mem_current_project`**
|
|
81
|
+
and navigate by its `available_projects`: pick the matching project explicitly
|
|
82
|
+
rather than letting an ambiguous cwd decide. An ambiguous answer is never
|
|
83
|
+
resolved by guessing.
|
|
84
|
+
|
|
85
|
+
## 4. Keyword-bound recall — the disclosed ceiling
|
|
86
|
+
|
|
87
|
+
Engram's recall is **keyword-bound** (FTS5 over stored text, no vectors). Two
|
|
88
|
+
consequences are obligations, not trivia:
|
|
89
|
+
|
|
90
|
+
- **A miss is not evidence that knowledge was never saved.** It means the query
|
|
91
|
+
did not hit the stored terms. Rephrase with the unit's own vocabulary (slug,
|
|
92
|
+
AC wording, file paths) before concluding anything is absent.
|
|
93
|
+
- **What you save must be searchable later.** Save the words a future session
|
|
94
|
+
will search for — the unit slug, the phase id, the failing command, the file
|
|
95
|
+
path — not a paraphrase.
|
|
96
|
+
|
|
97
|
+
Hybrid FTS5+vector recall is Engram's own direction (#192), never built here.
|
|
98
|
+
|
|
99
|
+
## 5. Session attribution — explicit on every write, on the surface that carries it
|
|
100
|
+
|
|
101
|
+
Every write must be **attributed to one known session**, never to whichever
|
|
102
|
+
session a machine happens to resolve. On a box with several active runtime
|
|
103
|
+
sessions an unresolved attribution fails closed and the write is lost — the one
|
|
104
|
+
outcome this protocol exists to prevent (the health probe's
|
|
105
|
+
`session-ambiguity` check reads exactly this signal, §1).
|
|
106
|
+
|
|
107
|
+
Which parameter carries that attribution depends on the surface in front of you:
|
|
108
|
+
|
|
109
|
+
| Write surface | How the session is carried | What you do |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| Engram's own MCP server (`engram mcp --tools=agent`) | its `mem_save`, `mem_save_prompt`, `mem_session_summary` and `mem_capture_passive` take a `session_id` argument | open the session (`mem_session_start`) and pass that id on **every** write |
|
|
112
|
+
| a host whose memory tools expose no `session_id` (Pi's Engram provider binds the runtime session itself) | the provider stamps the session from the live runtime session and **refuses** when that identity is ambiguous or disagrees with the project | never write before the session is open, always pass an explicit `project` (and `cwd` when the directory could match more than one project), and treat an attribution refusal as a failed write — record it (§7), do not retry blind |
|
|
113
|
+
|
|
114
|
+
On both surfaces the obligation is the same and the check is the same: **a write
|
|
115
|
+
that cannot say which session it belongs to is a write that did not happen**.
|
|
116
|
+
|
|
117
|
+
- `mem_session_start` opens the id (or the runtime session the provider binds to)
|
|
118
|
+
at unit start; the boundaries in §2 reuse it, and nothing is written before it.
|
|
119
|
+
- **`mem_session_end` runs only on confirmed-stale ids** — ids you opened yourself
|
|
120
|
+
and know are finished. Never end an id a live session may still hold.
|
|
121
|
+
- When `mem_session_summary` cannot resolve the project, the explicit
|
|
122
|
+
**project fallback** is the documented escape hatch: pass `project` by name
|
|
123
|
+
and the summary lands instead of being refused. Record the fallback when you
|
|
124
|
+
use it.
|
|
125
|
+
- Passing a `session_id` to a tool that does not declare it is not "explicit
|
|
126
|
+
attribution", it is an invalid call. Read the tool's own parameter list when
|
|
127
|
+
the host offers more than one memory surface, and record which surface you used.
|
|
128
|
+
|
|
129
|
+
## 6. The canonical split (D2)
|
|
130
|
+
|
|
131
|
+
Both writers exist on purpose; neither mirrors the other.
|
|
132
|
+
|
|
133
|
+
| Writer | Owns | Travels |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `docs/LOGS.md` (`log-session`) | the human/team journal: what happened, for people | with git |
|
|
136
|
+
| `mem_session_summary` / `unit/<NN-slug>/doc` | local decision and gotcha recall keyed by unit id | local only |
|
|
137
|
+
|
|
138
|
+
Team memory travels with git; agent recall stays local. A double-write on
|
|
139
|
+
purpose, recorded here so it is never mistaken for an accident.
|
|
140
|
+
|
|
141
|
+
## 7. Degradation — recorded, never silent
|
|
142
|
+
|
|
143
|
+
When the probe says `degraded` or a write fails:
|
|
144
|
+
|
|
145
|
+
- **Local progress is preserved.** The unit doc, Evidence rows and commit are
|
|
146
|
+
the record; they never depend on memory.
|
|
147
|
+
- **The mirror is marked pending explicitly** — one line in the Progress entry
|
|
148
|
+
or Evidence row saying the memory write is pending, so a later session knows
|
|
149
|
+
the gap exists and is not a "nothing was saved" conclusion.
|
|
150
|
+
- **Unrelated safe work continues.** Never stop a unit for a mirror failure.
|
|
151
|
+
- **Sync resumes when the layer answers** — retry the pending write at the next
|
|
152
|
+
boundary, not in a loop.
|
|
153
|
+
- **Read both sides back.** After a write, read the file and the mirror; when
|
|
154
|
+
the versions are irreconcilable, keep both and surface the difference rather
|
|
155
|
+
than silently picking one.
|
|
156
|
+
|
|
157
|
+
## Checklist (pass only if)
|
|
158
|
+
|
|
159
|
+
- [ ] The probe ran once and its verdict is in Evidence (§1)
|
|
160
|
+
- [ ] A save happened at unit start, at each phase transition, and at close (§2)
|
|
161
|
+
- [ ] Every save was explicitly attributed: a `session_id` on a surface that
|
|
162
|
+
accepts one, otherwise an open session plus an explicit `project` — and it
|
|
163
|
+
named the unit's `topic_key` (§2, §5)
|
|
164
|
+
- [ ] Recall followed the fixed order, with an explicit `project` and at most
|
|
165
|
+
one explicit `all_projects: true` retry (§3)
|
|
166
|
+
- [ ] Any miss was treated as keyword-bound, not as absence (§4)
|
|
167
|
+
- [ ] Any degradation was recorded as pending — never silent (§7)
|
|
168
|
+
|
|
169
|
+
## Forbidden
|
|
170
|
+
|
|
171
|
+
- Never let a memory verdict block a unit, or re-probe in a loop
|
|
172
|
+
- Never rely on an omitted selector for a global read
|
|
173
|
+
- Never write with unresolved session attribution — pass the `session_id` where
|
|
174
|
+
the surface takes one, and where it does not, never write before the session is
|
|
175
|
+
open (§5)
|
|
176
|
+
- Never call `mem_session_end` on an id you did not open or cannot confirm stale
|
|
177
|
+
- Never mirror `docs/LOGS.md` verbatim — the split is deliberate (§6)
|
|
178
|
+
- Never treat a recall miss as proof nothing was saved
|
|
179
|
+
- Never let a memory record override the committed artifact
|
|
@@ -166,7 +166,17 @@ name those files instead.
|
|
|
166
166
|
- [ ] Each task names its validator (a backticked command plus its expected outcome)
|
|
167
167
|
- [ ] Final task is verification (proves the whole unit works)
|
|
168
168
|
- [ ] No task reaches into a future-phase concern (docs, release, migrations)
|
|
169
|
-
- [ ] Phases labeled P1, P2, …
|
|
169
|
+
- [ ] Phases labeled P1, P2, … — `#308`: `S#` is the requirement id (a spec),
|
|
170
|
+
`P#` is the phase label (a task); the two vocabularies never swap roles
|
|
171
|
+
- [ ] Each requirement is cut from the request verbatim: numbered `S#` in
|
|
172
|
+
`## Specs`, one per distinct ask, with the requester's own words as its
|
|
173
|
+
quote and no requirement the request did not make
|
|
174
|
+
- [ ] A later correction is appended under its own id (`S1a`) and leaves the
|
|
175
|
+
requirement it corrects untouched
|
|
176
|
+
- [ ] Every task bullet names the `S#` it delivers on its `(Implements: …)` line
|
|
177
|
+
- [ ] The `## Log` is opened with `L1` = the request verbatim, and later entries
|
|
178
|
+
append (never rewrite) in the `log-kind@1` vocabulary
|
|
179
|
+
- [ ] `## Findings` is present and carries only OPEN rows (empty at plan time)
|
|
170
180
|
- [ ] Both planning ledgers are cut (planning evidence + obligations), in the
|
|
171
181
|
sizing rule's home, with stable ids
|
|
172
182
|
|
|
@@ -7,9 +7,9 @@ them, not the user. A blank or missing objective/scope is therefore a **document
|
|
|
7
7
|
defect**: stop and repair the SPEC (`/unit-lane <unit>` — its §1 writes the
|
|
8
8
|
objective/why/user-outcome) or re-triage. Never infer unit scope, and never
|
|
9
9
|
turn a doc defect into a question the user cannot answer. A gap that survives
|
|
10
|
-
the repair runs `
|
|
11
|
-
`open-questions@1` block and stops, routed to `design`
|
|
12
|
-
owning stage.
|
|
10
|
+
the repair runs `bun scripts/needs-input.mjs <unit-dir>` (node fallback if bun is
|
|
11
|
+
not installed), pastes the `open-questions@1` block and stops, routed to `design`
|
|
12
|
+
or `unit-lane` by the owning stage.
|
|
13
13
|
|
|
14
14
|
## Purpose
|
|
15
15
|
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verification-contract
|
|
3
3
|
user-invocable: false
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
|
|
6
6
|
license: MIT
|
|
7
7
|
description: >
|
|
8
8
|
Internal contract: the acceptance artifact per delivery unit — legacy (pre-
|
|
9
9
|
feature 61) units may carry a frozen `ACCEPTANCE.md` (binding if present);
|
|
10
10
|
post-feature 61 units use the unit doc's `## Acceptance criteria` section as
|
|
11
|
-
the canonical acceptance source; the unit doc's `## Evidence`
|
|
12
|
-
|
|
11
|
+
the canonical acceptance source; the unit doc's evidence carrier — `## Evidence`
|
|
12
|
+
table, or `## Log` `E` lines for a re-cut unit (#308) — serves as the execution
|
|
13
|
+
receipt. Consumed by planners, execute-phase, and review-change.
|
|
13
14
|
---
|
|
14
15
|
|
|
15
16
|
# Verification Contract (internal)
|
|
@@ -63,9 +64,10 @@ v1` is needed: property/fuzz rides the existing `commands` class.
|
|
|
63
64
|
|
|
64
65
|
## Freeze and receipt
|
|
65
66
|
|
|
66
|
-
The unit doc's
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
The unit doc's own evidence carrier is the execution receipt: the `## Evidence`
|
|
68
|
+
table for a legacy-shape unit, the `## Log` `E` lines for a re-cut one (#308). Each
|
|
69
|
+
row or line records a validator command, its exit code or blob digest, output
|
|
70
|
+
excerpt, and who verified it. A frozen criterion's receipt is the Evidence row for that
|
|
69
71
|
criterion — exact match continues; missing/mismatched evidence stops before
|
|
70
72
|
edits:
|
|
71
73
|
|
|
@@ -122,4 +124,4 @@ semantics are verified against authoritative documentation **before a test encod
|
|
|
122
124
|
|
|
123
125
|
## Done when
|
|
124
126
|
|
|
125
|
-
Execution receipt (unit doc `## Evidence` table for post-feature 61
|
|
127
|
+
Execution receipt (unit doc `## Log` `E` lines for a re-cut unit, `## Evidence` table for a post-feature 61 one; legacy `ACCEPTANCE.md` manifest binding-if-present) + named validators + literal quality floor; executor and reviewer evaluate identical evidence.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: workflow-status
|
|
3
3
|
user-invocable: true
|
|
4
|
-
version: 3.9.
|
|
4
|
+
version: 3.9.4
|
|
5
5
|
author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
|
|
6
6
|
license: MIT
|
|
7
7
|
argument-hint: "[--json-only] [--last-envelope <json|path>] [--compact]"
|
|
@@ -69,7 +69,9 @@ bytes on a mature repo); the exact keep/drop set is in
|
|
|
69
69
|
Per the agent guide's **Workflow conventions** + **documentation map**. The
|
|
70
70
|
script reads what THIS skill needs (`docs/features/ROADMAP.md`, the fix index
|
|
71
71
|
`docs/fix/README.md`, every in-flight feature folder's `TASKS.md` +
|
|
72
|
-
`progress.md`
|
|
72
|
+
`progress.md` and its findings carrier — `SPEC.md` `## Findings` + `## Log` for a
|
|
73
|
+
migrated unit (issue #308), `review-findings.md` for a legacy one — and
|
|
74
|
+
`docs/workflow/REPOSITORY_STATE.md`);
|
|
73
75
|
read them yourself only to interpret a field the script emitted.
|
|
74
76
|
|
|
75
77
|
## Progressive loading — fixed sensor route
|
|
@@ -104,7 +104,9 @@ Exactly two fields change:
|
|
|
104
104
|
`in-progress` stays in both modes, so `detail.startable_now` and
|
|
105
105
|
`detail.blocked_units` keep naming every unit either way.
|
|
106
106
|
- `findings.fix_now[].route`: the reviewer's multi-paragraph evidence memo becomes
|
|
107
|
-
`...(N char evidence, see the unit review-findings.md)
|
|
107
|
+
`...(N char evidence, see the unit review-findings.md)` for a legacy carrier and
|
|
108
|
+
`...(N char evidence, see the unit SPEC.md ## Findings)` for a migrated one (#308),
|
|
109
|
+
keeping the original
|
|
108
110
|
length visible. `id`, `file`, `axis`, `severity`, `class` and `suggested_tier`
|
|
109
111
|
are untouched, and the memo is on disk in the unit's `review-findings.md`, which
|
|
110
112
|
is where the fold reads it.
|