@telora/daemon 0.17.59 → 0.17.70

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 (118) hide show
  1. package/build-info.json +19 -3
  2. package/dist/cascade-restatement.d.ts +10 -0
  3. package/dist/cascade-restatement.d.ts.map +1 -1
  4. package/dist/cascade-restatement.js +107 -37
  5. package/dist/cascade-restatement.js.map +1 -1
  6. package/dist/ci-escalation.d.ts.map +1 -1
  7. package/dist/ci-escalation.js +5 -3
  8. package/dist/ci-escalation.js.map +1 -1
  9. package/dist/cli/backfill-frt-prose.d.ts +101 -0
  10. package/dist/cli/backfill-frt-prose.d.ts.map +1 -0
  11. package/dist/cli/backfill-frt-prose.js +195 -0
  12. package/dist/cli/backfill-frt-prose.js.map +1 -0
  13. package/dist/completion/event-escalations.d.ts +4 -11
  14. package/dist/completion/event-escalations.d.ts.map +1 -1
  15. package/dist/completion/event-escalations.js +21 -5
  16. package/dist/completion/event-escalations.js.map +1 -1
  17. package/dist/completion/event.d.ts +4 -11
  18. package/dist/completion/event.d.ts.map +1 -1
  19. package/dist/completion/event.js.map +1 -1
  20. package/dist/completion/review-exit-phase.d.ts.map +1 -1
  21. package/dist/completion/review-exit-phase.js +37 -7
  22. package/dist/completion/review-exit-phase.js.map +1 -1
  23. package/dist/completion/status-advance-phase.d.ts.map +1 -1
  24. package/dist/completion/status-advance-phase.js +46 -13
  25. package/dist/completion/status-advance-phase.js.map +1 -1
  26. package/dist/crash-recovery-cleanup.d.ts.map +1 -1
  27. package/dist/crash-recovery-cleanup.js +7 -1
  28. package/dist/crash-recovery-cleanup.js.map +1 -1
  29. package/dist/crash-recovery-types.d.ts +4 -9
  30. package/dist/crash-recovery-types.d.ts.map +1 -1
  31. package/dist/crash-recovery-types.js.map +1 -1
  32. package/dist/crash-recovery.d.ts +4 -9
  33. package/dist/crash-recovery.d.ts.map +1 -1
  34. package/dist/crash-recovery.js +5 -1
  35. package/dist/crash-recovery.js.map +1 -1
  36. package/dist/delivery-advance-block.d.ts +8 -6
  37. package/dist/delivery-advance-block.d.ts.map +1 -1
  38. package/dist/delivery-advance-block.js +14 -12
  39. package/dist/delivery-advance-block.js.map +1 -1
  40. package/dist/delivery-guards.d.ts.map +1 -1
  41. package/dist/delivery-guards.js +4 -1
  42. package/dist/delivery-guards.js.map +1 -1
  43. package/dist/delivery-lifecycle.d.ts.map +1 -1
  44. package/dist/delivery-lifecycle.js +47 -1
  45. package/dist/delivery-lifecycle.js.map +1 -1
  46. package/dist/delivery-merge.d.ts.map +1 -1
  47. package/dist/delivery-merge.js +5 -1
  48. package/dist/delivery-merge.js.map +1 -1
  49. package/dist/delivery-reconciler-apply.d.ts +85 -0
  50. package/dist/delivery-reconciler-apply.d.ts.map +1 -0
  51. package/dist/delivery-reconciler-apply.js +80 -0
  52. package/dist/delivery-reconciler-apply.js.map +1 -0
  53. package/dist/delivery-reconciler-shadow.d.ts +65 -0
  54. package/dist/delivery-reconciler-shadow.d.ts.map +1 -0
  55. package/dist/delivery-reconciler-shadow.js +127 -0
  56. package/dist/delivery-reconciler-shadow.js.map +1 -0
  57. package/dist/delivery-reconciler.d.ts +133 -0
  58. package/dist/delivery-reconciler.d.ts.map +1 -0
  59. package/dist/delivery-reconciler.js +160 -0
  60. package/dist/delivery-reconciler.js.map +1 -0
  61. package/dist/directive/directive-dispatch.d.ts.map +1 -1
  62. package/dist/directive/directive-dispatch.js +4 -1
  63. package/dist/directive/directive-dispatch.js.map +1 -1
  64. package/dist/escalation-provenance.d.ts +60 -0
  65. package/dist/escalation-provenance.d.ts.map +1 -0
  66. package/dist/escalation-provenance.js +153 -0
  67. package/dist/escalation-provenance.js.map +1 -0
  68. package/dist/escalations.d.ts +33 -3
  69. package/dist/escalations.d.ts.map +1 -1
  70. package/dist/escalations.js +58 -12
  71. package/dist/escalations.js.map +1 -1
  72. package/dist/focus-executor.js +1 -1
  73. package/dist/focus-executor.js.map +1 -1
  74. package/dist/focus-merge.d.ts.map +1 -1
  75. package/dist/focus-merge.js +3 -1
  76. package/dist/focus-merge.js.map +1 -1
  77. package/dist/focus-stage-lifecycle.d.ts.map +1 -1
  78. package/dist/focus-stage-lifecycle.js +5 -2
  79. package/dist/focus-stage-lifecycle.js.map +1 -1
  80. package/dist/index.js +16 -0
  81. package/dist/index.js.map +1 -1
  82. package/dist/listener-auto-advance.d.ts.map +1 -1
  83. package/dist/listener-auto-advance.js +73 -34
  84. package/dist/listener-auto-advance.js.map +1 -1
  85. package/dist/listener.d.ts.map +1 -1
  86. package/dist/listener.js +12 -0
  87. package/dist/listener.js.map +1 -1
  88. package/dist/merge-back-loop.d.ts.map +1 -1
  89. package/dist/merge-back-loop.js +7 -2
  90. package/dist/merge-back-loop.js.map +1 -1
  91. package/dist/nexus-escalation-bridge.d.ts +92 -0
  92. package/dist/nexus-escalation-bridge.d.ts.map +1 -0
  93. package/dist/nexus-escalation-bridge.js +109 -0
  94. package/dist/nexus-escalation-bridge.js.map +1 -0
  95. package/dist/nexus-incoming.d.ts +47 -0
  96. package/dist/nexus-incoming.d.ts.map +1 -0
  97. package/dist/nexus-incoming.js +93 -0
  98. package/dist/nexus-incoming.js.map +1 -0
  99. package/dist/nexus-return.d.ts +131 -0
  100. package/dist/nexus-return.d.ts.map +1 -0
  101. package/dist/nexus-return.js +326 -0
  102. package/dist/nexus-return.js.map +1 -0
  103. package/dist/queries/deliveries.d.ts +12 -0
  104. package/dist/queries/deliveries.d.ts.map +1 -1
  105. package/dist/queries/deliveries.js +17 -0
  106. package/dist/queries/deliveries.js.map +1 -1
  107. package/dist/queries/issues.d.ts +62 -12
  108. package/dist/queries/issues.d.ts.map +1 -1
  109. package/dist/queries/issues.js +46 -13
  110. package/dist/queries/issues.js.map +1 -1
  111. package/dist/resolvers/escalation-answers.d.ts +22 -0
  112. package/dist/resolvers/escalation-answers.d.ts.map +1 -0
  113. package/dist/resolvers/escalation-answers.js +98 -0
  114. package/dist/resolvers/escalation-answers.js.map +1 -0
  115. package/dist/resolvers/index.d.ts.map +1 -1
  116. package/dist/resolvers/index.js +2 -0
  117. package/dist/resolvers/index.js.map +1 -1
  118. package/package.json +3 -3
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Activation layer for the single-writer delivery reconciler.
3
+ *
4
+ * Delivery 4 of the Delivery Execution Pathway Consolidation focus (reality-tree
5
+ * injection #10). This is the step that makes the pure reconciler
6
+ * (delivery-reconciler.ts) the DECISION AUTHORITY for every daemon
7
+ * execution_status write, with the two safety properties the focus method
8
+ * (characterize -> shadow -> flip, reversible) requires:
9
+ *
10
+ * 1. Runtime self-check (replaces the manual prod shadow-observation gate).
11
+ * Each write site still computes what the legacy ("old path") logic would
12
+ * have written; `resolveReconciledWrite` compares that to the reconciler's
13
+ * target and logs `[reconciler-divergence]` on any mismatch. The retained
14
+ * legacy computation is exactly what lets prod self-verify the reconciler
15
+ * against the prior behavior for one release -- no maintenance-window or
16
+ * manual shadow observation needed.
17
+ *
18
+ * 2. Reversibility. A single switch, `TELORA_RECONCILER_WRITE`, DEFAULT-ON,
19
+ * selects whose decision is WRITTEN: ON -> the reconciler; OFF -> the
20
+ * retained legacy target. Flip to '0'/'off'/'false'/'no' (and restart) to
21
+ * revert instantly; the whole consolidation also reverts as one merge.
22
+ *
23
+ * Why activation is safe (suite stays green by construction): the reconciler was
24
+ * built (Delivery 3) to MIRROR the live writers and proven so by the Delivery 2
25
+ * parity tests. So in every characterized case `result.target === legacyTarget`
26
+ * -- the write is byte-identical and the characterization suite stays green. The
27
+ * self-check exists to catch any UN-characterized prod case where they differ.
28
+ *
29
+ * The single shared "issues are done" predicate (areDeliveryIssuesDone) and the
30
+ * agreed terminal set live in delivery-reconciler.ts. The agreed set is
31
+ * {Done, Verified, In Review} (OPEN = {To Do, In Progress, Blocked}); the
32
+ * divergent Postgres literal-Done predicate is removed in Delivery 5.
33
+ */
34
+ import { type ReconcileInput, type ReconcileResult } from './delivery-reconciler.js';
35
+ import type { ExecutionStatus } from '@telora/daemon-core';
36
+ /** Reversibility switch. DEFAULT-ON (opt-out), unlike the shadow's opt-in flag. */
37
+ export declare const RECONCILER_WRITE_ENV = "TELORA_RECONCILER_WRITE";
38
+ /**
39
+ * Whether the reconciler's decision is the one WRITTEN. DEFAULT-ON: unset / ''
40
+ * / any value other than the explicit off-tokens enables it. Only
41
+ * '0'/'off'/'false'/'no' (case-insensitive) revert to writing the legacy target.
42
+ *
43
+ * This mirrors the opt-OUT semantics of shouldRunLoop (undefined/'' -> on,
44
+ * '0' -> off) rather than the shadow harness's opt-IN, because the reconciler is
45
+ * the intended default writer after this delivery -- reverting is the exception.
46
+ */
47
+ export declare function reconcilerWriteEnabled(env?: NodeJS.ProcessEnv): boolean;
48
+ export interface ReconciledWriteDecision {
49
+ /**
50
+ * The status the caller should WRITE: the reconciler's target when the switch
51
+ * is ON (default), otherwise the retained legacy target.
52
+ */
53
+ target: ExecutionStatus;
54
+ /** The reconciler's computed result -- always present, regardless of the switch. */
55
+ result: ReconcileResult;
56
+ /** Whether the reconciler's target differs from the legacy target. */
57
+ diverged: boolean;
58
+ /** Whether the reconciler's decision is the one being written (the switch state). */
59
+ reconcilerAuthoritative: boolean;
60
+ }
61
+ export interface ResolveReconciledWriteParams {
62
+ /** Short site label for the divergence log (e.g. 'auto-advance', 'completion'). */
63
+ site: string;
64
+ deliveryId: string;
65
+ deliveryName: string;
66
+ /** The full signal for the reconciler. currentStatus is the status at THIS step. */
67
+ input: ReconcileInput;
68
+ /** What the legacy/old-path code decided to write for this same step. */
69
+ legacyTarget: ExecutionStatus;
70
+ }
71
+ export interface ReconciledWriteDeps {
72
+ /** Divergence sink. Defaults to console.log; injected in tests for capture. */
73
+ log?: (message: string) => void;
74
+ /** Switch state. Defaults to reconcilerWriteEnabled(); injected in tests. */
75
+ writeEnabled?: () => boolean;
76
+ }
77
+ /**
78
+ * Decide what status to write for one transition step, with the runtime
79
+ * self-check. Single-step: callers that walk multiple steps in one pass
80
+ * (e.g. queued -> coding -> verify) call this once per actual write, keying
81
+ * `input.currentStatus` + `legacyTarget` to that step, so the reconciler's
82
+ * single-step decision and the legacy step correspond 1:1.
83
+ */
84
+ export declare function resolveReconciledWrite(params: ResolveReconciledWriteParams, deps?: ReconciledWriteDeps): ReconciledWriteDecision;
85
+ //# sourceMappingURL=delivery-reconciler-apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-reconciler-apply.d.ts","sourceRoot":"","sources":["../src/delivery-reconciler-apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAMpF;AAED,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,MAAM,EAAE,eAAe,CAAC;IACxB,oFAAoF;IACpF,MAAM,EAAE,eAAe,CAAC;IACxB,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,4BAA4B;IAC3C,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,KAAK,EAAE,cAAc,CAAC;IACtB,yEAAyE;IACzE,YAAY,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,4BAA4B,EACpC,IAAI,GAAE,mBAAwB,GAC7B,uBAAuB,CAsBzB"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Activation layer for the single-writer delivery reconciler.
3
+ *
4
+ * Delivery 4 of the Delivery Execution Pathway Consolidation focus (reality-tree
5
+ * injection #10). This is the step that makes the pure reconciler
6
+ * (delivery-reconciler.ts) the DECISION AUTHORITY for every daemon
7
+ * execution_status write, with the two safety properties the focus method
8
+ * (characterize -> shadow -> flip, reversible) requires:
9
+ *
10
+ * 1. Runtime self-check (replaces the manual prod shadow-observation gate).
11
+ * Each write site still computes what the legacy ("old path") logic would
12
+ * have written; `resolveReconciledWrite` compares that to the reconciler's
13
+ * target and logs `[reconciler-divergence]` on any mismatch. The retained
14
+ * legacy computation is exactly what lets prod self-verify the reconciler
15
+ * against the prior behavior for one release -- no maintenance-window or
16
+ * manual shadow observation needed.
17
+ *
18
+ * 2. Reversibility. A single switch, `TELORA_RECONCILER_WRITE`, DEFAULT-ON,
19
+ * selects whose decision is WRITTEN: ON -> the reconciler; OFF -> the
20
+ * retained legacy target. Flip to '0'/'off'/'false'/'no' (and restart) to
21
+ * revert instantly; the whole consolidation also reverts as one merge.
22
+ *
23
+ * Why activation is safe (suite stays green by construction): the reconciler was
24
+ * built (Delivery 3) to MIRROR the live writers and proven so by the Delivery 2
25
+ * parity tests. So in every characterized case `result.target === legacyTarget`
26
+ * -- the write is byte-identical and the characterization suite stays green. The
27
+ * self-check exists to catch any UN-characterized prod case where they differ.
28
+ *
29
+ * The single shared "issues are done" predicate (areDeliveryIssuesDone) and the
30
+ * agreed terminal set live in delivery-reconciler.ts. The agreed set is
31
+ * {Done, Verified, In Review} (OPEN = {To Do, In Progress, Blocked}); the
32
+ * divergent Postgres literal-Done predicate is removed in Delivery 5.
33
+ */
34
+ import { reconcileDeliveryStatus, } from './delivery-reconciler.js';
35
+ /** Reversibility switch. DEFAULT-ON (opt-out), unlike the shadow's opt-in flag. */
36
+ export const RECONCILER_WRITE_ENV = 'TELORA_RECONCILER_WRITE';
37
+ /**
38
+ * Whether the reconciler's decision is the one WRITTEN. DEFAULT-ON: unset / ''
39
+ * / any value other than the explicit off-tokens enables it. Only
40
+ * '0'/'off'/'false'/'no' (case-insensitive) revert to writing the legacy target.
41
+ *
42
+ * This mirrors the opt-OUT semantics of shouldRunLoop (undefined/'' -> on,
43
+ * '0' -> off) rather than the shadow harness's opt-IN, because the reconciler is
44
+ * the intended default writer after this delivery -- reverting is the exception.
45
+ */
46
+ export function reconcilerWriteEnabled(env = process.env) {
47
+ const raw = env[RECONCILER_WRITE_ENV];
48
+ if (raw === undefined)
49
+ return true;
50
+ const v = raw.trim().toLowerCase();
51
+ if (v === '')
52
+ return true;
53
+ return !['0', 'off', 'false', 'no'].includes(v);
54
+ }
55
+ /**
56
+ * Decide what status to write for one transition step, with the runtime
57
+ * self-check. Single-step: callers that walk multiple steps in one pass
58
+ * (e.g. queued -> coding -> verify) call this once per actual write, keying
59
+ * `input.currentStatus` + `legacyTarget` to that step, so the reconciler's
60
+ * single-step decision and the legacy step correspond 1:1.
61
+ */
62
+ export function resolveReconciledWrite(params, deps = {}) {
63
+ const log = deps.log ?? ((m) => console.log(m));
64
+ const writeEnabled = (deps.writeEnabled ?? reconcilerWriteEnabled)();
65
+ const result = reconcileDeliveryStatus(params.input);
66
+ const diverged = result.target !== params.legacyTarget;
67
+ if (diverged) {
68
+ log(`[reconciler-divergence] site=${params.site} delivery=${params.deliveryId} ` +
69
+ `("${params.deliveryName}") legacy=${params.legacyTarget} ` +
70
+ `reconciled=${result.target} canonical=${result.canonical} ` +
71
+ `reason="${result.reason}"`);
72
+ }
73
+ return {
74
+ target: writeEnabled ? result.target : params.legacyTarget,
75
+ result,
76
+ diverged,
77
+ reconcilerAuthoritative: writeEnabled,
78
+ };
79
+ }
80
+ //# sourceMappingURL=delivery-reconciler-apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-reconciler-apply.js","sourceRoot":"","sources":["../src/delivery-reconciler-apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EACL,uBAAuB,GAGxB,MAAM,0BAA0B,CAAC;AAGlC,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAAG,yBAAyB,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACzE,MAAM,GAAG,GAAG,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACtC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAkCD;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAoC,EACpC,OAA4B,EAAE;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,sBAAsB,CAAC,EAAE,CAAC;IAErE,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,YAAY,CAAC;IAEvD,IAAI,QAAQ,EAAE,CAAC;QACb,GAAG,CACD,gCAAgC,MAAM,CAAC,IAAI,aAAa,MAAM,CAAC,UAAU,GAAG;YAC1E,KAAK,MAAM,CAAC,YAAY,aAAa,MAAM,CAAC,YAAY,GAAG;YAC3D,cAAc,MAAM,CAAC,MAAM,cAAc,MAAM,CAAC,SAAS,GAAG;YAC5D,WAAW,MAAM,CAAC,MAAM,GAAG,CAC9B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY;QAC1D,MAAM;QACN,QAAQ;QACR,uBAAuB,EAAE,YAAY;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Shadow harness for the single-writer delivery reconciler.
3
+ *
4
+ * Delivery 3 (single-writer reconciler, shadow mode) of the Delivery Execution
5
+ * Pathway Consolidation focus (reality-tree injection #10). De-risking method:
6
+ * characterize -> SHADOW -> flip one transition at a time. This is the shadow
7
+ * step.
8
+ *
9
+ * On each poll, for every active focus's deliveries, this gathers the live
10
+ * signal (issue rollup, worktree-committed flag), runs the PURE
11
+ * reconcileDeliveryStatus(), compares its computed target to the delivery's
12
+ * LIVE execution_status, and LOGS every divergence. It makes ZERO writes to
13
+ * execution_status -- there is no status writer in its dependency surface by
14
+ * construction. When divergence holds steady at zero, the reconciler is safe to
15
+ * flip into the write path one transition at a time (Delivery 4).
16
+ *
17
+ * Default-OFF: unlike the focus/verification loops (opt-OUT via shouldRunLoop),
18
+ * the shadow is opt-IN. It runs only when TELORA_RECONCILER_SHADOW is a truthy
19
+ * value ('1'/'true'/etc); unset / '' / '0' keep it a no-op, so wiring it into
20
+ * the live poll changes nothing until an operator deliberately enables it.
21
+ *
22
+ * Poll-time signal note: at poll time there is no exiting review session, so the
23
+ * harness supplies a conservative review state (a verify delivery with no open
24
+ * work stays in verify -- matching what the live poll does; verify->done is
25
+ * driven by the review-exit path, not the poll). The transitions the shadow
26
+ * meaningfully exercises at poll time are the issue-rollup-driven ones
27
+ * (queued/coding/verify_failed) and verify->verify_failed on open work.
28
+ */
29
+ import type { DaemonConfig } from './types.js';
30
+ import { getActiveFocuses, getDeliveryIssues } from './supabase.js';
31
+ import { getFocusDeliveries } from './queries/focuses.js';
32
+ import { getFocusWorktree } from './focus-worktree-state.js';
33
+ import { worktreeHasUncommittedChanges } from './worktree-safety.js';
34
+ /** Opt-in flag name. Default-OFF (only a truthy value enables the shadow). */
35
+ export declare const RECONCILER_SHADOW_ENV = "TELORA_RECONCILER_SHADOW";
36
+ /** Default-off opt-in: only '1'/'true'/'yes'/'on' (case-insensitive) enable. */
37
+ export declare function reconcilerShadowEnabled(env?: NodeJS.ProcessEnv): boolean;
38
+ /**
39
+ * Injectable collaborators. The surface is READ-ONLY by design: there is NO
40
+ * status-writer dependency, which is the structural guarantee that the shadow
41
+ * cannot mutate execution_status.
42
+ */
43
+ export interface ReconcilerShadowDeps {
44
+ isEnabled: () => boolean;
45
+ getActiveFocuses: typeof getActiveFocuses;
46
+ getFocusDeliveries: typeof getFocusDeliveries;
47
+ getDeliveryIssues: typeof getDeliveryIssues;
48
+ getFocusWorktree: typeof getFocusWorktree;
49
+ worktreeHasUncommittedChanges: typeof worktreeHasUncommittedChanges;
50
+ /** Divergence sink. Defaults to console.log; injected in tests for capture. */
51
+ log: (message: string) => void;
52
+ }
53
+ export interface ReconcilerShadowSummary {
54
+ /** Whether the shadow actually ran (false when the flag is off). */
55
+ ran: boolean;
56
+ /** Number of deliveries whose live status was compared. */
57
+ checked: number;
58
+ /** Number where the reconciled target differed from the live status. */
59
+ divergences: number;
60
+ }
61
+ /**
62
+ * Run one shadow pass for a (product-scoped) config. Reads only; never writes.
63
+ */
64
+ export declare function runReconcilerShadow(config: DaemonConfig, deps?: ReconcilerShadowDeps): Promise<ReconcilerShadowSummary>;
65
+ //# sourceMappingURL=delivery-reconciler-shadow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-reconciler-shadow.d.ts","sourceRoot":"","sources":["../src/delivery-reconciler-shadow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAKrE,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAEhE,gFAAgF;AAChF,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAIrF;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,6BAA6B,EAAE,OAAO,6BAA6B,CAAC;IACpE,+EAA+E;IAC/E,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAYD,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,GAAG,EAAE,OAAO,CAAC;IACb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,oBAAkC,GACvC,OAAO,CAAC,uBAAuB,CAAC,CA4ElC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Shadow harness for the single-writer delivery reconciler.
3
+ *
4
+ * Delivery 3 (single-writer reconciler, shadow mode) of the Delivery Execution
5
+ * Pathway Consolidation focus (reality-tree injection #10). De-risking method:
6
+ * characterize -> SHADOW -> flip one transition at a time. This is the shadow
7
+ * step.
8
+ *
9
+ * On each poll, for every active focus's deliveries, this gathers the live
10
+ * signal (issue rollup, worktree-committed flag), runs the PURE
11
+ * reconcileDeliveryStatus(), compares its computed target to the delivery's
12
+ * LIVE execution_status, and LOGS every divergence. It makes ZERO writes to
13
+ * execution_status -- there is no status writer in its dependency surface by
14
+ * construction. When divergence holds steady at zero, the reconciler is safe to
15
+ * flip into the write path one transition at a time (Delivery 4).
16
+ *
17
+ * Default-OFF: unlike the focus/verification loops (opt-OUT via shouldRunLoop),
18
+ * the shadow is opt-IN. It runs only when TELORA_RECONCILER_SHADOW is a truthy
19
+ * value ('1'/'true'/etc); unset / '' / '0' keep it a no-op, so wiring it into
20
+ * the live poll changes nothing until an operator deliberately enables it.
21
+ *
22
+ * Poll-time signal note: at poll time there is no exiting review session, so the
23
+ * harness supplies a conservative review state (a verify delivery with no open
24
+ * work stays in verify -- matching what the live poll does; verify->done is
25
+ * driven by the review-exit path, not the poll). The transitions the shadow
26
+ * meaningfully exercises at poll time are the issue-rollup-driven ones
27
+ * (queued/coding/verify_failed) and verify->verify_failed on open work.
28
+ */
29
+ import { getActiveFocuses, getDeliveryIssues } from './supabase.js';
30
+ import { getFocusDeliveries } from './queries/focuses.js';
31
+ import { getFocusWorktree } from './focus-worktree-state.js';
32
+ import { worktreeHasUncommittedChanges } from './worktree-safety.js';
33
+ import { reconcileDeliveryStatus } from './delivery-reconciler.js';
34
+ import { isExecutionStatus } from '@telora/daemon-core';
35
+ /** Opt-in flag name. Default-OFF (only a truthy value enables the shadow). */
36
+ export const RECONCILER_SHADOW_ENV = 'TELORA_RECONCILER_SHADOW';
37
+ /** Default-off opt-in: only '1'/'true'/'yes'/'on' (case-insensitive) enable. */
38
+ export function reconcilerShadowEnabled(env = process.env) {
39
+ const raw = env[RECONCILER_SHADOW_ENV];
40
+ if (raw === undefined)
41
+ return false;
42
+ return ['1', 'true', 'yes', 'on'].includes(raw.trim().toLowerCase());
43
+ }
44
+ const defaultDeps = {
45
+ isEnabled: () => reconcilerShadowEnabled(),
46
+ getActiveFocuses,
47
+ getFocusDeliveries,
48
+ getDeliveryIssues,
49
+ getFocusWorktree,
50
+ worktreeHasUncommittedChanges,
51
+ log: (m) => console.log(m),
52
+ };
53
+ /**
54
+ * Run one shadow pass for a (product-scoped) config. Reads only; never writes.
55
+ */
56
+ export async function runReconcilerShadow(config, deps = defaultDeps) {
57
+ if (!deps.isEnabled()) {
58
+ return { ran: false, checked: 0, divergences: 0 };
59
+ }
60
+ let checked = 0;
61
+ let divergences = 0;
62
+ let focuses;
63
+ try {
64
+ focuses = await deps.getActiveFocuses(config.organizationId, config.productId);
65
+ }
66
+ catch (err) {
67
+ deps.log(`[reconciler-shadow] failed to fetch active focuses: ${err.message}`);
68
+ return { ran: true, checked, divergences };
69
+ }
70
+ for (const focus of focuses) {
71
+ const reviewRequested = !!focus.review_requested_at;
72
+ let deliveries;
73
+ try {
74
+ deliveries = await deps.getFocusDeliveries(focus.focus_id);
75
+ }
76
+ catch (err) {
77
+ deps.log(`[reconciler-shadow] failed to fetch deliveries for focus ${focus.focus_id}: ${err.message}`);
78
+ continue;
79
+ }
80
+ // Resolve the worktree-committed signal once per focus (one worktree per focus).
81
+ const worktree = deps.getFocusWorktree(focus.focus_id);
82
+ let worktreeCommitted = true; // no worktree => nothing uncommitted can block (matches the advance precheck)
83
+ if (worktree) {
84
+ try {
85
+ worktreeCommitted = !deps.worktreeHasUncommittedChanges(worktree.worktreePath);
86
+ }
87
+ catch {
88
+ // Best-effort: a git failure should not break the shadow; assume committed.
89
+ worktreeCommitted = true;
90
+ }
91
+ }
92
+ for (const delivery of deliveries) {
93
+ const liveStatus = delivery.executionStatus ?? '';
94
+ if (!isExecutionStatus(liveStatus))
95
+ continue;
96
+ let issues;
97
+ try {
98
+ issues = await deps.getDeliveryIssues(delivery.id);
99
+ }
100
+ catch (err) {
101
+ deps.log(`[reconciler-shadow] failed to fetch issues for delivery ${delivery.id}: ${err.message}`);
102
+ continue;
103
+ }
104
+ const result = reconcileDeliveryStatus({
105
+ currentStatus: liveStatus,
106
+ issues: issues.map(i => ({ status: i.status, issueType: i.issueType })),
107
+ gitState: { worktreeCommitted },
108
+ guardVerdict: null,
109
+ // Poll-time review state: conservative. verify with no open work stays
110
+ // verify (verify->done is review-exit-driven, not poll-driven).
111
+ reviewState: { reviewRequested, reportExists: false, sessionType: 'coding', succeeded: false },
112
+ });
113
+ checked++;
114
+ if (result.changed) {
115
+ divergences++;
116
+ deps.log(`[reconciler-shadow] DIVERGENCE delivery=${delivery.id} ("${delivery.name}") ` +
117
+ `live=${liveStatus} reconciled=${result.target} ` +
118
+ `canonical=${result.canonical} reason="${result.reason}" (no write performed)`);
119
+ }
120
+ }
121
+ }
122
+ if (checked > 0) {
123
+ deps.log(`[reconciler-shadow] pass complete: ${checked} deliveries checked, ${divergences} divergence(s), 0 writes`);
124
+ }
125
+ return { ran: true, checked, divergences };
126
+ }
127
+ //# sourceMappingURL=delivery-reconciler-shadow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-reconciler-shadow.js","sourceRoot":"","sources":["../src/delivery-reconciler-shadow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Single-writer delivery reconciler (PURE).
3
+ *
4
+ * Delivery 3 of the Delivery Execution Pathway Consolidation focus
5
+ * (reality-tree injection #10: "Delivery execution_status has exactly one
6
+ * writer -- the daemon reconciler; every transition flows through it").
7
+ *
8
+ * This module is the consolidation's center of gravity: ONE pure function that
9
+ * computes the single next execution_status the daemon should write, plus ONE
10
+ * shared "issues are done" predicate that replaces the divergent copies spread
11
+ * across the live writers (advanceDeliveryStage / advanceDeliveryStatuses /
12
+ * runReviewExitHandler / checkDeliveryAutoAdvance / checkVerifyDeliveriesForOpenIssues).
13
+ *
14
+ * It is deliberately PURE -- no I/O, no supabase, no git. Callers gather the
15
+ * signal (issues, worktree-committed flag, guard verdict, review state) and
16
+ * pass it in; the reconciler only computes. This is what makes it
17
+ * shadow-testable: run it alongside the live path, compare its target to the
18
+ * live status, log divergence, write nothing (see delivery-reconciler-shadow.ts).
19
+ *
20
+ * The behavior here MIRRORS the CURRENT live writers as pinned by the
21
+ * Delivery 2 characterization suite
22
+ * (__tests__/delivery-state-machine-characterization.test.ts). It characterizes
23
+ * what the system does today, not an idealized target -- the shadow phase exists
24
+ * precisely to prove parity before any cutover.
25
+ *
26
+ * The coding -> queued re-queue edge (open work at team exit -> re-queue) is
27
+ * present in EXECUTION_STATUS_TRANSITIONS as of the D5 cleanup. `result.canonical`
28
+ * flags transitions NOT in the canonical map; the coding -> queued edge now
29
+ * resolves to `canonical=true`.
30
+ */
31
+ import type { ExecutionStatus } from '@telora/daemon-core';
32
+ /** Minimal issue shape the reconciler needs. */
33
+ export interface ReconcilerIssue {
34
+ status: string;
35
+ issueType: string;
36
+ }
37
+ /** Git-safety signal: the irreducible worktree-commit gate. */
38
+ export interface ReconcilerGitState {
39
+ /**
40
+ * Whether the focus worktree has NO uncommitted changes. The daemon is the
41
+ * only place this can be checked (Postgres has no git), which is the core
42
+ * reason the daemon -- not a PG trigger -- must own the coding -> verify write.
43
+ * When false, an otherwise-ready coding delivery is HELD in coding.
44
+ */
45
+ worktreeCommitted: boolean;
46
+ }
47
+ /** Verify-gate verdict (from the guard engine). null = no guard evaluated. */
48
+ export interface ReconcilerGuardVerdict {
49
+ /** True when a hard guard blocked the transition -> delivery pauses. */
50
+ blocked: boolean;
51
+ }
52
+ /** Review-window signal used to route verify -> done. */
53
+ export interface ReconcilerReviewState {
54
+ /** Whether the focus currently has review_requested_at set. */
55
+ reviewRequested: boolean;
56
+ /** Whether an explicit focus_reviews report exists for the review session. */
57
+ reportExists: boolean;
58
+ /** The exiting session's type. */
59
+ sessionType: 'coding' | 'review';
60
+ /** Whether that session exited successfully. */
61
+ succeeded: boolean;
62
+ }
63
+ export interface ReconcileInput {
64
+ currentStatus: ExecutionStatus;
65
+ issues: ReadonlyArray<ReconcilerIssue>;
66
+ gitState: ReconcilerGitState;
67
+ guardVerdict?: ReconcilerGuardVerdict | null;
68
+ reviewState?: ReconcilerReviewState | null;
69
+ }
70
+ export interface ReconcileResult {
71
+ /** The execution_status the daemon should write (equal to currentStatus when no change). */
72
+ target: ExecutionStatus;
73
+ /** Whether target differs from currentStatus. */
74
+ changed: boolean;
75
+ /** Human-readable rationale (for shadow divergence logs + debugging). */
76
+ reason: string;
77
+ /**
78
+ * Whether (currentStatus -> target) is present in the canonical
79
+ * EXECUTION_STATUS_TRANSITIONS map. Always true for a no-op (stay). False
80
+ * flags a live-vs-canonical gap (notably coding -> queued); see the module
81
+ * header.
82
+ */
83
+ canonical: boolean;
84
+ }
85
+ /**
86
+ * THE shared "issues are done" predicate. A delivery's work is done when none
87
+ * of its work issues (Tasks/Bugs, excluding Context Groups) are in an OPEN
88
+ * status. OPEN = {To Do, In Progress, Blocked}; 'In Review' and 'Verified' are
89
+ * terminal here -- this is the daemon predicate, deliberately chosen as the
90
+ * single source of truth over the Postgres auto_close predicate (which requires
91
+ * every issue to be literally 'Done'). A delivery with zero work issues is
92
+ * vacuously done.
93
+ *
94
+ * Replaces the previously-divergent inline copies in advanceDeliveryStatuses
95
+ * (`!TERMINAL_ISSUE_STATUSES.has`), listener-auto-advance (`OPEN_ISSUE_STATUSES`),
96
+ * and review-exit (`ACTIVE_WORK_STATUSES`) -- all three sets have identical
97
+ * membership; this names the predicate once.
98
+ */
99
+ export declare function areDeliveryIssuesDone(issues: ReadonlyArray<ReconcilerIssue>): boolean;
100
+ /** Whether the delivery has at least one work issue (Task/Bug). */
101
+ export declare function hasWorkIssues(issues: ReadonlyArray<ReconcilerIssue>): boolean;
102
+ /**
103
+ * Whether any work issue is in an OPEN (active) status. This is the routing
104
+ * signal for verify -> verify_failed (open work on a verify delivery) and the
105
+ * coding/verify_failed re-queue (open work re-queues). Mirror image of
106
+ * areDeliveryIssuesDone for deliveries that have work.
107
+ */
108
+ export declare function hasOpenWork(issues: ReadonlyArray<ReconcilerIssue>): boolean;
109
+ /** Whether any work issue is actively In Progress -- the queued -> coding driver. */
110
+ export declare function hasActiveWork(issues: ReadonlyArray<ReconcilerIssue>): boolean;
111
+ /**
112
+ * Compute the single next execution_status for a delivery from its full signal.
113
+ *
114
+ * Faithful to the current live writers (Delivery 2 characterization):
115
+ * - queued : has work + all done -> coding (step toward verify);
116
+ * has work + active -> coding (work started);
117
+ * otherwise -> stay (scoping gate / not started).
118
+ * - coding : open work -> queued (re-queue);
119
+ * all done + uncommitted worktree -> stay coding (git-safety gate);
120
+ * all done + committed + guard blocked -> paused;
121
+ * all done + committed -> verify.
122
+ * - verify : open work -> verify_failed;
123
+ * guard blocked -> paused;
124
+ * report exists -> done;
125
+ * clean review session -> done (auto-approve);
126
+ * otherwise -> stay verify (awaiting review outcome).
127
+ * - verify_failed : open work -> queued (re-queue);
128
+ * all done -> coding (re-iterate).
129
+ * - draft/planning/paused/done/cancelled : stay (out of reconciler scope;
130
+ * paused is cleared by a human re-queue, terminal states are final).
131
+ */
132
+ export declare function reconcileDeliveryStatus(input: ReconcileInput): ReconcileResult;
133
+ //# sourceMappingURL=delivery-reconciler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-reconciler.d.ts","sourceRoot":"","sources":["../src/delivery-reconciler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,+DAA+D;AAC/D,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,eAAe,EAAE,OAAO,CAAC;IACzB,8EAA8E;IAC9E,YAAY,EAAE,OAAO,CAAC;IACtB,kCAAkC;IAClC,WAAW,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACjC,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,eAAe,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACvC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,YAAY,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,4FAA4F;IAC5F,MAAM,EAAE,eAAe,CAAC;IACxB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,OAAO,CAIrF;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,OAAO,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,OAAO,CAE3E;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,OAAO,CAE7E;AAcD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CA8D9E"}