brainclaw 1.18.0 → 1.19.1
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/dist/brainclaw-vscode.vsix +0 -0
- package/dist/commands/claim.js +5 -1
- package/dist/commands/harvest.js +28 -2
- package/dist/commands/install-hooks.js +184 -27
- package/dist/commands/mcp-write-claims.js +63 -1
- package/dist/commands/mcp-write-coordination.js +57 -17
- package/dist/commands/mcp-write-entities.js +11 -0
- package/dist/commands/mcp.js +24 -1
- package/dist/commands/session-end.js +15 -0
- package/dist/commands/session-start.js +19 -0
- package/dist/core/claim-conformity.js +193 -0
- package/dist/core/claim-scope.js +155 -0
- package/dist/core/claims.js +160 -2
- package/dist/core/facade-schema.js +32 -0
- package/dist/core/guidance-telemetry.js +197 -0
- package/dist/core/ideation-loop-close.js +32 -4
- package/dist/core/instruction-templates.js +11 -3
- package/dist/core/loops/verbs.js +40 -1
- package/dist/core/next-actions.js +157 -0
- package/dist/core/review-loop-close.js +22 -4
- package/dist/core/schema.js +40 -0
- package/dist/core/surface-freshness.js +150 -0
- package/dist/core/warnings.js +98 -0
- package/dist/facts.js +5 -5
- package/dist/facts.json +4 -4
- package/docs/concepts/plans-and-claims.md +57 -0
- package/docs/integrations/claude-code.md +53 -0
- package/docs/integrations/mcp.md +45 -0
- package/docs/mcp-schema-changelog.md +75 -1
- package/package.json +1 -1
|
@@ -17,6 +17,59 @@ brainclaw export --format claude-md --write
|
|
|
17
17
|
- use `.brainclaw/project.md` as a readable fallback (it is a derived view, regenerated best-effort — run `brainclaw rebuild` if stale)
|
|
18
18
|
- use hooks or workflow checks when a stronger reminder is needed
|
|
19
19
|
|
|
20
|
+
## The advisory PreToolUse hook (v1.19.0+)
|
|
21
|
+
|
|
22
|
+
`brainclaw install-hooks` generates `.git/hooks/claude-pre-tool.sh` **and activates
|
|
23
|
+
it** by merging a `PreToolUse` entry into `.claude/settings.json`. Before v1.19.0 it
|
|
24
|
+
only printed instructions, so the hook was dead even for operators who ran the
|
|
25
|
+
command.
|
|
26
|
+
|
|
27
|
+
It nudges an agent that is editing files without holding a claim of its own. It is
|
|
28
|
+
**advisory and can never block**: `permissionDecision` is always `allow` and the
|
|
29
|
+
exit code is always 0 (trp_5f342186 — a hook cascade once destroyed work).
|
|
30
|
+
|
|
31
|
+
### The channel matters, and it is not stderr
|
|
32
|
+
|
|
33
|
+
Per the Claude Code hook contract:
|
|
34
|
+
|
|
35
|
+
| Exit | stderr goes to | Tool |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| 0 | **nobody** — not the model | proceeds |
|
|
38
|
+
| 2 | the model | **BLOCKED** |
|
|
39
|
+
| other non-zero | the user only | proceeds |
|
|
40
|
+
|
|
41
|
+
So "advisory = exit 0 + write to stderr" is **structurally mute**, and that is
|
|
42
|
+
exactly what brainclaw's generated hook did for an unknown number of releases: even
|
|
43
|
+
once its other defects were fixed, it would still have spoken into the void. The
|
|
44
|
+
only non-blocking channel that reaches the model is JSON on **stdout** at exit 0:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{ "hookSpecificOutput": {
|
|
48
|
+
"hookEventName": "PreToolUse",
|
|
49
|
+
"permissionDecision": "allow",
|
|
50
|
+
"additionalContext": "[brainclaw] Editing without an active claim of your own…" } }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If you write hooks of your own, this is the shape to copy.
|
|
54
|
+
|
|
55
|
+
### What it matches, and what it deliberately does not
|
|
56
|
+
|
|
57
|
+
The matcher is `Edit|Write|MultiEdit|NotebookEdit` — the tools whose `tool_input`
|
|
58
|
+
exposes a concrete file path. **`Bash` is excluded on purpose**: a shell command's
|
|
59
|
+
file footprint is not statically knowable, so it is `unverifiable`, never guessed.
|
|
60
|
+
Matching it was one source of the noise that made the pre-v1.19 hook worth ignoring.
|
|
61
|
+
|
|
62
|
+
Activation is non-destructive: unknown settings keys are preserved, a pre-existing
|
|
63
|
+
`PreToolUse` array is appended to rather than replaced, and a `settings.json` that
|
|
64
|
+
cannot be parsed is left **byte-identical** with a manual instruction printed —
|
|
65
|
+
that file holds your permission allow-list, and clobbering it would be far worse
|
|
66
|
+
than an unactivated advisory.
|
|
67
|
+
|
|
68
|
+
> **Spawned workers get no hooks.** `.claude/` is gitignored, so a dispatched
|
|
69
|
+
> worker's worktree never receives this hook (nor Codex's `.codex/hooks.json`).
|
|
70
|
+
> Lifecycle parity for dispatched lanes runs through the brief today — see
|
|
71
|
+
> trp#1277.
|
|
72
|
+
|
|
20
73
|
## Key idea
|
|
21
74
|
|
|
22
75
|
Claude Code should not carry all workspace state in static instructions.
|
package/docs/integrations/mcp.md
CHANGED
|
@@ -141,6 +141,51 @@ See [code map](../code-map.md) for the full Code Map reference (CLI, freshness m
|
|
|
141
141
|
| `bclaw_update_memory` | memory | Update a memory item's text or metadata |
|
|
142
142
|
| `bclaw_compact` | memory | LLM-driven semantic memory compaction (two-phase) |
|
|
143
143
|
|
|
144
|
+
### What a response tells you to do next (v1.19.0+)
|
|
145
|
+
|
|
146
|
+
Responses are self-teaching: rather than requiring you to memorise the API, they
|
|
147
|
+
carry the follow-up derived from **what actually happened**.
|
|
148
|
+
|
|
149
|
+
**`next_actions`** — an array of `{tool, args?, when?}`. Present only when there is
|
|
150
|
+
a genuine follow-up, so its presence is meaningful; a handler with nothing to add
|
|
151
|
+
omits the key entirely rather than padding it. It is derived from the outcome, not
|
|
152
|
+
from a static table: releasing a claim proposes something different depending on
|
|
153
|
+
whether the plan cascade fired or refused. Fan-out is capped at 3, with an explicit
|
|
154
|
+
note when more were available.
|
|
155
|
+
|
|
156
|
+
**`warning_details`** — the structured sibling of `warnings: string[]`. Each entry
|
|
157
|
+
carries a stable `code`, human `message`, the `data` the prose mentions, and — the
|
|
158
|
+
part a bare string could never hold — `next_actions` naming the way out.
|
|
159
|
+
|
|
160
|
+
```jsonc
|
|
161
|
+
{
|
|
162
|
+
"code": "wrote_outside_claim_scope",
|
|
163
|
+
"message": "Claim clm_… declared 'src/core' but 2 touched file(s) sit outside it: …",
|
|
164
|
+
"data": { "claim_id": "clm_…", "scope": "src/core", "unexpected_paths": ["docs/x.md"] },
|
|
165
|
+
"next_actions": [{ "tool": "bclaw_update", "args": { "entity": "claim", "…": "…" } }]
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`warnings` keeps its type **and** its byte-identical historical contents, so a
|
|
170
|
+
consumer that ignores `warning_details` sees no change. Read `warnings` for
|
|
171
|
+
completeness and `warning_details` for the codes that carry a recovery path — the
|
|
172
|
+
structured channel is a subset, not a mirror.
|
|
173
|
+
|
|
174
|
+
Codes you may see today:
|
|
175
|
+
|
|
176
|
+
| Code | Emitted by | Meaning |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `scope_already_claimed` | `bclaw_coordinate` | Another agent holds the scope |
|
|
179
|
+
| `plan_already_assigned` | `bclaw_coordinate` | A second assignment on one plan |
|
|
180
|
+
| `agent_validation_failed` | `bclaw_coordinate` | Target is not dispatchable |
|
|
181
|
+
| `wrote_outside_claim_scope` | release / assignment-completed / harvest / session-end | Files were written outside the claim's declared scope. **Advisory** — the write already happened |
|
|
182
|
+
| `generated_surfaces_stale` | `session-start` | Generated guidance on disk was written by an older brainclaw. Recovery is `brainclaw export --write`; no MCP tool performs it, so no `next_actions` is offered rather than one the engine would reject |
|
|
183
|
+
|
|
184
|
+
Conformity warnings are **silent on doubt** by construction: a claim whose scope is
|
|
185
|
+
a loop reference, free prose or a glob — 42.4% of the real corpus — yields
|
|
186
|
+
`unverifiable` and emits nothing. An accuser that is wrong that often teaches
|
|
187
|
+
agents to ignore the channel, which is worse than shipping no check at all.
|
|
188
|
+
|
|
144
189
|
### Canonical grammar (standard tier, v1.0+)
|
|
145
190
|
|
|
146
191
|
Phase 3 shipped a unified grammar that replaces the per-entity tools
|
|
@@ -8,7 +8,81 @@ guarantees this changelog follows.
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## [1.19.0] — 2026-08-01
|
|
12
|
+
|
|
13
|
+
**Added — `warning_details` on the facade response contract (pln#635)**
|
|
14
|
+
- Additive sibling of `warnings: string[]`, which keeps both its type and its
|
|
15
|
+
byte-identical historical contents. Each record carries `code` / `message` /
|
|
16
|
+
optional `data` / optional `next_actions`, so a consumer no longer has to
|
|
17
|
+
sniff-parse a string that may or may not be JSON to recover structure.
|
|
18
|
+
- The legacy string is DERIVED from the record, and only for an **enumerated**
|
|
19
|
+
set of codes that historically shipped a JSON blob (`agent_validation_failed`,
|
|
20
|
+
`plan_already_assigned`, `scope_already_claimed`). Enumerated rather than
|
|
21
|
+
inferred so a NEW code can never start emitting JSON at a consumer that has
|
|
22
|
+
only ever seen prose.
|
|
23
|
+
- Read contract, not input: no tool added/removed/renamed, no inputSchema change,
|
|
24
|
+
**no surface-fingerprint movement**. `warnings` remains the complete channel;
|
|
25
|
+
`warning_details` is a structured subset (see `src/core/warnings.ts` for why).
|
|
26
|
+
|
|
27
|
+
**Added — `next_actions` emitted by the write surfaces (pln#634 PR1)**
|
|
28
|
+
- `FacadeResponseSchema.next_actions` already existed and was optional; the write
|
|
29
|
+
facades simply never populated it. They now do, derived from the OUTCOME rather
|
|
30
|
+
than from a static table — and omit the key entirely when there is no genuine
|
|
31
|
+
follow-up, so its presence stays meaningful. Response-only; no fingerprint move.
|
|
32
|
+
|
|
33
|
+
**Added — new structured warning codes**
|
|
34
|
+
- `wrote_outside_claim_scope` (pln#636 C2) — emitted on `bclaw_release_claim`, on
|
|
35
|
+
assignment→`completed`, at LANE-RESULT harvest ingestion and at `session-end`.
|
|
36
|
+
Carries `claim_id`, `scope`, `declared_pathspecs`, `unexpected_paths`,
|
|
37
|
+
`base_sha`, and two recovery actions. Advisory: the write already happened.
|
|
38
|
+
- `generated_surfaces_stale` (pln#638 2b) — surfaced on `session-start` as
|
|
39
|
+
`stale_surfaces` when a generated guidance surface on disk was stamped by an
|
|
40
|
+
older brainclaw than the running one. Deliberately carries **no**
|
|
41
|
+
`next_actions`: the recovery is `brainclaw export --write` and no MCP tool
|
|
42
|
+
performs it, so the command travels in `message` + `data.refresh_command`
|
|
43
|
+
rather than as an action whose args the engine would reject.
|
|
44
|
+
|
|
45
|
+
**Added — `ClaimSchema.base_sha` / `ClaimSchema.paths` (pln#636 C0-b)**
|
|
46
|
+
- Both optional and never backfilled; legacy claims parse unchanged and a missing
|
|
47
|
+
baseline is treated as `unverifiable`, never guessed.
|
|
48
|
+
- Record shape only. `paths` is NOT exposed in `bclaw_claim`'s published
|
|
49
|
+
inputSchema — settable via the core and CLI, readable by the conformity
|
|
50
|
+
reconcile — so this moves **no** surface fingerprint. Widening the published
|
|
51
|
+
input belongs in its own governed change (tracked as a known gap in
|
|
52
|
+
CHANGELOG 1.19.0).
|
|
53
|
+
|
|
54
|
+
**Added — `SessionEndResult.scope_warnings`, `LaneHarvestResult.warnings`**
|
|
55
|
+
- Both are `WarningDetail[]`, born structured (hence `toWarningDetail`, which
|
|
56
|
+
builds the record without inventing a throwaway legacy string array). Additive
|
|
57
|
+
result fields on non-MCP surfaces; `LaneHarvestResult.warnings` is always
|
|
58
|
+
present (empty when nothing was ingested), which is an exact-shape change for
|
|
59
|
+
any caller asserting `deepEqual` on that result.
|
|
60
|
+
|
|
61
|
+
**Changed — a content-less loop artifact no longer satisfies a gate (pln#639)**
|
|
62
|
+
- Behavioural, not schema: `artifact.body` stays optional (ref-based artifacts
|
|
63
|
+
legitimately have none), but an artifact with neither a non-empty `body` nor a
|
|
64
|
+
`ref` no longer counts toward `min_artifacts_by_type`. The unmet-gate reason
|
|
65
|
+
string now names how many artifacts of that type were discarded as empty.
|
|
66
|
+
- Verified against the live corpus before shipping (219 loops / 321 artifacts,
|
|
67
|
+
zero content-less), so no running loop can be stalled by the stricter rule.
|
|
68
|
+
|
|
69
|
+
**Changed — loop artifacts are attributed to their DISPATCH phase (pln#639)**
|
|
70
|
+
- The ideation and review closers recorded `phase: loop.current_phase` (close
|
|
71
|
+
time); they now use the phase stamped on the slot at dispatch. A lane returning
|
|
72
|
+
after a phase advance is filed under the phase it was asked to work in.
|
|
73
|
+
- No gate in the engine keys on `type: 'verdict'` and `reviewer_green` scans all
|
|
74
|
+
phases, so review-loop outcomes are unaffected — attribution changes, verdicts
|
|
75
|
+
do not.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## [1.18.0] — 2026-07-31
|
|
80
|
+
|
|
81
|
+
> These entries sat under an `Unreleased` heading THROUGH the 1.18.0 release and
|
|
82
|
+
> are rolled retroactively here. pln#630 / pln#627 / pln#628 shipped in 1.18.0
|
|
83
|
+
> (see CHANGELOG.md); the pln#625 Phase 3 entry below predates it and was never
|
|
84
|
+
> rolled either. Rolling the section is part of cutting a release — the 1.19.0
|
|
85
|
+
> prep found it still open.
|
|
12
86
|
|
|
13
87
|
**Added — turn-attempt evidence-correlation fields (pln#630 PR2b-a)**
|
|
14
88
|
- Additive, backward-compatible: `LaneResultSchema` gains optional `turn_id` /
|