@telora/daemon 0.18.49 → 0.18.58

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 (117) hide show
  1. package/build-info.json +13 -3
  2. package/dist/ai-inspection-context.d.ts.map +1 -1
  3. package/dist/ai-inspection-context.js +11 -1
  4. package/dist/ai-inspection-context.js.map +1 -1
  5. package/dist/ai-inspection-runner.d.ts.map +1 -1
  6. package/dist/ai-inspection-runner.js +0 -1
  7. package/dist/ai-inspection-runner.js.map +1 -1
  8. package/dist/audit-phase.d.ts.map +1 -1
  9. package/dist/audit-phase.js +4 -0
  10. package/dist/audit-phase.js.map +1 -1
  11. package/dist/cascade-restatement.d.ts +14 -5
  12. package/dist/cascade-restatement.d.ts.map +1 -1
  13. package/dist/cascade-restatement.js +35 -6
  14. package/dist/cascade-restatement.js.map +1 -1
  15. package/dist/completion/team-completion.d.ts.map +1 -1
  16. package/dist/completion/team-completion.js +32 -2
  17. package/dist/completion/team-completion.js.map +1 -1
  18. package/dist/de-restatement.d.ts.map +1 -1
  19. package/dist/de-restatement.js +0 -1
  20. package/dist/de-restatement.js.map +1 -1
  21. package/dist/directive/close-loop-stage.d.ts.map +1 -1
  22. package/dist/directive/close-loop-stage.js +10 -2
  23. package/dist/directive/close-loop-stage.js.map +1 -1
  24. package/dist/focus-executor.d.ts +7 -2
  25. package/dist/focus-executor.d.ts.map +1 -1
  26. package/dist/focus-executor.js +20 -9
  27. package/dist/focus-executor.js.map +1 -1
  28. package/dist/focus-lifecycle.d.ts.map +1 -1
  29. package/dist/focus-lifecycle.js +20 -0
  30. package/dist/focus-lifecycle.js.map +1 -1
  31. package/dist/git-genesis.d.ts +100 -0
  32. package/dist/git-genesis.d.ts.map +1 -0
  33. package/dist/git-genesis.js +231 -0
  34. package/dist/git-genesis.js.map +1 -0
  35. package/dist/git.d.ts.map +1 -1
  36. package/dist/git.js +28 -5
  37. package/dist/git.js.map +1 -1
  38. package/dist/negative-branch.d.ts +32 -1
  39. package/dist/negative-branch.d.ts.map +1 -1
  40. package/dist/negative-branch.js +55 -9
  41. package/dist/negative-branch.js.map +1 -1
  42. package/dist/output-monitor.js +5 -8
  43. package/dist/output-monitor.js.map +1 -1
  44. package/dist/prd-controller.d.ts +0 -2
  45. package/dist/prd-controller.d.ts.map +1 -1
  46. package/dist/prd-controller.js +14 -35
  47. package/dist/prd-controller.js.map +1 -1
  48. package/dist/prd-divergence.d.ts +19 -8
  49. package/dist/prd-divergence.d.ts.map +1 -1
  50. package/dist/prd-divergence.js +7 -26
  51. package/dist/prd-divergence.js.map +1 -1
  52. package/dist/prd-viability.d.ts +14 -15
  53. package/dist/prd-viability.d.ts.map +1 -1
  54. package/dist/prd-viability.js +21 -34
  55. package/dist/prd-viability.js.map +1 -1
  56. package/dist/queries/prd.d.ts +24 -2
  57. package/dist/queries/prd.d.ts.map +1 -1
  58. package/dist/queries/prd.js +17 -0
  59. package/dist/queries/prd.js.map +1 -1
  60. package/dist/queries/schemas.d.ts +28 -0
  61. package/dist/queries/schemas.d.ts.map +1 -1
  62. package/dist/queries/schemas.js +26 -0
  63. package/dist/queries/schemas.js.map +1 -1
  64. package/dist/queries/sessions.d.ts +14 -0
  65. package/dist/queries/sessions.d.ts.map +1 -1
  66. package/dist/queries/sessions.js +19 -0
  67. package/dist/queries/sessions.js.map +1 -1
  68. package/dist/queries/starter-repo.d.ts +27 -0
  69. package/dist/queries/starter-repo.d.ts.map +1 -0
  70. package/dist/queries/starter-repo.js +32 -0
  71. package/dist/queries/starter-repo.js.map +1 -0
  72. package/dist/queries/verification.d.ts +132 -0
  73. package/dist/queries/verification.d.ts.map +1 -1
  74. package/dist/queries/verification.js +271 -0
  75. package/dist/queries/verification.js.map +1 -1
  76. package/dist/reality-writeback.d.ts +257 -0
  77. package/dist/reality-writeback.d.ts.map +1 -0
  78. package/dist/reality-writeback.js +179 -0
  79. package/dist/reality-writeback.js.map +1 -0
  80. package/dist/resolvers/shared/reality-tree.d.ts +39 -1
  81. package/dist/resolvers/shared/reality-tree.d.ts.map +1 -1
  82. package/dist/resolvers/shared/reality-tree.js +51 -1
  83. package/dist/resolvers/shared/reality-tree.js.map +1 -1
  84. package/dist/session-lineage.d.ts +25 -0
  85. package/dist/session-lineage.d.ts.map +1 -1
  86. package/dist/session-lineage.js +23 -0
  87. package/dist/session-lineage.js.map +1 -1
  88. package/dist/session-stamp.d.ts +63 -0
  89. package/dist/session-stamp.d.ts.map +1 -0
  90. package/dist/session-stamp.js +65 -0
  91. package/dist/session-stamp.js.map +1 -0
  92. package/dist/spawner/helpers.d.ts.map +1 -1
  93. package/dist/spawner/helpers.js +5 -8
  94. package/dist/spawner/helpers.js.map +1 -1
  95. package/dist/supabase.d.ts +2 -2
  96. package/dist/supabase.d.ts.map +1 -1
  97. package/dist/supabase.js +1 -1
  98. package/dist/supabase.js.map +1 -1
  99. package/dist/templates/claude-md.d.ts +1 -1
  100. package/dist/templates/claude-md.d.ts.map +1 -1
  101. package/dist/templates/claude-md.js +6 -3
  102. package/dist/templates/claude-md.js.map +1 -1
  103. package/dist/types/session.d.ts +24 -0
  104. package/dist/types/session.d.ts.map +1 -1
  105. package/dist/verification-engine.d.ts +10 -0
  106. package/dist/verification-engine.d.ts.map +1 -1
  107. package/dist/verification-engine.js +32 -1
  108. package/dist/verification-engine.js.map +1 -1
  109. package/dist/verify-restatement.d.ts +16 -0
  110. package/dist/verify-restatement.d.ts.map +1 -1
  111. package/dist/verify-restatement.js +7 -0
  112. package/dist/verify-restatement.js.map +1 -1
  113. package/package.json +2 -2
  114. package/dist/prd-clearance-engine.d.ts +0 -121
  115. package/dist/prd-clearance-engine.d.ts.map +0 -1
  116. package/dist/prd-clearance-engine.js +0 -164
  117. package/dist/prd-clearance-engine.js.map +0 -1
@@ -6,6 +6,7 @@
6
6
  * - Trigger the existing reality_tree_verify_injection compound op on pass.
7
7
  */
8
8
  import { callApi } from './shared.js';
9
+ import { decideNodeWriteback, detectInwardDrift, } from '../reality-writeback.js';
9
10
  export async function getPendingVerifications(productId) {
10
11
  const response = await callApi('daemon_get_pending_verifications', productId ? { productId } : {});
11
12
  return response.items ?? [];
@@ -46,4 +47,274 @@ export async function verifyInjectionWithEvidence(injectionNodeId, evidence) {
46
47
  });
47
48
  await callApi('reality_tree_verify_injection', { injectionNodeId });
48
49
  }
50
+ /**
51
+ * Translate the pure `decideNodeWriteback` output into the verify call's
52
+ * `restatements` payload.
53
+ *
54
+ * The flip endpoint (`reality_tree_verify_injection`) is the only seam that
55
+ * persists a node's `verify_classification` / `verify_divergence_reason`, and
56
+ * it does so per-restatement -- but ONLY when the restatement carries a
57
+ * non-empty `statement` (an empty statement is dropped whole, classification
58
+ * included). So a writeback can be applied iff it carries achieved prose.
59
+ *
60
+ * Mapping:
61
+ * - match | legitimate_divergence WITH a non-empty statement -> a
62
+ * VerifyRestatement carried into the flip so classification (+ reason)
63
+ * lands atomically with the promotion. The achieved statement is the prose
64
+ * written as the targeted UDE's new base statement (for a match this equals
65
+ * the declared desired effect carried forward unchanged).
66
+ * - any writeback WITHOUT achieved prose, or a `shortfall` -> NOT emitted as
67
+ * a restatement (there is no edge path that stamps classification without
68
+ * prose, and a shortfall must not flip the node). Reported back via
69
+ * `skipped` so the caller can see what was not stamped.
70
+ *
71
+ * Pure (no I/O); exported for unit testing the mapping.
72
+ */
73
+ export function planNodeWritebackApply(writebacks) {
74
+ const restatements = [];
75
+ const skipped = [];
76
+ for (const wb of writebacks) {
77
+ if (wb.classification === 'shortfall') {
78
+ skipped.push({
79
+ nodeId: wb.nodeId,
80
+ reason: 'shortfall: no flip; classification not persisted (claim did not hold)',
81
+ });
82
+ continue;
83
+ }
84
+ // TEL-6: an `assumed` match carries no evidence. Persisting a
85
+ // verify_classification='match' for it would record an UNEARNED "verified"
86
+ // claim, so skip it -- the node stays unstamped until grounded by evidence.
87
+ if (wb.classification === 'match' && wb.assumed === true) {
88
+ skipped.push({
89
+ nodeId: wb.nodeId,
90
+ reason: 'assumed match: no evidence; not stamped verified (unearned certainty)',
91
+ });
92
+ continue;
93
+ }
94
+ const statement = wb.statement;
95
+ if (typeof statement !== 'string' || statement.trim().length === 0) {
96
+ skipped.push({
97
+ nodeId: wb.nodeId,
98
+ reason: 'no achieved statement: verify edge drops a restatement with empty prose',
99
+ });
100
+ continue;
101
+ }
102
+ // match | legitimate_divergence WITH prose -> restatement.
103
+ const entry = {
104
+ nodeId: wb.nodeId,
105
+ statement,
106
+ classification: wb.classification,
107
+ };
108
+ if (wb.classification === 'legitimate_divergence' && wb.verifyDivergenceReason) {
109
+ entry.divergenceReason = wb.verifyDivergenceReason;
110
+ }
111
+ restatements.push(entry);
112
+ }
113
+ return { restatements, skipped };
114
+ }
115
+ /**
116
+ * Same as `verifyInjectionWithEvidence` but additionally stamps the per-node
117
+ * realized/diverged writeback computed by `decideNodeWriteback`. Closes the
118
+ * reality-tree writeback loop: as a delivery lands, the nodes its injection
119
+ * targeted carry an explicit match / legitimate_divergence status legible to a
120
+ * later reader.
121
+ *
122
+ * Order of operations:
123
+ * 1. `reality_tree_node_update` on the injection node -> persist evidence.
124
+ * 2. `reality_tree_verify_injection` with the per-node restatements -> flips
125
+ * the injection and promotes overlays, applying the classification (+
126
+ * reason) to each targeted UDE atomically. Writebacks with no achieved
127
+ * prose, and shortfalls, are skipped (logged) -- there is no edge path
128
+ * that persists a classification without prose / a flip.
129
+ *
130
+ * Non-destructive: only stamps status + evidence/reason on nodes the injection
131
+ * owns; a match carries the declared desired effect forward unchanged. When
132
+ * `writebacks` is empty this is byte-equivalent to `verifyInjectionWithEvidence`.
133
+ */
134
+ export async function verifyInjectionWithWriteback(injectionNodeId, evidence, writebacks, realityTreeId) {
135
+ await callApi('reality_tree_node_update', {
136
+ nodeId: injectionNodeId,
137
+ evidence,
138
+ });
139
+ const { restatements, skipped } = planNodeWritebackApply(writebacks);
140
+ if (skipped.length > 0) {
141
+ console.warn(`[reality-writeback] injection ${injectionNodeId.slice(0, 8)}: ` +
142
+ `${skipped.length} targeted node writeback(s) not stamped -- ` +
143
+ skipped.map((s) => `${s.nodeId.slice(0, 8)} (${s.reason})`).join('; '));
144
+ }
145
+ const verifyBody = { injectionNodeId };
146
+ if (restatements.length > 0)
147
+ verifyBody.restatements = restatements;
148
+ await callApi('reality_tree_verify_injection', verifyBody);
149
+ // Inward drift: any node reality CONTRADICTED (legitimate_divergence /
150
+ // shortfall) is a claim the tree got wrong. Turn each one into an inward
151
+ // crt_drift_proposal so the tree-owner can correct the asserting claim,
152
+ // instead of leaving a mistaken assertion frozen. Surfaced for human ratify;
153
+ // never auto-applied. Best-effort + non-fatal: a proposal-emit failure must
154
+ // not undo the verify/flip that already landed.
155
+ await emitInwardDriftProposals(injectionNodeId, writebacks, realityTreeId);
156
+ }
157
+ /**
158
+ * Surface inward drift proposals for the contradicted nodes in a writeback.
159
+ *
160
+ * For each writeback the pure `detectInwardDrift` deems a contradicted claim
161
+ * (`legitimate_divergence` / `shortfall`), create one `update_statement`
162
+ * crt_drift_proposal flagged `inward:true` via the EXISTING
163
+ * `crt_drift_proposal_create` pipeline. A `match` (or unstamped) node yields
164
+ * nothing, so a clean landing emits no proposals.
165
+ *
166
+ * Requires the reality tree id (the create action keys off it). When the tree
167
+ * id is unknown, the proposals cannot be created -- we log and skip, leaving
168
+ * the per-node stamps in place (a later reader still sees the divergence).
169
+ *
170
+ * Non-fatal: each create is independently try/caught so one failure neither
171
+ * blocks the others nor unwinds the already-applied verify flip.
172
+ */
173
+ export async function emitInwardDriftProposals(injectionNodeId, writebacks, realityTreeId) {
174
+ const proposals = writebacks
175
+ .map((wb) => {
176
+ const stamped = {
177
+ nodeId: wb.nodeId,
178
+ verifyClassification: wb.classification,
179
+ verifyDivergenceReason: wb.verifyDivergenceReason ?? null,
180
+ // TEL-5: the claim a human ratifier must reconsider is the tree's
181
+ // ORIGINAL assertion (the claim reality CONTRADICTED), NOT the achieved
182
+ // reality prose. Carry `originalClaim`; the detector falls back to a
183
+ // placeholder when it is absent. (`wb.statement` is the achieved prose
184
+ // -- it belongs in proposedCorrection / the divergence reason, never in
185
+ // observedState.)
186
+ claimStatement: wb.originalClaim ?? null,
187
+ };
188
+ return detectInwardDrift(stamped);
189
+ })
190
+ .filter((p) => p !== null);
191
+ if (proposals.length === 0)
192
+ return;
193
+ if (!realityTreeId) {
194
+ console.warn(`[reality-writeback] injection ${injectionNodeId.slice(0, 8)}: ` +
195
+ `${proposals.length} contradicted node(s) detected but no realityTreeId -- ` +
196
+ `inward drift proposals NOT created (per-node stamps retained).`);
197
+ return;
198
+ }
199
+ for (const proposal of proposals) {
200
+ try {
201
+ await callApi('crt_drift_proposal_create', {
202
+ realityTreeId,
203
+ proposalKind: proposal.proposalKind,
204
+ observedState: proposal.observedState,
205
+ proposedCorrection: proposal.proposedCorrection,
206
+ nodeId: proposal.nodeId,
207
+ proposedMetadata: proposal.proposedMetadata,
208
+ });
209
+ }
210
+ catch (err) {
211
+ console.warn(`[reality-writeback] Failed to create inward drift proposal for node ` +
212
+ `${proposal.nodeId.slice(0, 8)} (tree ${realityTreeId.slice(0, 8)}): ` +
213
+ `${err.message}. Stamp retained; proposal not surfaced.`);
214
+ }
215
+ }
216
+ }
217
+ /**
218
+ * Resolve the targeted UDE nodes of an injection via the existing
219
+ * `reality_tree_edge_list` ('targets' edges out of the injection) joined to
220
+ * `reality_tree_node_list` for each target's declared prose. Returns [] when
221
+ * the tree id is unknown or a lookup fails -- the writeback then degrades to a
222
+ * plain injection verify (no per-node stamping), which is non-destructive and
223
+ * matches prior behavior.
224
+ */
225
+ export async function resolveTargetedNodes(injectionId, treeId) {
226
+ if (!treeId)
227
+ return [];
228
+ try {
229
+ const [edgesResp, nodesResp] = await Promise.all([
230
+ callApi('reality_tree_edge_list', { treeId }),
231
+ callApi('reality_tree_node_list', { treeId }),
232
+ ]);
233
+ const targetIds = (edgesResp.items ?? [])
234
+ .filter((e) => e.edgeType === 'targets' && e.fromNodeId === injectionId)
235
+ .map((e) => e.toNodeId);
236
+ if (targetIds.length === 0)
237
+ return [];
238
+ const nodeById = new Map();
239
+ for (const n of nodesResp.items ?? [])
240
+ nodeById.set(n.id, n);
241
+ const isClassification = (v) => v === 'match' || v === 'legitimate_divergence' || v === 'shortfall';
242
+ return targetIds.map((nodeId) => {
243
+ const node = nodeById.get(nodeId);
244
+ const declared = node?.frtStatement ?? node?.statement ?? '';
245
+ const existing = node?.verifyClassification;
246
+ return {
247
+ nodeId,
248
+ achievedStatement: declared,
249
+ originalClaim: declared,
250
+ existingClassification: isClassification(existing) ? existing : null,
251
+ };
252
+ });
253
+ }
254
+ catch (err) {
255
+ console.warn(`[reality-writeback] Failed to resolve targeted nodes for injection ` +
256
+ `${injectionId.slice(0, 8)} (tree ${treeId.slice(0, 8)}): ${err.message}. ` +
257
+ `Falling back to plain verify (no per-node writeback).`);
258
+ return [];
259
+ }
260
+ }
261
+ /**
262
+ * Build the writeback-applying verify callback used by the close-loop sweep.
263
+ *
264
+ * For each injection the sweep verifies, this closure:
265
+ * 1. Resolves the injection's targeted UDE node ids (edge-list) + each node's
266
+ * EXISTING verify_classification.
267
+ * 2. Models the landing as a CLEAN realization for the still-unstamped (or
268
+ * already-match) targets -- the anchoring delivery closed successfully, so
269
+ * the cascade is treated as flipped and the injection as delivered. A
270
+ * target the per-delivery verify path ALREADY stamped as a contradiction
271
+ * (legitimate_divergence / shortfall) is EXCLUDED from the landing so the
272
+ * close-loop sweep never clobbers a diverged stamp back to 'match' (TEL-3).
273
+ * 3. Computes the per-node writeback and applies it via
274
+ * `verifyInjectionWithWriteback`, stamping match/evidence on each targeted
275
+ * UDE so a later reader sees which claims actually held.
276
+ *
277
+ * No targeted nodes -> the writeback is empty and the call is byte-equivalent
278
+ * to the plain `verifyInjectionWithEvidence`.
279
+ *
280
+ * `treeIdByInjection` maps an injection node id to its reality_tree id, captured
281
+ * by the dispatcher from the focus-injections snapshot. The returned callback
282
+ * matches the `(injectionId, evidence) => Promise<void>` shape the close-loop
283
+ * sweep expects, so it drops into `advanceFocusToDoneWithSweep` unchanged.
284
+ *
285
+ * Exported here (rather than in the dispatcher) so the wiring is unit-testable
286
+ * against the callApi mock seam without dragging the dispatcher's heavy import
287
+ * graph.
288
+ */
289
+ export function buildWritebackVerify(treeIdByInjection) {
290
+ return async (injectionId, evidence) => {
291
+ const treeId = treeIdByInjection.get(injectionId);
292
+ const resolved = await resolveTargetedNodes(injectionId, treeId);
293
+ // TEL-3: a node the per-delivery verify path ALREADY stamped as a
294
+ // contradiction (legitimate_divergence / shortfall) must NOT be clobbered
295
+ // back to 'match' at close-loop. Exclude it from the clean-match landing --
296
+ // its stamp (and its inward drift proposal) already landed at verify time.
297
+ // Only un-stamped (or already-match) nodes get a fresh close-loop match.
298
+ const targetedNodes = resolved
299
+ .filter((n) => n.existingClassification !== 'legitimate_divergence' &&
300
+ n.existingClassification !== 'shortfall')
301
+ .map((n) => ({
302
+ nodeId: n.nodeId,
303
+ achievedStatement: n.achievedStatement,
304
+ originalClaim: n.originalClaim,
305
+ }));
306
+ const writebacks = decideNodeWriteback({
307
+ injectionId,
308
+ targetedNodes,
309
+ cascadeFlipped: true,
310
+ delivered: true,
311
+ evidence,
312
+ });
313
+ // Pass the tree id so any contradicted node (divergence/shortfall) can be
314
+ // surfaced as an inward drift proposal. The close-loop sweep models a clean
315
+ // landing (all 'match'), so this emits nothing here today -- but the seam is
316
+ // wired so a divergent landing routed through this path corrects the tree.
317
+ await verifyInjectionWithWriteback(injectionId, evidence, writebacks, treeId);
318
+ };
319
+ }
49
320
  //# sourceMappingURL=verification.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/queries/verification.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAiBtC,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,SAAkB;IAElB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAC5B,kCAAkC,EAClC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAC/B,CAAC;IACF,OAAO,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,UAAkB,EAClB,OAA4B;IAE5B,MAAM,OAAO,CAAC,6CAA6C,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;AACxF,CAAC;AAiBD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,eAAuB,EACvB,YAAkC;IAElC,MAAM,IAAI,GAA4B,EAAE,eAAe,EAAE,CAAC;IAC1D,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IAC9E,MAAM,OAAO,CAAC,+BAA+B,EAAE,IAAI,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,eAAuB,EACvB,QAAgB;IAEhB,MAAM,OAAO,CAAC,0BAA0B,EAAE;QACxC,MAAM,EAAE,eAAe;QACvB,QAAQ;KACT,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,+BAA+B,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/queries/verification.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Reality-tree writeback: decide the per-node verify classification a landing
3
+ * stamps onto the nodes an injection owns.
4
+ *
5
+ * The differential problem this closes: a confident-but-wrong tree stays wrong
6
+ * because reality never writes back. When a delivery lands, the injection it
7
+ * materialized is flipped to `verified`, but the *targeted* UDE nodes are not
8
+ * told whether the asserted desired effect actually held. So a mistaken claim
9
+ * is frozen, not corrected. This module computes -- deterministically, from a
10
+ * small typed landing signal -- what status each targeted node should carry so
11
+ * a later reader can see which claims actually realized.
12
+ *
13
+ * Reuses the EXISTING node verify-classification model (no new status
14
+ * machinery, no migration):
15
+ * - `classification`: 'match' | 'legitimate_divergence' | 'shortfall'
16
+ * (mirrors reality_tree_nodes.verify_classification)
17
+ * - `evidence`: rationale for a clean realization (-> node.evidence)
18
+ * - `verifyDivergenceReason`: why the achieved effect differs
19
+ * (-> node.verify_divergence_reason)
20
+ *
21
+ * The function is PURE: no DB, no I/O, no clock. The dispatcher (close-loop
22
+ * landing path) supplies the landing signal and applies the result via the
23
+ * existing callApi verify / node-update seam. Nothing here is destructive --
24
+ * the output only stamps status + evidence/reason on nodes the injection owns.
25
+ *
26
+ * @module reality-writeback
27
+ */
28
+ /** The three verify outcomes a node can carry. Mirrors VerifyClassification
29
+ * in src/types/reality-tree.ts -- duplicated here only because the daemon
30
+ * cannot import the Vite app's types. */
31
+ export type WritebackClassification = 'match' | 'legitimate_divergence' | 'shortfall';
32
+ /**
33
+ * One node the injection targets, as seen at landing. Intentionally minimal --
34
+ * just enough to identify the node and, optionally, observe whether its UDE
35
+ * flipped and how the achieved effect compares to what was declared. We model
36
+ * the landing observation per-node so a partially-divergent landing (one UDE
37
+ * flipped, another did not) stamps each node correctly.
38
+ */
39
+ export interface TargetedNodeLanding {
40
+ /** reality_tree_nodes.id of the UDE this injection targeted. */
41
+ nodeId: string;
42
+ /**
43
+ * The node's ACHIEVED desired-effect prose. For a clean `match`, this is the
44
+ * declared desired effect carried forward unchanged (achieved == declared).
45
+ * Carried into the writeback's `statement` so the apply step has non-empty
46
+ * prose -- the verify edge only stamps a node's classification when the
47
+ * restatement carries a non-empty statement (an empty statement is dropped
48
+ * whole, classification included). Optional: omit when no prose is available
49
+ * and the apply step will fall back to leaving the node un-stamped.
50
+ */
51
+ achievedStatement?: string;
52
+ /**
53
+ * Did the FRT cascade actually flip this targeted UDE (UDE -> DE)? A clean
54
+ * landing flips it; a divergent landing leaves it unflipped. Optional so a
55
+ * caller that only has a focus-wide clean/divergent signal can omit it and
56
+ * fall back to the landing-level `cascadeFlipped`.
57
+ */
58
+ flipped?: boolean;
59
+ /**
60
+ * Whether the achieved effect (what reality delivered) differs from the
61
+ * declared desired effect even though the UDE flipped. A flipped-but-different
62
+ * landing is a `legitimate_divergence`, not a `match`.
63
+ */
64
+ achievedDiffersFromDeclared?: boolean;
65
+ /**
66
+ * Free-text reason describing the divergence or shortfall. Carried verbatim
67
+ * into verifyDivergenceReason. Ignored for a clean match.
68
+ */
69
+ divergenceReason?: string;
70
+ /**
71
+ * The node's ORIGINAL claim -- its declared desired-effect prose
72
+ * (frt_statement, else statement) AS IT STOOD BEFORE this landing. Distinct
73
+ * from `achievedStatement` (what reality delivered). Carried onto the
74
+ * writeback so the inward-drift detector can frame the contradiction as the
75
+ * tree's claim (observedState) vs what reality showed (proposedCorrection).
76
+ * A confident-but-wrong assertion is corrected by surfacing the CLAIM the
77
+ * ratifier must reconsider, not the reality that already happened. Optional:
78
+ * absent, the inward detector falls back to a deterministic placeholder.
79
+ */
80
+ originalClaim?: string;
81
+ }
82
+ /**
83
+ * The landing signal for one injection. Deliberately NOT coupled to a live
84
+ * derive_frt run -- the caller distills derive_frt (or a simpler delivery
85
+ * close) into this typed shape and hands it in.
86
+ */
87
+ export interface InjectionLanding {
88
+ /** reality_tree_nodes.id of the injection node that landed. */
89
+ injectionId: string;
90
+ /** The nodes this injection targets (the UDEs it claimed to dissolve). */
91
+ targetedNodes: readonly TargetedNodeLanding[];
92
+ /**
93
+ * Landing-wide flip signal: did the cascade flip the targeted UDEs as a
94
+ * whole? Used as the fallback when a `TargetedNodeLanding` does not carry its
95
+ * own per-node `flipped`. A clean landing is `true`; a divergent landing is
96
+ * `false`.
97
+ */
98
+ cascadeFlipped: boolean;
99
+ /**
100
+ * Did the injection deliver its effect at all? When false, the gap means the
101
+ * injection did not produce the intended change and the targeted nodes are
102
+ * stamped `shortfall` rather than `legitimate_divergence`. Defaults to true
103
+ * (the injection delivered something) when omitted.
104
+ */
105
+ delivered?: boolean;
106
+ /**
107
+ * Evidence text for a clean realization. Cited verbatim on each matched
108
+ * node's evidence field so an audit read can trace why the claim was
109
+ * accepted. Optional -- absent, the match carries no evidence string.
110
+ */
111
+ evidence?: string;
112
+ }
113
+ /**
114
+ * Per-node writeback decision. Shaped to feed straight into the existing
115
+ * verify/node-update seam:
116
+ * - match -> stamp evidence (the achieved effect held)
117
+ * - legitimate_divergence | shortfall -> stamp verifyDivergenceReason
118
+ */
119
+ export interface NodeWriteback {
120
+ nodeId: string;
121
+ classification: WritebackClassification;
122
+ /**
123
+ * The achieved desired-effect prose to stamp on the node alongside the
124
+ * classification, carried from the landing's `achievedStatement`. Required
125
+ * by the apply step for the classification to land (the verify edge drops a
126
+ * restatement with an empty statement). Absent when the landing supplied no
127
+ * prose -- the apply step then skips the node.
128
+ */
129
+ statement?: string;
130
+ /** Set only for `match`; the rationale the claim held. */
131
+ evidence?: string;
132
+ /** Set only for divergence/shortfall; why the achieved effect differs. */
133
+ verifyDivergenceReason?: string;
134
+ /**
135
+ * The node's ORIGINAL claim (declared desired-effect prose before this
136
+ * landing), carried from the landing's `originalClaim`. Distinct from
137
+ * `statement` (the ACHIEVED prose). Threaded so a contradicted node's inward
138
+ * drift proposal frames the tree's claim (observedState), not the reality
139
+ * that already happened. Absent when the landing supplied no original claim.
140
+ */
141
+ originalClaim?: string;
142
+ /**
143
+ * TEL-6: an `assumed` match is a clean landing that carries NO evidence.
144
+ * Recording it as a `verified` (`match`) stamp would assert an UNEARNED
145
+ * certainty -- the exact disease this writeback fights. So an unevidenced
146
+ * match is flagged `assumed` and the apply step does NOT persist a
147
+ * `verify_classification='match'` for it (it stays unstamped until grounded).
148
+ * Only ever true on a `match`.
149
+ */
150
+ assumed?: boolean;
151
+ }
152
+ /**
153
+ * Pure decision: given one injection's landing signal, decide the per-node
154
+ * writeback for each targeted node.
155
+ *
156
+ * Rules (deterministic, evaluated per node):
157
+ * 1. Empty target set -> empty output.
158
+ * 2. Injection did not deliver -> EVERY node 'shortfall' + reason.
159
+ * (delivered === false; the gap means the injection produced nothing.)
160
+ * 3. Node flipped AND achieved == declared -> 'match' (+ evidence if any).
161
+ * Flip is the node's own `flipped` when present, else the landing's
162
+ * `cascadeFlipped`.
163
+ * 4. Node flipped BUT achieved differs -> 'legitimate_divergence'
164
+ * (+ verifyDivergenceReason).
165
+ * 5. Node did NOT flip -> 'legitimate_divergence'
166
+ * (+ verifyDivergenceReason) -- the targeted UDE did not move as claimed,
167
+ * but the injection still delivered (rule 2 already handled non-delivery).
168
+ *
169
+ * No side effects. The caller applies the result via callApi.
170
+ */
171
+ export declare function decideNodeWriteback(landing: InjectionLanding): NodeWriteback[];
172
+ /**
173
+ * True iff the landing realized cleanly: every targeted node matched. An
174
+ * empty target set is vacuously clean. Convenience predicate for callers that
175
+ * need a single clean/divergent bit (e.g. to choose whether to short-circuit
176
+ * the flip), derived from the same pure decision so the two never disagree.
177
+ */
178
+ export declare function isCleanLanding(landing: InjectionLanding): boolean;
179
+ /**
180
+ * One node's stamped verify status as the inward detector sees it. Mirrors the
181
+ * columns the writeback persists onto reality_tree_nodes
182
+ * (`verify_classification` / `verify_divergence_reason`) plus the node's own
183
+ * claim prose, so the detector can frame the contradiction as
184
+ * observedState (the claim) vs proposedCorrection (what reality showed).
185
+ *
186
+ * Deliberately decoupled from `NodeWriteback`: any caller with a stamped node
187
+ * row (a fresh DB read, or the writeback's own output) can satisfy this shape.
188
+ */
189
+ export interface StampedNode {
190
+ /** reality_tree_nodes.id of the stamped node. */
191
+ nodeId: string;
192
+ /**
193
+ * The node's stamped verify classification. `null`/`undefined` = unstamped
194
+ * (reality has not written back yet) -> no inward proposal.
195
+ */
196
+ verifyClassification?: WritebackClassification | null;
197
+ /** The recorded reason the achieved effect diverged. */
198
+ verifyDivergenceReason?: string | null;
199
+ /**
200
+ * The tree's CLAIM about this node -- its declared desired-effect prose
201
+ * (frt_statement, else statement). Carried into the proposal's observedState
202
+ * as the assertion reality contradicted. Optional: absent, a deterministic
203
+ * placeholder is used so the proposal still frames the contradiction.
204
+ */
205
+ claimStatement?: string | null;
206
+ }
207
+ /**
208
+ * The inward drift-proposal payload, shaped to feed straight into the existing
209
+ * `crt_drift_proposal_create` edge action (snake-cased by the caller / edge).
210
+ * `proposalKind` is always `update_statement` -- a contradicted claim is a
211
+ * claim whose statement reality showed to be wrong; the human ratifier decides
212
+ * the actual correction. `proposedMetadata.inward` flags it as INWARD drift
213
+ * (vs outward audit drift) and `sourceNodeId` records the stamped node that
214
+ * produced it.
215
+ */
216
+ export interface InwardDriftProposal {
217
+ nodeId: string;
218
+ proposalKind: 'update_statement';
219
+ /** The tree's claim about the node -- the assertion reality contradicted. */
220
+ observedState: string;
221
+ /** What realized reality showed (the divergence reason) -- the correction. */
222
+ proposedCorrection: string;
223
+ proposedMetadata: {
224
+ /** Distinguishes inward (reality-contradicts-tree) from outward audit drift. */
225
+ inward: true;
226
+ /** The stamped node id that produced this proposal. */
227
+ sourceNodeId: string;
228
+ /** The stamped classification that triggered it (legitimate_divergence | shortfall). */
229
+ verifyClassification: 'legitimate_divergence' | 'shortfall';
230
+ };
231
+ }
232
+ /**
233
+ * Pure inward-drift detector.
234
+ *
235
+ * Detection rule (deterministic): a node whose `verifyClassification` is
236
+ * `legitimate_divergence` or `shortfall` is a CONTRADICTED claim -- realized
237
+ * reality did not match what the tree asserted. It maps to one inward
238
+ * `update_statement` drift proposal carrying:
239
+ * - observedState = the tree's claim (claimStatement, else a placeholder)
240
+ * - proposedCorrection = what reality showed (verifyDivergenceReason, else a
241
+ * placeholder)
242
+ * - proposedMetadata = { inward:true, sourceNodeId, verifyClassification }
243
+ *
244
+ * A node stamped `match` produces NO proposal (reality confirmed the claim).
245
+ * An unstamped node (null/undefined classification) produces NO proposal
246
+ * (reality has not written back yet, so there is nothing to contradict).
247
+ *
248
+ * No side effects. The caller surfaces the result via crt_drift_proposal_create
249
+ * -- never auto-applies it.
250
+ */
251
+ export declare function detectInwardDrift(node: StampedNode): InwardDriftProposal | null;
252
+ /**
253
+ * Batch convenience: run `detectInwardDrift` over many stamped nodes, dropping
254
+ * the nulls. Order-preserving; pure.
255
+ */
256
+ export declare function detectInwardDriftForNodes(nodes: readonly StampedNode[]): InwardDriftProposal[];
257
+ //# sourceMappingURL=reality-writeback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reality-writeback.d.ts","sourceRoot":"","sources":["../src/reality-writeback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;yCAEyC;AACzC,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,uBAAuB,GAAG,WAAW,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,aAAa,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC9C;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,uBAAuB,CAAC;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,EAAE,CAyE9E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAEjE;AAqBD;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,oBAAoB,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACtD,wDAAwD;IACxD,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,kBAAkB,CAAC;IACjC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE;QAChB,gFAAgF;QAChF,MAAM,EAAE,IAAI,CAAC;QACb,uDAAuD;QACvD,YAAY,EAAE,MAAM,CAAC;QACrB,wFAAwF;QACxF,oBAAoB,EAAE,uBAAuB,GAAG,WAAW,CAAC;KAC7D,CAAC;CACH;AAOD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,mBAAmB,GAAG,IAAI,CA2B/E;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,WAAW,EAAE,GAC5B,mBAAmB,EAAE,CAOvB"}