@treeseed/dsh-chapters 0.1.24 → 0.2.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.
Files changed (103) hide show
  1. package/README.md +2 -1
  2. package/cordis.patch.yml +49 -1
  3. package/docs/architecture.md +1 -496
  4. package/docs/backlog.md +234 -4
  5. package/docs/contract.md +127 -1
  6. package/docs/development.md +248 -12
  7. package/docs/host-compaction-seam.md +108 -0
  8. package/docs/knowledge-repo.md +532 -16
  9. package/docs/project-state.md +323 -0
  10. package/docs/verify.md +266 -0
  11. package/lib/archive.d.ts +49 -1
  12. package/lib/archive.js +56 -2
  13. package/lib/archive.js.map +1 -1
  14. package/lib/arrival.js +24 -10
  15. package/lib/arrival.js.map +1 -1
  16. package/lib/attach.d.ts +46 -0
  17. package/lib/attach.js +120 -0
  18. package/lib/attach.js.map +1 -0
  19. package/lib/auto-save.d.ts +74 -0
  20. package/lib/auto-save.js +175 -26
  21. package/lib/auto-save.js.map +1 -1
  22. package/lib/client.js +413 -11
  23. package/lib/client.js.map +1 -1
  24. package/lib/commands.d.ts +8 -1
  25. package/lib/commands.js +135 -7
  26. package/lib/commands.js.map +1 -1
  27. package/lib/compose.js +25 -6
  28. package/lib/compose.js.map +1 -1
  29. package/lib/continue-core.d.ts +24 -1
  30. package/lib/continue-core.js +41 -9
  31. package/lib/continue-core.js.map +1 -1
  32. package/lib/diag.d.ts +55 -0
  33. package/lib/diag.js +186 -0
  34. package/lib/diag.js.map +1 -0
  35. package/lib/engine-core.d.ts +53 -1
  36. package/lib/engine-core.js +64 -7
  37. package/lib/engine-core.js.map +1 -1
  38. package/lib/engine.d.ts +99 -0
  39. package/lib/engine.js +488 -36
  40. package/lib/engine.js.map +1 -1
  41. package/lib/enrich-queue.js +28 -2
  42. package/lib/enrich-queue.js.map +1 -1
  43. package/lib/enrich-wire.d.ts +92 -2
  44. package/lib/enrich-wire.js +135 -17
  45. package/lib/enrich-wire.js.map +1 -1
  46. package/lib/enrich.d.ts +27 -2
  47. package/lib/enrich.js +114 -18
  48. package/lib/enrich.js.map +1 -1
  49. package/lib/index.d.ts +52 -0
  50. package/lib/index.js +182 -2
  51. package/lib/index.js.map +1 -1
  52. package/lib/indexing.d.ts +7 -0
  53. package/lib/indexing.js.map +1 -1
  54. package/lib/injections.d.ts +1 -0
  55. package/lib/injections.js +38 -0
  56. package/lib/injections.js.map +1 -1
  57. package/lib/last-resort.d.ts +24 -0
  58. package/lib/last-resort.js +27 -0
  59. package/lib/last-resort.js.map +1 -0
  60. package/lib/prompt.d.ts +130 -0
  61. package/lib/prompt.js +255 -0
  62. package/lib/prompt.js.map +1 -0
  63. package/lib/registry.d.ts +39 -1
  64. package/lib/registry.js +76 -9
  65. package/lib/registry.js.map +1 -1
  66. package/lib/render.d.ts +31 -3
  67. package/lib/render.js +75 -3
  68. package/lib/render.js.map +1 -1
  69. package/lib/repair-run.d.ts +49 -0
  70. package/lib/repair-run.js +423 -0
  71. package/lib/repair-run.js.map +1 -0
  72. package/lib/repair.d.ts +200 -0
  73. package/lib/repair.js +354 -0
  74. package/lib/repair.js.map +1 -0
  75. package/lib/rules-commands.d.ts +22 -0
  76. package/lib/rules-commands.js +177 -20
  77. package/lib/rules-commands.js.map +1 -1
  78. package/lib/rules.d.ts +184 -7
  79. package/lib/rules.js +312 -27
  80. package/lib/rules.js.map +1 -1
  81. package/lib/save-core.d.ts +31 -1
  82. package/lib/save-core.js +153 -17
  83. package/lib/save-core.js.map +1 -1
  84. package/lib/session-rules.d.ts +222 -0
  85. package/lib/session-rules.js +454 -0
  86. package/lib/session-rules.js.map +1 -0
  87. package/lib/store.d.ts +22 -1
  88. package/lib/store.js +94 -17
  89. package/lib/store.js.map +1 -1
  90. package/lib/sync.js +13 -1
  91. package/lib/sync.js.map +1 -1
  92. package/lib/tools.d.ts +14 -0
  93. package/lib/tools.js +321 -32
  94. package/lib/tools.js.map +1 -1
  95. package/lib/types.d.ts +12 -1
  96. package/lib/types.js.map +1 -1
  97. package/lib/version.d.ts +9 -0
  98. package/lib/version.js +10 -0
  99. package/lib/version.js.map +1 -0
  100. package/lib/warnings.d.ts +10 -0
  101. package/lib/warnings.js +18 -0
  102. package/lib/warnings.js.map +1 -0
  103. package/package.json +9 -3
package/lib/save-core.js CHANGED
@@ -14,26 +14,95 @@
14
14
  */
15
15
  import { composeChapters } from "./compose.js";
16
16
  import { deriveRanges } from "./continue-core.js";
17
- import { renderChapter } from "./render.js";
17
+ import { estimateTokens, oversizeRanges, renderChapter } from "./render.js";
18
18
  import { chapterTopics } from "./signature.js";
19
19
  import { makeArchiveFs, commitChapters } from "./store.js";
20
- import { reserve, reservePlan as reservePlanNumber } from "./registry.js";
20
+ import { releaseReservation, reserve, reservePlan as reservePlanNumber } from "./registry.js";
21
+ /** One serialized read-allocate-write for a door that cannot use makeAllocator (same rule, #59). */
22
+ async function reserveNumbers(store, sessionId, attemptId, count, plan = false) {
23
+ let numbers = [];
24
+ await store.mutate(sessionId, (state) => {
25
+ const r = plan ? reservePlanNumber(state, attemptId, count) : reserve(state, attemptId, count);
26
+ numbers = r.numbers;
27
+ return r.state;
28
+ });
29
+ return { numbers };
30
+ }
21
31
  import { writeArchive, attemptKey } from "./archive.js";
32
+ import { supersedeChapter } from "./repair.js";
33
+ /**
34
+ * Split a range whose RENDERED size would blow past the oversize ceiling (#60, repair path only).
35
+ *
36
+ * The normal doors cut on `turn/end` and warn when a chapter is over `chapterTokenTarget`, because a
37
+ * boundary is around the corner and clipping is forbidden. A REPAIR span can be one gigantic turn — a
38
+ * delegated subagent whose single turn ran to 4 MB — where there IS no next boundary, and refusing it
39
+ * (the #59c gate) would leave the husk superseded-by-nothing. So the repair splits at EVENT boundaries
40
+ * inside the turn: nothing is truncated, every byte still lands in a chapter, and the TOC gains several
41
+ * consecutive ranges instead of one unreadable one. The rule that binds is completeness, not "one chapter
42
+ * per turn" — and a chapter nobody can `read` back is not an archive.
43
+ */
44
+ function splitOversize(chapters, events, chapterTokenTarget, oversizeFactor) {
45
+ const ceiling = Math.floor(chapterTokenTarget * oversizeFactor);
46
+ const notes = [];
47
+ const out = [];
48
+ for (const c of chapters) {
49
+ const inRange = events.filter((e) => e.seq >= c.startSeq && e.seq <= c.endSeq);
50
+ const total = inRange.reduce((m, e) => m + estimateTokens(JSON.stringify(e.data ?? {})), 0);
51
+ if (total <= ceiling) {
52
+ out.push(c);
53
+ continue;
54
+ }
55
+ const parts = Math.ceil(total / ceiling);
56
+ const perPart = Math.ceil(inRange.length / parts);
57
+ let title = c.title;
58
+ for (let i = 0, n = 0; i < inRange.length; i += perPart, n++) {
59
+ const from = inRange[i].seq;
60
+ const to = inRange[Math.min(i + perPart, inRange.length) - 1].seq;
61
+ out.push({ ...c, title: n === 0 ? title : `${title} (part ${n + 1})`, startSeq: from, endSeq: to });
62
+ }
63
+ notes.push(`"${c.title}" (seqs ${c.startSeq}-${c.endSeq}) is ${total} est tokens in a single unfinished turn — split into ${parts} chapters at event boundaries (repair path; nothing truncated)`);
64
+ }
65
+ return { ranges: out, notes };
66
+ }
67
+ /**
68
+ * Force a repaired archive to cover exactly the span the finding named (#60). Composition may still cut
69
+ * it into topics - a cut is a chapter boundary, not a loss - but nothing may start above `fromSeq` or
70
+ * stop before the last completed turn inside the span, or the hole the finding reported stays open while
71
+ * the repair reports success.
72
+ */
73
+ function clampSpan(chapters, fromSeq, toSeq, events) {
74
+ // Nothing to clamp: the span held no completed turn at all. Returning EMPTY is the honest answer —
75
+ // inventing a title here would fabricate a chapter, and an empty `records` makes the caller skip the
76
+ // supersede, which is exactly right: a record is never marked superseded without its replacement (#60).
77
+ if (chapters.length === 0)
78
+ return [];
79
+ const lastCompleted = events.reduce((m, e) => (e.type === 'turn/end' && e.seq <= toSeq && e.seq > m ? e.seq : m), fromSeq);
80
+ return chapters.map((c, i) => ({
81
+ ...c,
82
+ startSeq: i === 0 ? Math.min(c.startSeq, fromSeq) : Math.max(c.startSeq, chapters[i - 1].endSeq + 1),
83
+ endSeq: i === chapters.length - 1 ? lastCompleted : Math.min(c.endSeq, lastCompleted),
84
+ }));
85
+ }
22
86
  export async function saveSession(a) {
23
87
  const { events, sessionId, cwd, store, config } = a;
24
88
  if (cwd === '')
25
89
  throw new Error('saveSession: session has no workspace cwd — nowhere reachable to write');
26
90
  if (sessionId === '')
27
91
  throw new Error('saveSession: no session id to own the archive');
28
- const anchor = [...events].reverse().find((e) => e.type === 'turn/end')?.seq;
92
+ // A repair targets a span it chose; every other door archives the watermark tail up to the last
93
+ // completed turn. One pipeline, one difference (#60).
94
+ const anchor = a.span !== undefined ? a.span.toSeq : [...events].reverse().find((e) => e.type === 'turn/end')?.seq;
29
95
  if (anchor === undefined) {
30
96
  return { skipped: 'no-completed-turn', fromSeq: 0, anchor: -1, lastArchived: 0, priorChapters: 0, records: [], warnings: [] };
31
97
  }
32
98
  // Watermark: only archive what is newer than the last saved chapter.
33
99
  const state = await store.get(sessionId);
34
100
  const lastArchived = state.chapters.reduce((m, c) => Math.max(m, c.endSeq), 0);
35
- const fromSeq = lastArchived > 0 ? lastArchived + 1 : 0;
36
- if (fromSeq > 0 && anchor <= lastArchived) {
101
+ const fromSeq = a.span !== undefined ? a.span.fromSeq : (lastArchived > 0 ? lastArchived + 1 : 0);
102
+ // A REPAIR span is deliberate re-derivation of seqs the watermark has already passed (#60): the
103
+ // nothing-new guard is about not re-archiving a tail, and would otherwise refuse to fix the hole a
104
+ // hollow chapter sits exactly on top of. The span caller has already decided what needs re-rendering.
105
+ if (a.span === undefined && fromSeq > 0 && anchor <= lastArchived) {
37
106
  return { skipped: 'nothing-new', fromSeq, anchor, lastArchived, priorChapters: state.chapters.length, records: [], warnings: [] };
38
107
  }
39
108
  // Topic-sequential composition — same pipeline as fork/continue.
@@ -41,9 +110,21 @@ export async function saveSession(a) {
41
110
  mergeThreshold: config.mergeThreshold,
42
111
  chapterLimit: config.chapterLimit,
43
112
  });
44
- const chapters = composed.chapters.length > 0
113
+ let chapters = composed.chapters.length > 0
45
114
  ? composed.chapters
46
115
  : deriveRanges(events, anchor, config.chapterTokenTarget, fromSeq).chapters;
116
+ const repairNotes = [];
117
+ if (a.span !== undefined) {
118
+ // A repair's span is bounded by the finding, so force exactly that range: composition inside a hole
119
+ // may cut it into topics, and a cut is fine, but nothing may start above `fromSeq` or end below the
120
+ // last completed turn inside the span.
121
+ chapters = clampSpan(chapters, a.span.fromSeq, a.span.toSeq, events);
122
+ // A repair span may be one enormous turn; the oversize gate would refuse it and leave the husk
123
+ // un-replaced. Split inside it at event boundaries — see `splitOversize`.
124
+ const split = splitOversize(chapters, events, config.chapterTokenTarget, config.chapterOversizeFactor ?? 2);
125
+ chapters = split.ranges;
126
+ repairNotes.push(...split.notes);
127
+ }
47
128
  // Render + write archive (same as runContinue steps 2-3, minus child creation).
48
129
  const below = events.filter((e) => e.seq <= anchor);
49
130
  const renderConfig = {
@@ -54,31 +135,86 @@ export async function saveSession(a) {
54
135
  ...(a.subagentOf !== undefined && a.subagentOf !== '' ? { subagentOf: a.subagentOf } : {}),
55
136
  };
56
137
  const rendered = chapters.map((range) => renderChapter(below, range, renderConfig, [], chapterTopics(below, range.startSeq, range.endSeq)));
138
+ // #58 — NEVER commit an archive that rendered nothing. A `tool/call` is always preceded by an
139
+ // `assistant/message`, so a non-empty range with zero rendered messages is not a short
140
+ // conversation: it is a read that carried no payloads. The real instance was
141
+ // `sessionQuery.listEvents`, whose `SessionEventRecord` rows have `seq`/`type`/`time`/`surface`
142
+ // and no `data` — 12 children on this machine archived as `**unknown**` / `{}` / `0 B` shells.
143
+ // The refusal is BEFORE `writeArchive`, so no number is reserved and no file is written: a
144
+ // committed husk would poison the watermark (`max(endSeq)`), and the child could then never be
145
+ // re-archived without a repair (#60). Refuse with numbers, never truncate — AGENTS.md.
146
+ //
147
+ // AMENDED #60: the test is on the ARCHIVE, not on each chapter. A repair may split one enormous turn
148
+ // into consecutive parts, and a part holding only tool calls legitimately renders zero messages —
149
+ // refusing the whole re-read over that stranded five SAIP children's knowledge again, which is the
150
+ // opposite of what the gate protects. "No payloads anywhere" is the anomaly; `describeHollow` keeps
151
+ // naming every message-free part so it is never silent, and the single-chapter case (#58's instance)
152
+ // still refuses exactly as before.
153
+ const describeHollow = (r) => {
154
+ const un = r.stats.unrenderedSeqs;
155
+ return `"${r.range.title}" spans seqs ${r.range.startSeq}..${r.range.endSeq}: ${r.stats.events} events, `
156
+ + `${r.stats.toolCalls} tool calls, 0 rendered messages, ${un.length} unrendered`
157
+ + `${un.length > 0 ? ` (first: ${un.slice(0, 5).join(', ')})` : ''}`;
158
+ };
159
+ const hollow = rendered.filter((r) => r.stats.events > 0 && r.stats.messages === 0);
160
+ if (rendered.length > 0 && hollow.length === rendered.length) {
161
+ return {
162
+ skipped: 'payloadless',
163
+ fromSeq,
164
+ anchor,
165
+ lastArchived,
166
+ priorChapters: state.chapters.length,
167
+ records: [],
168
+ warnings: hollow.map((r) => `${describeHollow(r)} — the read carried event SHAPES but no payloads; nothing was reserved or written`),
169
+ };
170
+ }
171
+ // Parts that carry tool calls but no prose are reported and STILL archived (#60): "what was
172
+ // attempted" is half the record, and silence about it is the defect class this issue is named for.
173
+ const hollowNotes = hollow.map((r) => `${describeHollow(r)} — archived for its tool calls, not a payload failure`);
174
+ // #59: refuse before reserving anything, exactly like the payloadless gate — a spent number with no
175
+ // file behind it is the burned-reservation state this whole round is eliminating. The factor is
176
+ // config, never a literal: over `chapterTokenTarget` warns, over `target × factor` refuses.
177
+ const tooBig = oversizeRanges(rendered, config.chapterTokenTarget, config.chapterOversizeFactor ?? 2);
178
+ if (tooBig.length > 0) {
179
+ return {
180
+ skipped: 'oversize', fromSeq, anchor, lastArchived,
181
+ priorChapters: state.chapters.length, records: [], warnings: tooBig,
182
+ };
183
+ }
57
184
  const wrote = await writeArchive({
58
185
  fs: makeArchiveFs(cwd),
59
186
  allocator: {
187
+ // One section per allocation (#59) — identical semantics to makeAllocator, which is why the
188
+ // shared helper is used by every other door; this door had its own copy of the race.
60
189
  async reserve(attemptId, count) {
61
- const fresh = await store.get(sessionId);
62
- const r = reserve(fresh, attemptId, count);
63
- await store.put(sessionId, r.state);
64
- return r.numbers;
190
+ const { numbers } = await reserveNumbers(store, sessionId, attemptId, count);
191
+ return numbers;
65
192
  },
66
193
  async reservePlan(attemptId, count) {
67
- const fresh = await store.get(sessionId);
68
- const r = reservePlanNumber(fresh, attemptId, count);
69
- await store.put(sessionId, r.state);
70
- return r.numbers;
194
+ const { numbers } = await reserveNumbers(store, sessionId, attemptId, count, true);
195
+ return numbers;
196
+ },
197
+ async release(attemptId) {
198
+ await store.mutate(sessionId, (state) => releaseReservation(state, attemptId));
71
199
  },
72
200
  },
73
201
  // raw value: makeArchiveFs roots RELATIVE paths at the session cwd and
74
202
  // passes absolute ones through — resolving here would double-root relative stores
75
203
  storeRoot: config.artifactStoreRoot,
204
+ cwd, // #69: records are stored workspace-relative
76
205
  rootSessionId: state.rootSession,
77
206
  chapters: rendered,
78
- attemptId: attemptKey(sessionId, anchor),
207
+ attemptId: attemptKey(sessionId, anchor, a.attemptSalt),
79
208
  });
80
209
  // Commit chapter records to session state so search index picks them up.
81
- await commitChapters(store, sessionId, wrote.records);
82
- return { skipped: null, fromSeq, anchor, lastArchived, priorChapters: state.chapters.length, records: wrote.records, warnings: wrote.warnings };
210
+ if (a.supersede !== undefined && wrote.records.length > 0) {
211
+ // Commit AND mark in one section: no reader can ever see the replacement without the old record
212
+ // marked, or the mark without its replacement (#60).
213
+ await store.mutate(sessionId, (fresh) => supersedeChapter(fresh, a.supersede.over, wrote.records, a.supersede.reason));
214
+ }
215
+ else {
216
+ await commitChapters(store, sessionId, wrote.records);
217
+ }
218
+ return { skipped: null, fromSeq, anchor, lastArchived, priorChapters: state.chapters.length, records: wrote.records, warnings: [...repairNotes, ...hollowNotes, ...wrote.warnings] };
83
219
  }
84
220
  //# sourceMappingURL=save-core.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"save-core.js","sourceRoot":"","sources":["../src/save-core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"save-core.js","sourceRoot":"","sources":["../src/save-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,222 @@
1
+ import { type RuleRecord, type RulesSectionResult } from './rules.ts';
2
+ import type { SessionEventLike } from './types.ts';
3
+ /** One captured rule: the human's body, anchored to the seq it came from. */
4
+ export interface CapturedRule {
5
+ body: string;
6
+ seq: number;
7
+ }
8
+ /**
9
+ * The markers a turn's HUMAN messages contain. Two screens, both load-bearing:
10
+ *
11
+ * - `isHumanAuthored` — the same shared predicate signatures use (r28: injected
12
+ * context moves chapter boundaries and would here too). A host-injected
13
+ * instruction file that happens to contain a line starting with the marker is
14
+ * NOT a rule request.
15
+ * - `stripReminderSpans` — `<system-reminder>` spans ride INSIDE human
16
+ * messages. The human's own lines survive; the injected span does not (§15
17
+ * amendment, "host-injected context is not conversation").
18
+ */
19
+ export declare function humanRuleMarkers(events: readonly SessionEventLike[], prefix: string): CapturedRule[];
20
+ /**
21
+ * The next free number in the SHARED per-machine sequence. Both tiers author
22
+ * into `rules/<harness>/`, and ids are `<harness>/<NNN>`, so a session rule must
23
+ * not take a number a project rule already holds — neither the registry's (pre-
24
+ * sync) records' nor the disk's (a killed write leaves a file without a record;
25
+ * the r39 walk-past rule). Numbers are allocated, never scanned-for-content.
26
+ */
27
+ export declare function nextRuleNumber(opts: {
28
+ records: Iterable<[string, RuleRecord]>;
29
+ harnessId: string;
30
+ rulesDir: string;
31
+ }): number;
32
+ export interface CaptureDeps {
33
+ /** workspace store root, e.g. `<cwd>/.dsh-chapters` */
34
+ storeDir: string;
35
+ harnessId: string;
36
+ /** the session whose tree these rules bind (§7.5 activation) */
37
+ sessionId: string;
38
+ /** for id-collision avoidance with the shared tier's pre-sync records */
39
+ records: Iterable<[string, RuleRecord]>;
40
+ prefix: string;
41
+ /** the completed turn's events */
42
+ events: readonly SessionEventLike[];
43
+ now?: () => string;
44
+ }
45
+ export interface CaptureResult {
46
+ written: string[];
47
+ skipped: number;
48
+ }
49
+ /**
50
+ * Capture this turn's markers. Returns the rule ids written (empty when nothing
51
+ * matched), and never throws into the session — the caller contains failures the
52
+ * way the signature listener does.
53
+ */
54
+ export declare function captureSessionRules(deps: CaptureDeps): CaptureResult;
55
+ /**
56
+ * The current session's ancestor path, root-first — the async mirror of
57
+ * `registry.ancestorPath`, which takes a synchronous getter the realm does not
58
+ * have. §7.5 activation is "this rule's session is on MY path", so every render
59
+ * site needs this walk; a missing parent stops the walk instead of throwing,
60
+ * because a rules render must never break a compaction (the same containment
61
+ * the notice path uses).
62
+ */
63
+ export declare function ancestorSessionIds(get: (id: string) => Promise<{
64
+ parentSession: string | null;
65
+ } | undefined>, sessionId: string, maxDepth?: number): Promise<string[]>;
66
+ /** One mined rule candidate, as the enrichment pass proposes it (§7.5). */
67
+ /**
68
+ * Rule ancestry crosses BOTH lineage edges (#52, user decision 2026-10-21).
69
+ *
70
+ * Our registry is the sole authority on CONTINUATION lineage and deliberately
71
+ * ignores the kernel header's `parentSession` — right for chapter numbering and
72
+ * the TOC, and it left a whole session shape uncovered: a delegated subagent is an
73
+ * unrelated root by that view, so it inherited no activated rules from ANY door.
74
+ * The rule tier now walks both edges, READ-ONLY, writing nothing:
75
+ *
76
+ * registry parentSession (ours) ∪ header parentSession (the host's)
77
+ *
78
+ * transitively, so a subagent of a continuation child of a delegating parent sees
79
+ * the whole chain — and still walks UP only, which keeps the direction one-way: a
80
+ * child's inferences never govern the session that delegated them. Two bounds,
81
+ * because this runs inside a head rebuild: an expansion cap, and a reader that
82
+ * throws contributes no edge — a rule walk must never break a turn.
83
+ */
84
+ export declare const RULE_LINEAGE_MAX_EXPANSIONS = 64;
85
+ export interface RuleAncestryWalk {
86
+ ancestors: Set<string>;
87
+ truncated: boolean;
88
+ }
89
+ export declare function ruleAncestorSet(opts: {
90
+ /** Usually [sessionId]; the session always belongs to its own ancestry. */
91
+ seeds: readonly string[];
92
+ /** Our registry chain (continuation lineage). */
93
+ registryAncestors?: ((id: string) => Promise<readonly string[]>) | undefined;
94
+ /** The host header's delegation edge, for any session id. */
95
+ parentOf?: ((id: string) => Promise<string | null | undefined>) | undefined;
96
+ maxExpansions?: number;
97
+ }): Promise<RuleAncestryWalk>;
98
+ /**
99
+ * A `parentOf` from whatever session views this plane can reach: a live agent
100
+ * handle first, then `sessionQuery`'s durable headers. undefined when NEITHER
101
+ * exists — which degrades the walk to registry edges only.
102
+ *
103
+ * Cordis `ctx.get` THROWS for an unregistered service and a plugin plane may have
104
+ * neither, so every lookup is guarded (the #43 lesson: a strict host makes a
105
+ * plausible service name throw).
106
+ */
107
+ export declare function makeHeaderParentReader(get?: (name: string) => unknown): ((id: string) => Promise<string | null | undefined>) | undefined;
108
+ export interface MinedRule {
109
+ text: string;
110
+ category: string;
111
+ /** the human's own words this rule came from — the quote IS the gate */
112
+ quote: string;
113
+ }
114
+ /**
115
+ * THE verbatim-quote gate (§7.5). A mined rule activates only when its quote is
116
+ * the human's own words, present verbatim (whitespace-normalized) in the
117
+ * chapter's USER text. Assistant prose is deliberately NOT admissible evidence:
118
+ * the model restating an instruction it was given is the amplification path, and
119
+ * a quote it invented is a guess wearing a citation.
120
+ */
121
+ export declare function quoteIsHuman(humanText: string, quote: string): boolean;
122
+ export interface MineDeps {
123
+ storeDir: string;
124
+ harnessId: string;
125
+ /** the session whose tree the mined rules bind — the chapter's OWN session */
126
+ sessionId: string;
127
+ records: Iterable<[string, RuleRecord]>;
128
+ /** the chapter's human-authored bytes (its `**User…:**` chunks joined) */
129
+ humanText: string;
130
+ rules: readonly MinedRule[];
131
+ /** per-chapter cap: one conversation must not mint a dozen standing orders */
132
+ maxPerChapter: number;
133
+ /** the chapter these came from (provenance rendered into the head) */
134
+ chapterNumber: number;
135
+ /**
136
+ * §7.5 policy (amended 2026-10-21): may a mined rule govern on arrival? TRUE by
137
+ * default — a rule the model inferred from context is the reason this tier
138
+ * exists; the human may not have known to say it. When false every mined rule is
139
+ * written `reviewOnly: true` and stays inert until this machine approves it, the
140
+ * conservative posture a shared box may want.
141
+ */
142
+ autoActivate: boolean;
143
+ now?: () => string;
144
+ }
145
+ /**
146
+ * Write the mined candidates. Each records its warrant (`stated` / `inferred`) and
147
+ * the chapter it came from; whether it governs on arrival is the `autoActivate`
148
+ * POLICY, not an evidence test (§7.5, amended 2026-10-21 — the tier's premise is
149
+ * that the human may not have known to say the rule). Deduped by normalized body
150
+ * against what the machine already holds, so re-running the ladder (or a
151
+ * chapter annotated by a newer model) fills gaps and never duplicates.
152
+ */
153
+ export declare function captureMinedRules(deps: MineDeps): {
154
+ ids: string[];
155
+ stated: number;
156
+ inferred: number;
157
+ pending: number;
158
+ };
159
+ /** Turn a task description into the relevance term set §7.4 selects on — the same
160
+ * normalization the rule-term index uses, so a query and a rule body meet in one
161
+ * vocabulary instead of two. */
162
+ export declare function queryTopics(query: string): string[];
163
+ /** The registry view the renderer needs — kept structural so tests can hand it a map. */
164
+ export interface RulesStoreLike {
165
+ get(id: string): Promise<{
166
+ parentSession: string | null;
167
+ collections: {
168
+ terms: string[];
169
+ }[];
170
+ } | undefined>;
171
+ }
172
+ export interface RenderRulesOpts {
173
+ mirrorDir: string;
174
+ storeDir: string;
175
+ projectKey: string;
176
+ harnessId: string;
177
+ budgetTokens: number;
178
+ projectCap?: number | undefined;
179
+ sessionCap?: number | undefined;
180
+ /** §7.4 relevance on; off ⇒ deterministic category→id order (the tape order). */
181
+ relevance: boolean;
182
+ /** §7.6: a BRANCH head carries the project tier only — zero session bytes. */
183
+ includeSession: boolean;
184
+ /** When supplied, selection uses THESE terms (the assembly door passes the
185
+ * task query) instead of the session's own recent signatures. */
186
+ topicsOverride?: readonly string[] | undefined;
187
+ store: RulesStoreLike;
188
+ sessionId: string;
189
+ /** #52: reads the host header's parentSession for any id in the chain. Absent
190
+ * ⇒ the walk follows registry edges only, so delegation contributes nothing. */
191
+ parentOf?: ((id: string) => Promise<string | null | undefined>) | undefined;
192
+ }
193
+ /**
194
+ * THE one rules renderer for a rebuilt head. Both doors (continue / fork) and the
195
+ * compaction checkpoint call this and nothing else, so the same session can never
196
+ * see two different rule sets depending on which path rebuilt its head — the same
197
+ * one-builder discipline as `search.rankEntries` and `deterministicCommand`.
198
+ *
199
+ * Relevance topics come from the session’s OWN stored turn signatures:
200
+ * deterministic, already on disk, zero model tokens (§1 invariant 1).
201
+ */
202
+ export declare function renderRulesBlock(opts: RenderRulesOpts): Promise<RulesSectionResult>;
203
+ /**
204
+ * The `turn/end` listener (the same boundary the topic signatures collect on —
205
+ * §7.5: this extends the existing door, it is not a sixth archive moment).
206
+ *
207
+ * Never-break containment: every failure lands in `warn`, because a rule that
208
+ * could not be written must not cost a user their turn.
209
+ */
210
+ export declare function makeRuleCaptureListener(deps: {
211
+ enabled: () => boolean;
212
+ prefix: () => string;
213
+ harnessId: () => string;
214
+ storeRoot: (cwd: string) => string;
215
+ store: () => Promise<{
216
+ store: {
217
+ rules(): IterableIterator<[string, RuleRecord]>;
218
+ };
219
+ }>;
220
+ warn: (error: unknown) => void;
221
+ onCaptured?: (sessionId: string, ids: string[]) => void;
222
+ }): (session: unknown, event: unknown) => void;