@treeseed/dsh-chapters 0.1.5 → 0.1.6
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/docs/architecture.md +9 -3
- package/docs/plans-carriage.md +304 -0
- package/docs/verify.md +23 -1
- package/lib/archive.d.ts +9 -0
- package/lib/archive.js +5 -0
- package/lib/archive.js.map +1 -1
- package/lib/artifact-query.js +20 -0
- package/lib/artifact-query.js.map +1 -1
- package/lib/compose.js +38 -3
- package/lib/compose.js.map +1 -1
- package/lib/continue-core.d.ts +36 -1
- package/lib/continue-core.js +74 -9
- package/lib/continue-core.js.map +1 -1
- package/lib/engine-core.d.ts +16 -1
- package/lib/engine-core.js +25 -3
- package/lib/engine-core.js.map +1 -1
- package/lib/engine.d.ts +4 -0
- package/lib/engine.js +3 -1
- package/lib/engine.js.map +1 -1
- package/lib/index.d.ts +6 -0
- package/lib/index.js +14 -0
- package/lib/index.js.map +1 -1
- package/lib/log-shape.d.ts +38 -0
- package/lib/log-shape.js +93 -0
- package/lib/log-shape.js.map +1 -0
- package/lib/plans.d.ts +105 -0
- package/lib/plans.js +217 -0
- package/lib/plans.js.map +1 -0
- package/lib/render.d.ts +5 -0
- package/lib/render.js +114 -37
- package/lib/render.js.map +1 -1
- package/lib/store.js +13 -0
- package/lib/store.js.map +1 -1
- package/lib/tools.js +31 -2
- package/lib/tools.js.map +1 -1
- package/lib/types.d.ts +56 -0
- package/lib/types.js.map +1 -1
- package/package.json +1 -1
package/docs/architecture.md
CHANGED
|
@@ -70,7 +70,8 @@ The model supplies ranges; the plugin renders. Within a range:
|
|
|
70
70
|
| Event content | Handling |
|
|
71
71
|
|---|---|
|
|
72
72
|
| user / assistant text | inline, verbatim, attributed |
|
|
73
|
-
| tool **invocation** (name + arguments) |
|
|
73
|
+
| tool **invocation** (name + arguments) | inline as a bounded head (400 chars) — the "what was attempted" half of the record; above `callArgArtifactTokens` the full arguments are **artifact-backed** like any deferred blob (0 = off by default) |
|
|
74
|
+
| session **plan** (`exit_plan_mode` call + its verdict result) | full text always artifact-backed + a labeled `## Plans in this chapter` block after the transcript (docs/plans-carriage.md) |
|
|
74
75
|
| tool **result** judged **not worth keeping** | deferred to `artifacts/`, replaced by a reference line |
|
|
75
76
|
| tool **result** judged worth keeping, ≤ floor | inline, verbatim, no model input needed |
|
|
76
77
|
| tool **result** judged worth keeping, > floor | inline by model override **and** still written to `artifacts/` |
|
|
@@ -94,8 +95,13 @@ Division of labour:
|
|
|
94
95
|
- **Model submits exceptions only**: `toolResultOverrides: [{seq, inline}]`. Usually empty or one entry, so
|
|
95
96
|
the judgment costs almost no output tokens — which is why this is affordable where "the model writes the
|
|
96
97
|
chapter bodies" was not.
|
|
97
|
-
- **Invocations
|
|
98
|
-
attempted" half of the record and the thing a successor most needs.
|
|
98
|
+
- **Invocations stay inline as a bounded head.** Plugin rule, not a choice; it is the "what was
|
|
99
|
+
attempted" half of the record and the thing a successor most needs. The head is 400 characters, so
|
|
100
|
+
a large argument (`write` carrying a whole file, a plan carrying a whole design) is *also* written to
|
|
101
|
+
`artifacts/` whenever `callArgArtifactTokens` is above zero — the inline text is then a head with a
|
|
102
|
+
resolution, never the only copy. Session plans get this treatment unconditionally and by name: the
|
|
103
|
+
plan's own bytes are always an artifact, cited with its outline and verdict
|
|
104
|
+
(docs/plans-carriage.md § 2/§ 3).
|
|
99
105
|
- **The artifact is written either way.** Inlining is a convenience copy *alongside* its reference. So a
|
|
100
106
|
wrong call is a context-economy miss, never data loss — that asymmetry is what makes delegating this
|
|
101
107
|
judgment to the model safe.
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Plans in the Archive — design record
|
|
2
|
+
|
|
3
|
+
Written 2026-10-09. **Read before writing code.** Human decisions for this feature are recorded at
|
|
4
|
+
§ Decisions Taken and are binding; anything marked *deferred* is a human call, not ours.
|
|
5
|
+
|
|
6
|
+
DSh ships plan mode (`@deepseek-ai/dsh-plan-mode`) and our own preset mounts it
|
|
7
|
+
(`presets/chapters/agent.cordis.yml:109-133`). Today a session plan survives an archive only as the
|
|
8
|
+
first 400 characters of a tool-call line. That is the worst possible outcome for the one artifact in a
|
|
9
|
+
conversation that is *deliberately* decision-complete — and the reason the plugin exists at all: a
|
|
10
|
+
continuation that cannot see the approved plan either re-plans from recall (lossy) or implements
|
|
11
|
+
something nobody approved (worse).
|
|
12
|
+
|
|
13
|
+
## Facts to re-verify on any DSH upgrade
|
|
14
|
+
|
|
15
|
+
| Fact | Where | Consequence for us |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| The plan is a **tool-call argument**, field `plan`, type string, required | `dsh-plan-mode/lib/index.js:230-236` | Detection is one predicate: `tool/call && name === 'exit_plan_mode'`. There is no plan document event. |
|
|
18
|
+
| The host validates `/^#\s+\S/` on the plan text | `index.js:256` | We can rely on a leading `#` H1 for the title. |
|
|
19
|
+
| Approval result is the canonical `{ approved: true }` + fixed render text | `index.js:237-251` | Verdict is derivable from the paired result, not from prose. |
|
|
20
|
+
| Rejection = failed call carrying review feedback; dismissal = failed call naming the takeover | `index.js` execute arm + package README § Model Experience | Three distinct non-approval shapes to classify, plus a fourth we must not invent. |
|
|
21
|
+
| State is one log-only whole-value event `plan/mode { active }`, appended at the next **accepted in-turn pre-step** | `index.js:374, 389` | An approved exit may not have its mode event yet at archive time → the *result* is the primary signal, the mode event secondary. |
|
|
22
|
+
| Mode state is recovered by **folding the log** (projection `apply`, `stateVersion: 3`) | `index.js:83-94` | Last logged value wins; we mirror that rule, we do not cache a verdict. |
|
|
23
|
+
| The mode-switch notice rides as `source.kind 'plugin'`, `plugin: 'plan-mode'`, `form: 'notice'` | `index.js:392-410` | Our injection screen already omits it (`src/injections.ts:38-41, 94-102`). Deliberate — see § Non-Goals. |
|
|
24
|
+
| `/plan <message>` steers a real user message, `source.kind 'user'`; bare `/plan`, `/plan off` and their terminal results stay outside model history | `index.js:220` + README § Human Command | The instruction a human typed under plan guidance **is** conversation and is archived verbatim today. Nothing to change. |
|
|
25
|
+
| Freshly created agents begin plan mode **inactive**; `plan/mode` is per-session and not inheritable | README § Known Limitations | A `chapters_continue` / `chapters_fork` child cannot know it was mid-plan unless we carry that text. |
|
|
26
|
+
| `tool/call` data shape is `data.{callId, name, arguments}`, `arguments` an object **or** a JSON string | `src/types.ts:8`, precedent `src/render.ts:253` | The extractor must accept both, exactly as the renderer already does. |
|
|
27
|
+
|
|
28
|
+
## What the pipeline loses today
|
|
29
|
+
|
|
30
|
+
| Loss | Line | Fix below |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| Full plan bytes never reach the store (400-char head only) | `src/render.ts:250-257` | § 2 + § 3 |
|
|
33
|
+
| Artifacts are written for `tool/result` payloads only | `src/render.ts:258-277`, `:126-156` | § 3 |
|
|
34
|
+
| `plan/mode` events fall to `default:` → `unrenderedSeqs` (a disclosed hole, no prose) | `src/render.ts:284-285` | § 2 |
|
|
35
|
+
| Nothing in the TOC names a plan or its verdict | `src/continue-core.ts:111-141` | § 4 |
|
|
36
|
+
| `chapters_search` resolves chapters + rules; artifacts travel (`src/sync.ts:160-215`) but are not index entries | `src/search.ts:76, 104-105` | § 8 |
|
|
37
|
+
| A plan in an **open** turn is above the archive ceiling (completed turns only, `src/tools.ts:186-189`) and is never archived | `src/tools.ts:194-198` | § 5 `livePlans` |
|
|
38
|
+
|
|
39
|
+
## Decisions taken (human, 2026-10-09)
|
|
40
|
+
|
|
41
|
+
1. **Home for plan bytes: artifact pointer + chapter block.** The verbatim plan goes to the
|
|
42
|
+
content-addressed artifact store; the chapter carries status, outline, a bounded head, and the path.
|
|
43
|
+
*Not* a first-class `kind: plan` corpus document — that stays deferred (§ Deferred), because it
|
|
44
|
+
widens the corpus and needs a `docs/knowledge-repo.md` amendment.
|
|
45
|
+
2. **Mode carriage: notice-only.** The child is *told* about the active plan. We do not seed a synthetic
|
|
46
|
+
`plan/mode` event into the seed: the seed contract is pinned as one event at `seq 0`
|
|
47
|
+
(AGENTS.md invariant 2, `spikes/probe/FINDINGS.md`), and flipping the child's mode also changes the
|
|
48
|
+
composed `plan:policy` header section. Both belong to a measured spike, not to this feature.
|
|
49
|
+
3. **Record before code.** This file is the reviewable artifact; implementation starts after it lands.
|
|
50
|
+
|
|
51
|
+
## Design
|
|
52
|
+
|
|
53
|
+
### 1. `src/plans.ts` — pure detector (no cordis, no fs, L0-testable)
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
export type PlanStatus = 'approved' | 'rejected' | 'dismissed' | 'pending' | 'superseded' | 'failed'
|
|
57
|
+
export interface PlanDoc {
|
|
58
|
+
seq: number; resultSeq: number | null; callId: string
|
|
59
|
+
title: string; status: PlanStatus; text: string
|
|
60
|
+
sha256: string; bytes: number; estTokens: number
|
|
61
|
+
outline: string[] // H2/H3 headings, in order, verbatim
|
|
62
|
+
artifactPath: string // artifacts/<aa>/<sha>.txt
|
|
63
|
+
archived: boolean // false when seq > archiveCeiling
|
|
64
|
+
}
|
|
65
|
+
export function detectPlans(events, ceiling, opts): { plans: PlanDoc[]; modeActiveAt: (seq: number) => boolean }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
*Status-vocabulary amendment (2026-10-09, at implementation).* A fifth class appeared in the host's own
|
|
69
|
+
`execute` arm and is not a human verdict at all: the review could never open (no user-questions channel;
|
|
70
|
+
the plan-mode service reloaded mid-review; the call ran outside plan mode; the markdown had no `#`
|
|
71
|
+
heading). Labelling those `rejected` would credit the user with a decision they never made, so the union
|
|
72
|
+
carries `failed` and prints the host's own text as the verdict line. The four shapes the record named are
|
|
73
|
+
all still there.
|
|
74
|
+
|
|
75
|
+
Rules, each pinned by a unit row:
|
|
76
|
+
|
|
77
|
+
- **Pair by callId** using the existing `sameCall` logic (`src/render.ts:158-164`) — extract it, do not
|
|
78
|
+
duplicate it.
|
|
79
|
+
- **Verdict precedence**: paired `tool/result` first (`{approved:true}` → approved; `isError` +
|
|
80
|
+
"Keep planning" feedback → rejected; failed call naming takeover → dismissed); **no result event →
|
|
81
|
+
`pending`**, which must never be rendered as approval. The `plan/mode` fold is secondary evidence and
|
|
82
|
+
only breaks a tie.
|
|
83
|
+
- **`superseded`**: same H1 title, different sha256, later seq ⇒ newest is operative, earlier ones are
|
|
84
|
+
`superseded`. Deterministic; no model judgement.
|
|
85
|
+
- **Screen the body**: run `stripReminderSpans` over the plan text. A plan is model-authored bytes, but
|
|
86
|
+
an injected span riding inside it is host state (same reasoning as `src/injections.ts:62-70`).
|
|
87
|
+
- **Redaction rides for free**: build the doc through `artifactRef`, so the `render → redact → write`
|
|
88
|
+
chokepoint applies (`src/render.ts:179-182`). Never write an unredacted plan blob.
|
|
89
|
+
- Title = the first heading, H1 preferred; keep the 72-char cap that `deriveIdentity` already uses
|
|
90
|
+
(`src/engine-core.ts:251-262`).
|
|
91
|
+
|
|
92
|
+
### 2. Chapter body: a labeled section **after** the transcript
|
|
93
|
+
|
|
94
|
+
`renderChapter` appends one block, after the verbatim transcript and before the closing of the body —
|
|
95
|
+
never interleaved, so the transcript stays exactly what the log said:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
## Plans in this chapter
|
|
99
|
+
|
|
100
|
+
### Plan — "Carry session plans into chapters" — APPROVED (call seq 412, result seq 419)
|
|
101
|
+
- full text: `artifacts/8f/8f3a1c….txt` (18.4 KB ≈ 4.6K tok) — chapters_artifact 'toc' | 'search' | 'read'
|
|
102
|
+
- outline: Goal · Success criteria · Changes by subsystem · Tests · Assumptions · Rollback
|
|
103
|
+
- head (first 900 chars, verbatim): `# Carry session plans into chapters …`
|
|
104
|
+
- mode: plan mode ACTIVE from seq 118 (log event plan/mode, seq 118)
|
|
105
|
+
- superseded by the same-titled plan at seq 455 — that one is operative
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Frontmatter gains `plans: [412:approved:8f3a1c9d]` — one `seq:status:sha8` triple per plan — and
|
|
109
|
+
`planMode: active|inactive|unknown`, BOTH emitted only when the chapter really carries a plan or a mode
|
|
110
|
+
flip. *Why the compact triple instead of the nested list this record first specified:* the only reader of
|
|
111
|
+
frontmatter is `indexing.parseFrontmatter`, which understands `key: value` and flat `key: [a, b]`. Nested
|
|
112
|
+
YAML maps parse as nothing at all — an index that looks populated and reads empty, the worst kind of lie
|
|
113
|
+
here. So the machine-readable home for the full facts is the **chapter record** (`ChapterRecord.plans`,
|
|
114
|
+
zod-validated in the registry, `src/store.ts`), which is what the notice builder consumes; the
|
|
115
|
+
frontmatter line is the human-visible claim of the same fact, and the prose lives in the body block.
|
|
116
|
+
|
|
117
|
+
The sha256 anchor convention must hash what `parseChapterFile`
|
|
118
|
+
returns — body **including** the trailing newline (`src/engine-core.ts:297-302`; the T9 lesson: a
|
|
119
|
+
mismatch silently blocked enrichment for an era).
|
|
120
|
+
|
|
121
|
+
`plan/mode` gets an explicit `case` so its handling is *stated* rather than a silent skip: it renders as
|
|
122
|
+
the `mode:` line above and does not enter `unrenderedSeqs`.
|
|
123
|
+
|
|
124
|
+
### 3. Invocation artifacts, generally (the honest fix for "always inline")
|
|
125
|
+
|
|
126
|
+
Any `tool/call` whose serialized arguments exceed `callArgArtifactTokens` gets the same treatment:
|
|
127
|
+
full blob to the artifact store, bounded head + path inline. Plans are simply the case that earns the
|
|
128
|
+
mechanism. In the same commit, correct `docs/architecture.md:73` and `:97`, which claim invocations and
|
|
129
|
+
arguments "always stay inline" while the code caps at 400 (`src/render.ts:255`). The real rule:
|
|
130
|
+
|
|
131
|
+
> Invocations are always inline; a bounded head is always artifact-backed. Every byte of an
|
|
132
|
+
> invocation and its result remains retrievable.
|
|
133
|
+
|
|
134
|
+
### 4. The notice: `plansSection`, built exactly like `rulesSection`
|
|
135
|
+
|
|
136
|
+
`assembleNotice` takes an optional `plansSection: string` (`src/continue-core.ts:111-141` precedent).
|
|
137
|
+
Empty or absent ⇒ **zero injected bytes**, which is what keeps this tape-safe (§ Tapes). Placement:
|
|
138
|
+
between the project line and the preamble, so it is above the fold:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
## Plans on this path (3: 1 approved, 1 rejected, 1 pending)
|
|
142
|
+
- ACTIVE PLAN: "Carry session plans into chapters" — APPROVED (ch. 4, seq 412, sha 8f3a1c…, ~4.6K tok)
|
|
143
|
+
full text: .dsh-chapters/artifacts/8f/8f3a1c….txt — read it with chapters_artifact before implementing;
|
|
144
|
+
do NOT re-plan from recall.
|
|
145
|
+
- REJECTED v1 "…" (ch. 4, seq 388) — user feedback is archived in that chapter
|
|
146
|
+
- pending "…" (seq 501) — the review was never answered. NOT approved; do not implement it.
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Cost is counted, never exempted: the section is part of `noticeTokens` and flows through the same
|
|
150
|
+
`preflight` (`src/continue-core.ts:146-162`) — `tocTokens + handoffNoteTokens ≤ ratio × (window − header)`.
|
|
151
|
+
Over budget ⇒ refuse with numbers. **Do not "remove the token measurement" for plans.** The measurement
|
|
152
|
+
is the only thing that keeps the refuse-with-numbers rule true; exempting a multi-K-token prose form
|
|
153
|
+
would make the 8K chapter target and the child's cold head meaningless on exactly the 32K hardware this
|
|
154
|
+
project targets. Economy comes from *carriage* (artifact + bounded head), not from blinding the meter.
|
|
155
|
+
|
|
156
|
+
### 5. `chapters_segment` reports the facts
|
|
157
|
+
|
|
158
|
+
Add to the output (`src/tools.ts:186-205`): `plans: [...]` (every field a model needs to choose ranges,
|
|
159
|
+
minus the text), `modeActive`, and `livePlans` — plans whose `seq > archiveCeiling` (an open turn:
|
|
160
|
+
precisely the mid-review case), explicitly labelled *not archived, parent log only*. Ranges stay the
|
|
161
|
+
model's call and chapter text stays the plugin's (invariant 4); the model never guesses a verdict again.
|
|
162
|
+
|
|
163
|
+
### 6. Composition and titles
|
|
164
|
+
|
|
165
|
+
- Forced split points: an `exit_plan_mode` call seq is a topic boundary — feed them to
|
|
166
|
+
`composeChapters` (`src/compose.ts:78`) so a plan is never buried mid-chapter.
|
|
167
|
+
- `deriveIdentity` prefers the plan H1 when a span opens with a submission (`src/engine-core.ts:251`);
|
|
168
|
+
`HARNESS_PROSE` (`:248`) stays as-is — a plan is not harness prose.
|
|
169
|
+
|
|
170
|
+
### 7. Config register (Schemastery `Config`, `src/index.ts:53-110`) — no hardcoded tunables
|
|
171
|
+
|
|
172
|
+
| Key | Default | Meaning |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `planInlineChars` | 900 | Verbatim head in the chapter block. The artifact holds the rest. 0 = pointer only. |
|
|
175
|
+
| `callArgArtifactTokens` | **0 (off)** | Above this, a tool-call argument is artifact-backed. |
|
|
176
|
+
| `plansInNotice` | true | Renders zero bytes when the path holds no plans. |
|
|
177
|
+
|
|
178
|
+
*Two amendments, both made by measurement rather than taste.*
|
|
179
|
+
|
|
180
|
+
- **`planModeEvents` was cut.** A `plan/mode` event is either printed in the Plans block or it is a
|
|
181
|
+
silently dropped byte, and silently dropped bytes are the one thing this store does not do. There is no
|
|
182
|
+
honest second value for that knob, so the rule is unconditional: the flip prints, and the folded state
|
|
183
|
+
lands in `planMode:`.
|
|
184
|
+
- **`callArgArtifactTokens` ships at 0, not 600.** Turning it on changes chapter bytes wherever a `write`
|
|
185
|
+
call carried a whole file — and the recorded model tapes are full of such turns (§ Tapes). Plans are
|
|
186
|
+
unaffected: their carriage is unconditional and named. A deployment that wants argument blobs opts in
|
|
187
|
+
deliberately, knowing it owes a re-record.
|
|
188
|
+
|
|
189
|
+
### 8. Search, and why no new index
|
|
190
|
+
|
|
191
|
+
A plan is discoverable through the **chapter that cites it**: the chapter's `topics` frontmatter is
|
|
192
|
+
already the index unit (`src/indexing.ts:140-152`, `src/search.ts:104`), so `chapters_search` returns
|
|
193
|
+
the chapter, whose body hands over the artifact path, and `chapters_artifact` (toc / search / read) does
|
|
194
|
+
the recursive descent — a Markdown plan has headings, so `action:'toc'` yields a line-numbered map for
|
|
195
|
+
free. **No second index** (hard rule; the TOC is the only index). Making plans corpus documents
|
|
196
|
+
(`kind: plan`, indexed like rules — the `sync.ts:203` "rules are chapters of a different kind, same
|
|
197
|
+
transport" precedent) stays deferred to § Deferred.
|
|
198
|
+
|
|
199
|
+
Registry note: **do not** use `state.plans` — that name is the compaction manifest
|
|
200
|
+
(`src/registry.ts:37`, `src/store.ts:67`). If a cross-session lookup is ever needed, name it
|
|
201
|
+
`submittedPlans`.
|
|
202
|
+
|
|
203
|
+
## Invariant audit
|
|
204
|
+
|
|
205
|
+
| Invariant | This design |
|
|
206
|
+
|---|---|
|
|
207
|
+
| 1 — never rewrite the durable log | Read-only over the log; artifacts and chapters are appends. Original plan events stay in the parent forever. |
|
|
208
|
+
| 2 — never seed from parent events | Unchanged: still one synthetic notice event at `seq 0` (decision 2 — no `plan/mode` seed). |
|
|
209
|
+
| 3 — never contribute a system-prompt section | The plans section is per-continuation notice text, not a header contribution. We only *read* plan mode's contribution. |
|
|
210
|
+
| 4 — never let the model author chapter bodies | The plan text is copied from the log by the plugin; the model supplies ranges and gets facts back. |
|
|
211
|
+
| Hard rules | No new index; no renumbering (plan blobs are content-addressed, chapters untouched); ranges still validated (`validateRanges`, `src/render.ts:96-123`); never truncate to fit — the head cap is a *display* choice with the full bytes retrievable, and the budget still refuses. |
|
|
212
|
+
|
|
213
|
+
## Tapes and e2e impact (measured, not assumed)
|
|
214
|
+
|
|
215
|
+
- `grep -rlo "exit_plan_mode\|plan mode\|plan-mode" tests/fixtures/` → **no hits** (2026-10-09). No
|
|
216
|
+
recorded scenario submits a plan, so a conditional plans section renders zero bytes in every replay:
|
|
217
|
+
**no re-record required** for the notice or renderer changes. Re-confirm after implementation — if a
|
|
218
|
+
product prompt *is* edited (personas, tool descriptions, notice text), the rule stands: re-record
|
|
219
|
+
**whole projects**, never one spec of a shared boot.
|
|
220
|
+
- New e2e project `plans` (own boot, own `E2E_PORT`, throwaway home `var/e2e-home-<port>`, one journey =
|
|
221
|
+
one boot — the fork- and fanout-carve-out lesson), recorded once with `npm run test:e2e:record`, then
|
|
222
|
+
replayed. Prompts must be tool-free **in words the model obeys** (the RR2 OOM lesson).
|
|
223
|
+
- Coverage: `npm run coverage:ci` gate (≥85 all four) must stay green; `src/plans.ts` is pure and gets a
|
|
224
|
+
full-branch row like the other planners, and the new `render.ts` arms need the success/refusal
|
|
225
|
+
surface covered the way the 2026-09-23 sweep did it.
|
|
226
|
+
|
|
227
|
+
## Verification rows to add to `docs/verify.md`
|
|
228
|
+
|
|
229
|
+
| # | Claim | Evidence |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| P1 | Verdict classification is right for all four shapes + superseded | `tests/unit/plans.test.ts` over host-shaped fixtures (mirror the real nesting the way `tests/unit/render.test.ts:18-22` mirrors tool-result shape) |
|
|
232
|
+
| P2 | A plan with no result is `pending`, and `pending` never renders as approval | unit + a notice golden test |
|
|
233
|
+
| P3 | Full plan bytes are retrievable: archive → artifact exists → `chapters_artifact` read returns them byte-identical (modulo redaction) | integration, same style as `corpus-hygiene.test.ts` |
|
|
234
|
+
| P4 | `plan/mode` no longer lands in `unrenderedSeqs`, and no other event type silently vanishes | `tests/unit/render.test.ts` rows (the `mystery/event` row at `:124-129` must stay) |
|
|
235
|
+
| P5 | The plans section is counted by `preflight` and an over-budget archive refuses **with numbers** | unit on `preflight` + integration on `runContinue` |
|
|
236
|
+
| P6 | A plan above the ceiling is reported as `livePlans` and carried, marked not-archived | integration on `chapters_segment` |
|
|
237
|
+
| P7 | Injected spans inside a plan body are screened; a plan quoting `AGENTS.md` in prose survives verbatim | `injections.test.ts` rows (H1 family) |
|
|
238
|
+
| P8 | Zero bytes when the path has no plans (tape neutrality) | notice golden test, both directions |
|
|
239
|
+
| P9 | Both carriage paths agree (continuation AND in-place engine compaction) | `tests/unit/plans-engine.test.ts` |
|
|
240
|
+
| P10 | A chapter's `artifacts/…` citation resolves whether the blob sits at the store root or inside the ancestry tree | `tests/unit/artifact-query.test.ts` + the integration row |
|
|
241
|
+
| P11 | The browser journey, once its tape is recorded | `tests/e2e/plans.spec.ts` (project `plans-dev`, self-skips without the live model) |
|
|
242
|
+
|
|
243
|
+
`docs/verify.md` § Plans Carriage is the ledger; this table is the design's own list of what it claims.
|
|
244
|
+
|
|
245
|
+
## Landing stages
|
|
246
|
+
|
|
247
|
+
| Stage | Deliverable | Status (2026-10-09) |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| 0 | This record lands; no code | done — reviewed, decisions 1–3 held |
|
|
250
|
+
| 1 | `src/plans.ts` + `src/log-shape.ts` (the shared pairing readers) + unit rows | done — P1/P2/P7 |
|
|
251
|
+
| 2 | `render.ts` Plans block + frontmatter + invocation artifacts; `docs/architecture.md` wording fix | done — P3/P4/P8 |
|
|
252
|
+
| 3 | `chapters_segment` facts + composer split points + `deriveIdentity` preference | done — P6 |
|
|
253
|
+
| 4 | `plansSection` in `assembleNotice` + wiring + config register | done — P5/P8/P9 |
|
|
254
|
+
| 5 | Site docs (§9 anatomy, §16 tools, §17 configuration, §18 notice) | done in the same release |
|
|
255
|
+
| — | Seven-segment tape replay | green WITHOUT re-recording (2026-10-09, `npm run test:e2e:replay`, EXIT=0) |
|
|
256
|
+
| — | `plans` browser journey | spec written as the `plans-dev` project; **awaits its tape** (no live Local model on this box — it self-skips, and is deliberately outside the CI chain until recorded) |
|
|
257
|
+
|
|
258
|
+
Deterministic ledger at landing: **549 unit+integration rows, zero failures** with the TreeDX container
|
|
259
|
+
up (80 of them new, across `plans`, `render-plans`, `continue-plans`, `plans-segmentation`, `plans-tools`,
|
|
260
|
+
`plans-engine`, `log-shape` and the `plans-carriage` integration), `npm run coverage:ci` **98.11 % stmts /
|
|
261
|
+
86.44 % branch / 93.8 % funcs** — the gate (≥85 on all four) green, branches *up* from the 85.61 % the
|
|
262
|
+
record started at. The seven-segment tape replay then ran against the BUILT artifacts: EXIT=0, 8 tests,
|
|
263
|
+
with no tape re-recorded.
|
|
264
|
+
|
|
265
|
+
### Two things the implementation found that the record had not predicted
|
|
266
|
+
|
|
267
|
+
- **`renderChapter` cannot pair a verdict inside its own range.** A composed chapter boundary can fall
|
|
268
|
+
between an `exit_plan_mode` call and the `tool/result` that answers it, so a range-local scan printed
|
|
269
|
+
APPROVED plans as PENDING — the exact inversion this feature exists to prevent. The scan therefore runs
|
|
270
|
+
over the whole event list the caller passes (`buildFinalizedChapters` now hands it the full shadowed
|
|
271
|
+
span instead of one chapter's slice) and only the *display* is range-filtered. Pinned by P9.
|
|
272
|
+
- **An ancestor path's plans cannot be ordered by `seq`.** Every session numbers its own events from zero,
|
|
273
|
+
so a root chapter's seq 40 and a child chapter's seq 3 are incomparable numbers, and sorting the notice
|
|
274
|
+
rows by seq would crown the wrong plan as operative — the exact failure mode the block exists to remove.
|
|
275
|
+
The rows therefore travel in **causal order**: the registry walk's root-first chapter sequence, plans
|
|
276
|
+
within a chapter by seq, then the caller's unarchived tail, and `buildPlansSection` prints that order and
|
|
277
|
+
takes the last row as operative without re-sorting. (This is the same flattening rule the chapter list
|
|
278
|
+
already follows — reading order IS causal order — applied to a new record type; pinned by a unit row.)
|
|
279
|
+
- **Deferred artifacts were already unreachable, for every blob, not just plans.** `writeArchive` writes
|
|
280
|
+
to `<storeRoot>/<rootSession>/artifacts/…`, the arrival stubber writes to `<storeRoot>/artifacts/…`, and
|
|
281
|
+
`resolveArtifactWithMirror` looked only at the second place plus the mirror — so a chapter's own
|
|
282
|
+
`artifacts/aa/<sha>.txt` citation, the standard form the body prints, could 404 on the machine that
|
|
283
|
+
wrote it. The resolver now walks the session trees between the store root and the mirror (P10), which
|
|
284
|
+
is what makes "every byte remains retrievable" true rather than intended.
|
|
285
|
+
|
|
286
|
+
## Deferred (human decisions, not ours)
|
|
287
|
+
|
|
288
|
+
- **`kind: plan` corpus documents** — makes plans first-class, topic-indexed, `chapters_search`-reachable
|
|
289
|
+
like rules; costs a chapter number per plan and is a `docs/knowledge-repo.md` amendment.
|
|
290
|
+
- **Seeding `plan/mode`** so a continuation is genuinely *in* plan mode (needs a probe against the
|
|
291
|
+
seed contract + the header effect, and a policy answer: should children be gated?).
|
|
292
|
+
- **Per-message anchoring** — a plan is the most natural anchor to fork from; `deriveRanges` already
|
|
293
|
+
supports any anchor, the button still forks at conversation end.
|
|
294
|
+
- Whether the `plan-mode` mode-switch *notice* should stay screened out of chapters (decision 2026-09-21
|
|
295
|
+
says injected context is not conversation; a human-initiated mode flip arguably is). Small text, but
|
|
296
|
+
it is the one place the blanket screen drops something a reader might want.
|
|
297
|
+
|
|
298
|
+
## Proposed AGENTS.md lines (deliberately NOT applied yet — it is the unimplemented-feature rule)
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
- `docs/plans-carriage.md` — **read before writing code in this area**: how a session plan reaches the
|
|
302
|
+
chapters, the TOC, and the artifact store; and why the token meter is never exempted.
|
|
303
|
+
```
|
|
304
|
+
plus a find-fast row `plans in chapters / active plan in TOC → docs/plans-carriage.md (+ site §§ notice, archive anatomy)`.
|
package/docs/verify.md
CHANGED
|
@@ -127,9 +127,31 @@ readability judgment.
|
|
|
127
127
|
| T11 | Git-plane auth honesty | a rejected credential (401/403) classifies as `auth`, never `network` — clone/pull/push carry it and the degrade-to-local-only status says `credentials rejected … re-link with /chapters-link`, not the unreachable-ghost (the TreeDX live lesson applied to git) | `git-auth-classification.test.ts` (5) over a REAL smart-HTTP remote with a token gate; classifier unit rows included |
|
|
128
128
|
| T12 | Corpus listing is complete | `paths/list` paginates (limit 100, base64 offset cursor) — `corpusPaths` follows `nextCursor` to the end; a second machine materializes EVERY file past a page boundary | `treedx-sync.test.ts` pagination row (150 files over the paginating stub); the live container (>100 paths) proves it at the real service |
|
|
129
129
|
| T13 | The human entry surface | `/chapters-link` all four modes incl. refusals (no-token non-loopback, junk target), `/chapters-status` renders each fact ONCE (a duplicate-`Provider:` line was caught here), `/chapters-enrich` verbs, legacy workspace-token migration to the DSH home (0600, old file deleted) | `link-git-commands.test.ts` (11), `token-migration.test.ts` (4) |
|
|
130
|
-
| COV | Both coverage ledgers are statement-grade and run | `npm run coverage:ci` — the GATED deterministic ledger (c8 over all unit+integration, `--check-coverage` at 85% statements/branches/functions/lines; enforced in hosted CI, which is GREEN end to end 2026-09-25) — currently **
|
|
130
|
+
| COV | Both coverage ledgers are statement-grade and run | `npm run coverage:ci` — the GATED deterministic ledger (c8 over all unit+integration, `--check-coverage` at 85% statements/branches/functions/lines; enforced in hosted CI, which is GREEN end to end 2026-09-25) — currently **98.11% stmts / 86.44% branch / 93.8% funcs @ 549 tests, zero skips with the TreeDX container up** (the plans-carriage work added 80 rows and RAISED branch coverage from the 85.61% this row used to quote). `npm run coverage:e2e` — seven-project replay under E2E_COVERAGE=1; boots run lib/*.js with REAL source maps (tsconfig `sourceMap`) remapped by c8/v8-to-istanbul; first ledger **80% stmts / 62% branches / 74% funcs** — it corrected the earlier line-range estimate honestly (tools.ts 99% lines → 72% statements). The 2026-09-23 audit then closed most of that gap at the DETERMINISTIC plane: the engine's construction/listeners/degraded-summarize/plot-elicit/finalize-guard paths (`engine-lifecycle.test.ts` — real cordis `Context()`, real base engine, injected llm/tokenMeter fakes: engine.ts 40→91% stmts), every tool wrapper's success/refusal/missing-caller surface (`tools-surface` + `tools-branches` + `tools-deep-branches`), the TreeDX error taxonomy via one-shot stub faults (`treedx-provider-branches`) and parser-shape drift via injected `fetchImpl` (`treedx-parser-branches`), the local-path git transport arms (`gitops-branches`), host-command error arms (`host-command-branches`), and the pure planners (vocabulary/enrich/indexing/search/arrival/archive — `rules-vocab-branches`, `enrich-planner-branches`, `indexing-branches`, `notice-search-rules-branches`, `render-archive-ladder-branches`, `pure-branches`). It also caught one REAL bug on the way: `canonicalizeRemote` carried embedded `user:token@` credentials into the project key (pasting a remote with and without creds forked the pool — now stripped, pinned in `pure-branches.test.ts`). Gotchas pinned in the script header: c8 filters include/exclude BEFORE remapping (`--include=src/**` against lib-path profiles zeroes the report). Neither ledger alone is the claim; the e2e one makes index/render-in-browser paths that no deterministic test can see accountable |
|
|
131
131
|
| H1 | Corpus carries no project instructions | host-injected context (instruction files, runtime snapshot, skill catalog, our own TOC notice — event-level AND `<system-reminder>` spans inside human messages) renders as a countable `⟦omitted:host-injected …⟧` marker, never bytes; conversation survives verbatim and byte-identical | unit `injections.test.ts` (15) + `render.test.ts` rows; integration `corpus-hygiene.test.ts` (archive→sync→remote→pull→search sentinel-absence, and legacy-store-publishes-unchanged anti-migration guard); e2e stays AGENTS-BLIND (tape masking) |
|
|
132
132
|
|
|
133
|
+
|
|
134
|
+
## Plans Carriage (docs/plans-carriage.md, implemented 2026-10-09)
|
|
135
|
+
|
|
136
|
+
A session plan is one `tool/call` for `exit_plan_mode` whose `arguments.plan` carries the whole
|
|
137
|
+
markdown, answered by a `tool/result` that carries the human verdict. There is no plan document in
|
|
138
|
+
the log, so EVERY row below is about reading those two events the same way in three places — the
|
|
139
|
+
renderer, the segmentation tool, and the child's notice.
|
|
140
|
+
|
|
141
|
+
| # | Check | Passes when | Evidence |
|
|
142
|
+
|---|---|---|---|
|
|
143
|
+
| P1 | Verdict classification is right for every host shape | approved (`{approved:true}` / the fixed render text), rejected ("keep planning" + feedback), dismissed (takeover text), `failed` (the review never opened: no channel, service reloaded, outside plan mode, no `#` heading), pending (NO result event) — and a `superseded` rule that only fires for a same-title later submission | unit `plans.test.ts` (23) over fixtures copied from `@deepseek-ai/dsh-plan-mode/lib/index.js:230-289`; the pairing primitives are pinned separately in `log-shape.test.ts` (7) |
|
|
144
|
+
| P2 | `pending` is never printable as approval | a plan with no result renders "NO RESULT: the review was never answered"; the notice adds "do NOT implement it", and the word `approved` appears nowhere in that row | unit `plans.test.ts` + `render-plans.test.ts` + `continue-plans.test.ts`; integration notice assertion |
|
|
145
|
+
| P3 | Full plan bytes are retrievable | archive → the artifact file EXISTS on disk → its bytes equal the submitted plan (modulo the § 9 redaction chokepoint) → `chapters_artifact` `toc` lists the plan's own headings with line numbers and `search` reaches a phrase by SHA alone | integration `plans-carriage.test.ts` (4, real `node:fs` + real registry domain); unit `render-plans.test.ts`, `plans-engine.test.ts` (engine path parity: the same block from `buildFinalizedChapter(s)`) |
|
|
146
|
+
| P4 | `plan/mode` is not a silent hole | the event renders as a `mode` line, folds last-value-wins into `planMode:` frontmatter/record, and stays OUT of `unrenderedSeqs` — while an unnamed event type STILL lands there | unit `render-plans.test.ts` + `plans-engine.test.ts`; the pre-existing `render.test.ts` `mystery/event` row is unchanged |
|
|
147
|
+
| P5 | The plans block is MEASURED, never exempted | with the block on, the same archive REFUSES at a budget where the block-off variant passes; refusal carries both numbers | unit `continue-plans.test.ts` (the paired-measurement row); `preflight` untouched (`src/continue-core.ts:147-161`) |
|
|
148
|
+
| P6 | A plan above the ceiling is carried and named | `chapters_segment` returns `livePlans` (seq > `archiveCeiling`) and `modeActive`; the notice prints `NOT ARCHIVED — parent log seq N only`, and promises no artifact for bytes the store does not hold | unit `plans-tools.test.ts` (4) + `continue-plans.test.ts`; integration `plans-carriage.test.ts` (the open-review row) |
|
|
149
|
+
| P7 | Plan bodies obey the injection screen | a `<system-reminder>` span inside a plan is removed (countable marker upstream), while a plan that QUOTES `AGENTS.md` in prose survives verbatim — and credential patterns are redacted in BOTH the printed head and the stored blob | unit `plans.test.ts` + `render-plans.test.ts` (H1 family) |
|
|
150
|
+
| P8 | A plan-less path is byte-identical to pre-feature | no `## Plans in this chapter` block, no `plans:`/`planMode:` frontmatter lines, no `## Plans` in the notice, and `chapters_segment` emits no `planHint` — the whole feature is conditional on there being a plan | unit `render-plans.test.ts`, `continue-plans.test.ts`, `plans-segmentation.test.ts`, `plans-tools.test.ts`; integration `plans-carriage.test.ts` |
|
|
151
|
+
| P9 | Both carriage paths agree | the CONTINUATION path (`chapters_continue`) and the ENGINE path (in-place `summarize`/finalize) render the same block and the same record facts, including a verdict that lands past a composed chapter boundary — which is why `renderChapter` scans the whole event list, not its own range | unit `plans-engine.test.ts` (5) + `render-plans.test.ts`; zod round-trip of `plans`/`planMode` through the registry in `plans-engine.test.ts`, legacy rows gaining nothing |
|
|
152
|
+
| P10 | Artifact citations resolve wherever they were written | a chapter's `artifacts/aa/<sha>.txt` reference resolves whether the blob sits at the STORE ROOT (arrival stubs) or inside the ANCESTRY TREE (`<store>/<root>/artifacts/…`, where `writeArchive` puts deferred results and every plan) — before this fix the second form was unreadable through `chapters_artifact`, which is what "every byte remains retrievable" actually promised | `artifact-query.test.ts` rows + integration `plans-carriage.test.ts` (`resolveArtifactWithMirror` over the real tree) |
|
|
153
|
+
| P11 | The browser plane, once recorded | `/plan <message>` → model submits → user approves in the plan-review card → fork → the child's own log carries `ACTIVE PLAN: … APPROVED` and the plan blob exists with its full bytes | `tests/e2e/plans.spec.ts` (project `plans-dev`) — SELF-SKIPS without the live Local model; NOT in the CI chain until its tape is recorded on the GPU box (docs/plans-carriage.md § Tapes) |
|
|
154
|
+
|
|
133
155
|
## The Cache Metric, Before You Trust a Number
|
|
134
156
|
|
|
135
157
|
`usage.inputTokens` is the **uncached delta** and `usage.cacheReadTokens` is the cached prefix, so:
|
package/lib/archive.d.ts
CHANGED
|
@@ -48,6 +48,15 @@ export interface ChapterRecord {
|
|
|
48
48
|
sha256: string;
|
|
49
49
|
bytes: number;
|
|
50
50
|
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Plans this chapter carries (docs/plans-carriage.md § 2/§ 8): the durable,
|
|
53
|
+
* machine-readable half of the Plans block. Absent on records written before
|
|
54
|
+
* the feature — the notice reads `undefined` as "no plans here", never as a
|
|
55
|
+
* lie. The full bytes live in the cited artifact; the prose lives in the file.
|
|
56
|
+
*/
|
|
57
|
+
plans?: import('./types.ts').PlanFact[] | undefined;
|
|
58
|
+
/** Folded plan-mode state at the chapter's end ('unknown' when the log never said). */
|
|
59
|
+
planMode?: 'active' | 'inactive' | 'unknown' | undefined;
|
|
51
60
|
}
|
|
52
61
|
export interface WriteResult {
|
|
53
62
|
records: ChapterRecord[];
|
package/lib/archive.js
CHANGED
|
@@ -80,6 +80,11 @@ export async function writeArchive(input) {
|
|
|
80
80
|
sha256: bodyHash,
|
|
81
81
|
estimatedTokens: chapter.stats.estimatedTokens,
|
|
82
82
|
artifacts: chapter.artifacts.map((a) => ({ path: join(treeDir, a.path), sha256: a.sha256, bytes: a.bytes })),
|
|
83
|
+
// Plans ride along ONLY when the chapter has them: an absent field means
|
|
84
|
+
// "no plans here" for a pre-feature record, and an empty array here would
|
|
85
|
+
// be read as a fact by the notice builder.
|
|
86
|
+
...(chapter.stats.plans !== undefined && chapter.stats.plans.length > 0 ? { plans: chapter.stats.plans } : {}),
|
|
87
|
+
...(chapter.stats.planMode !== undefined && chapter.stats.planMode !== 'unknown' ? { planMode: chapter.stats.planMode } : {}),
|
|
83
88
|
});
|
|
84
89
|
}
|
|
85
90
|
return { records, artifactPathsWritten, warnings };
|
package/lib/archive.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"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"}
|
package/lib/artifact-query.js
CHANGED
|
@@ -149,6 +149,26 @@ export function resolveArtifactWithMirror(storeDir, ref, mirrorDir) {
|
|
|
149
149
|
})();
|
|
150
150
|
if (tail === null || tail.split(/[\\/]/).includes('..'))
|
|
151
151
|
return null;
|
|
152
|
+
// Session trees FIRST (measured 2026-10-09, plans-carriage): a chapter defers a
|
|
153
|
+
// result — or a plan's full text — to `artifacts/<aa>/<sha>.txt`, and
|
|
154
|
+
// archive.writeArchive writes it under the ANCESTRY TREE directory
|
|
155
|
+
// (<storeRoot>/<rootSession>/artifacts/…), not the store root where arrival
|
|
156
|
+
// stubs live. Before this, every such citation pointed at a path
|
|
157
|
+
// chapters_artifact could not resolve, so 'every byte remains retrievable'
|
|
158
|
+
// held only on the machine and directory layout that happened to match.
|
|
159
|
+
if (fs.existsSync(storeDir)) {
|
|
160
|
+
for (const entry of fs.readdirSync(storeDir, { withFileTypes: true })) {
|
|
161
|
+
if (!entry.isDirectory() || entry.name.startsWith('.'))
|
|
162
|
+
continue;
|
|
163
|
+
const cand = path.join(storeDir, entry.name, 'artifacts', tail);
|
|
164
|
+
const root = path.resolve(storeDir);
|
|
165
|
+
const resolved = path.resolve(cand);
|
|
166
|
+
if (resolved !== root && !resolved.startsWith(root + path.sep))
|
|
167
|
+
continue;
|
|
168
|
+
if (fs.existsSync(cand))
|
|
169
|
+
return cand;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
152
172
|
const artRoot = path.join(mirrorDir, 'artifacts');
|
|
153
173
|
if (!fs.existsSync(artRoot))
|
|
154
174
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-query.js","sourceRoot":"","sources":["../src/artifact-query.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"artifact-query.js","sourceRoot":"","sources":["../src/artifact-query.ts"],"names":[],"mappings":"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"}
|
package/lib/compose.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* relabel later, never re-chapter (append-only, §4.4).
|
|
18
18
|
*/
|
|
19
19
|
import { deriveIdentity } from "./engine-core.js";
|
|
20
|
+
import { detectPlans } from "./plans.js";
|
|
20
21
|
const union = (a, b) => new Set([...a, ...b]);
|
|
21
22
|
const inter = (a, b) => {
|
|
22
23
|
const set = new Set(a);
|
|
@@ -86,17 +87,45 @@ export function composeChapters(events, spanStart, spanEnd, collections, config)
|
|
|
86
87
|
return a === b || a.startsWith(b + '.') || b.startsWith(a + '.');
|
|
87
88
|
};
|
|
88
89
|
const primaryMatch = (c, r) => primaryEq(primaryOf(c), primaryOf(r.first)) || primaryEq(primaryOf(c), primaryOf(r.last));
|
|
90
|
+
// A plan submission is the strongest topic boundary a log contains: the
|
|
91
|
+
// planning work CONCLUDES with it (docs/plans-carriage.md § 6), so the
|
|
92
|
+
// collection that carries one closes its chapter and the implementation that
|
|
93
|
+
// follows opens the next. Deterministic, collection-granular, no model call.
|
|
94
|
+
const planSeqs = detectPlans(events.filter((e) => e.seq >= spanStart && e.seq <= spanEnd)).plans
|
|
95
|
+
.map((p) => p.seq);
|
|
96
|
+
const holdsPlan = (lo, hi) => planSeqs.some((sq) => sq >= lo && sq <= hi);
|
|
97
|
+
const firstPlanTitleIn = (lo, hi) => {
|
|
98
|
+
const hit = detectPlans(events.filter((e) => e.seq >= lo && e.seq <= hi)).plans[0];
|
|
99
|
+
return hit !== undefined && hit.title !== '' ? hit.title : undefined;
|
|
100
|
+
};
|
|
89
101
|
const chapters = [];
|
|
90
102
|
let running = runningOf(usable[0]);
|
|
103
|
+
// True after a plan closed the chapter: the NEXT collection opens the next
|
|
104
|
+
// chapter, it is never merged backwards (and never re-added — a duplicate
|
|
105
|
+
// range would archive the same text twice, which validateRanges refuses).
|
|
106
|
+
let closedAtPlan = false;
|
|
91
107
|
for (const c of usable.slice(1)) {
|
|
108
|
+
if (closedAtPlan) {
|
|
109
|
+
running = runningOf(c);
|
|
110
|
+
closedAtPlan = false;
|
|
111
|
+
if (holdsPlan(running.startSeq, running.endSeq)) {
|
|
112
|
+
close();
|
|
113
|
+
closedAtPlan = true;
|
|
114
|
+
}
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
92
117
|
// r28 (first live topic test): overlap Jaccard ALONE never reaches τ on
|
|
93
118
|
// real research turns — a same-topic pair touching 5–6 files each scores
|
|
94
119
|
// ~0.08 because one shared path dilutes in a union of ~10. The signal
|
|
95
120
|
// that actually separates is the PRIMARY path (paths[0]: the first file
|
|
96
121
|
// the turn touched): identical across the render pair, distinct at every
|
|
97
122
|
// topic change. Merge on (score ≥ τ) OR (primary match).
|
|
123
|
+
// A chapter that already holds a plan is CLOSED: the submission concludes the
|
|
124
|
+
// planning, so the next turn opens the next chapter even when the topic
|
|
125
|
+
// overlaps. (Merging into a plan-bearing chapter would bury the decision.)
|
|
98
126
|
const merge = (scoreAgainst(c, running) >= config.mergeThreshold || primaryMatch(c, running))
|
|
99
|
-
&& running.size + c.size <= config.chapterLimit
|
|
127
|
+
&& running.size + c.size <= config.chapterLimit
|
|
128
|
+
&& !holdsPlan(running.startSeq, running.endSeq);
|
|
100
129
|
if (merge) {
|
|
101
130
|
for (const p of c.paths)
|
|
102
131
|
running.paths.add(p);
|
|
@@ -112,12 +141,18 @@ export function composeChapters(events, spanStart, spanEnd, collections, config)
|
|
|
112
141
|
close();
|
|
113
142
|
running = runningOf(c);
|
|
114
143
|
}
|
|
144
|
+
// The chapter that carries a plan ENDS there (docs/plans-carriage.md § 6).
|
|
145
|
+
if (holdsPlan(running.startSeq, running.endSeq)) {
|
|
146
|
+
close();
|
|
147
|
+
closedAtPlan = true;
|
|
148
|
+
}
|
|
115
149
|
}
|
|
116
|
-
|
|
150
|
+
if (!closedAtPlan)
|
|
151
|
+
close();
|
|
117
152
|
function close() {
|
|
118
153
|
const lo = running.startSeq;
|
|
119
154
|
const hi = running.endSeq;
|
|
120
|
-
const identity = deriveIdentity(messagesOf(events, lo, hi), false);
|
|
155
|
+
const identity = deriveIdentity(messagesOf(events, lo, hi), false, firstPlanTitleIn(lo, hi));
|
|
121
156
|
const pathsHint = [...running.paths].slice(0, 3).join(', ');
|
|
122
157
|
chapters.push({
|
|
123
158
|
title: identity.title,
|
package/lib/compose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,cAAc,EAAsB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
|