@tacuchi/agent-workflow-cli 25.7.0 → 25.8.0

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 (189) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/adapters/git-cli.js +86 -7
  3. package/dist/adapters/git-cli.js.map +1 -1
  4. package/dist/application/capability/readiness.js +26 -10
  5. package/dist/application/capability/readiness.js.map +1 -1
  6. package/dist/application/capability/wrapper.js +10 -3
  7. package/dist/application/capability/wrapper.js.map +1 -1
  8. package/dist/application/dev-only-services.js +5 -7
  9. package/dist/application/dev-only-services.js.map +1 -1
  10. package/dist/application/doctor/provider-mcps.js +1 -1
  11. package/dist/application/doctor/provider-mcps.js.map +1 -1
  12. package/dist/application/flow/advance.js +41 -7
  13. package/dist/application/flow/advance.js.map +1 -1
  14. package/dist/application/flow/checkout-observation.js +49 -0
  15. package/dist/application/flow/checkout-observation.js.map +1 -1
  16. package/dist/application/flow/close-at-boundary.js +144 -0
  17. package/dist/application/flow/close-at-boundary.js.map +1 -0
  18. package/dist/application/flow/flow-service.js +4 -3
  19. package/dist/application/flow/flow-service.js.map +1 -1
  20. package/dist/application/flow/internal-actions.js +64 -1
  21. package/dist/application/flow/internal-actions.js.map +1 -1
  22. package/dist/application/flow/internal-drive.js +23 -18
  23. package/dist/application/flow/internal-drive.js.map +1 -1
  24. package/dist/application/flow/reopen-run.js +152 -0
  25. package/dist/application/flow/reopen-run.js.map +1 -0
  26. package/dist/application/flow/run-journey.js +11 -8
  27. package/dist/application/flow/run-journey.js.map +1 -1
  28. package/dist/application/flow/run-projection.js +16 -5
  29. package/dist/application/flow/run-projection.js.map +1 -1
  30. package/dist/application/flow/run-state-service.js +1 -1
  31. package/dist/application/flow/run-state-service.js.map +1 -1
  32. package/dist/application/flow/submit.js +158 -48
  33. package/dist/application/flow/submit.js.map +1 -1
  34. package/dist/application/hook-sql-mutation-guard.js +147 -12
  35. package/dist/application/hook-sql-mutation-guard.js.map +1 -1
  36. package/dist/application/self/install-skill.js +35 -11
  37. package/dist/application/self/install-skill.js.map +1 -1
  38. package/dist/application/self/install-targets.js +73 -2
  39. package/dist/application/self/install-targets.js.map +1 -1
  40. package/dist/application/self/uninstall.js +21 -7
  41. package/dist/application/self/uninstall.js.map +1 -1
  42. package/dist/application/session-narrative.js +9 -0
  43. package/dist/application/session-narrative.js.map +1 -1
  44. package/dist/application/session-resume-service.js +65 -16
  45. package/dist/application/session-resume-service.js.map +1 -1
  46. package/dist/cli/ascii.js +84 -0
  47. package/dist/cli/ascii.js.map +1 -0
  48. package/dist/cli/commands/amend.js +1 -0
  49. package/dist/cli/commands/amend.js.map +1 -1
  50. package/dist/cli/commands/capability.js +15 -0
  51. package/dist/cli/commands/capability.js.map +1 -1
  52. package/dist/cli/commands/check-branch.js +1 -0
  53. package/dist/cli/commands/check-branch.js.map +1 -1
  54. package/dist/cli/commands/checkpoint-read.js +1 -0
  55. package/dist/cli/commands/checkpoint-read.js.map +1 -1
  56. package/dist/cli/commands/checkpoint-write.js +4 -1
  57. package/dist/cli/commands/checkpoint-write.js.map +1 -1
  58. package/dist/cli/commands/claims.js +1 -0
  59. package/dist/cli/commands/claims.js.map +1 -1
  60. package/dist/cli/commands/code-scan.js +1 -0
  61. package/dist/cli/commands/code-scan.js.map +1 -1
  62. package/dist/cli/commands/context-budget.js +1 -0
  63. package/dist/cli/commands/context-budget.js.map +1 -1
  64. package/dist/cli/commands/context-plan.js +1 -0
  65. package/dist/cli/commands/context-plan.js.map +1 -1
  66. package/dist/cli/commands/cut-intent.js +1 -0
  67. package/dist/cli/commands/cut-intent.js.map +1 -1
  68. package/dist/cli/commands/designs.js +1 -0
  69. package/dist/cli/commands/designs.js.map +1 -1
  70. package/dist/cli/commands/dev-only.js +4 -0
  71. package/dist/cli/commands/dev-only.js.map +1 -1
  72. package/dist/cli/commands/doctor.js +5 -0
  73. package/dist/cli/commands/doctor.js.map +1 -1
  74. package/dist/cli/commands/export.js +13 -0
  75. package/dist/cli/commands/export.js.map +1 -1
  76. package/dist/cli/commands/fix-git.js +1 -0
  77. package/dist/cli/commands/fix-git.js.map +1 -1
  78. package/dist/cli/commands/flow.js +11 -0
  79. package/dist/cli/commands/flow.js.map +1 -1
  80. package/dist/cli/commands/generate-launch.js +1 -0
  81. package/dist/cli/commands/generate-launch.js.map +1 -1
  82. package/dist/cli/commands/git-flow.js +1 -0
  83. package/dist/cli/commands/git-flow.js.map +1 -1
  84. package/dist/cli/commands/history-update.js +7 -9
  85. package/dist/cli/commands/history-update.js.map +1 -1
  86. package/dist/cli/commands/hook.js +11 -3
  87. package/dist/cli/commands/hook.js.map +1 -1
  88. package/dist/cli/commands/host-doctor.js +1 -0
  89. package/dist/cli/commands/host-doctor.js.map +1 -1
  90. package/dist/cli/commands/host-memory.js +2 -9
  91. package/dist/cli/commands/host-memory.js.map +1 -1
  92. package/dist/cli/commands/mcp.js +30 -4
  93. package/dist/cli/commands/mcp.js.map +1 -1
  94. package/dist/cli/commands/merge-state.js +1 -0
  95. package/dist/cli/commands/merge-state.js.map +1 -1
  96. package/dist/cli/commands/multiroot.js +16 -0
  97. package/dist/cli/commands/multiroot.js.map +1 -1
  98. package/dist/cli/commands/persist.js +1 -0
  99. package/dist/cli/commands/persist.js.map +1 -1
  100. package/dist/cli/commands/plan.js +1 -0
  101. package/dist/cli/commands/plan.js.map +1 -1
  102. package/dist/cli/commands/plugin-cache.js +4 -0
  103. package/dist/cli/commands/plugin-cache.js.map +1 -1
  104. package/dist/cli/commands/plugin-doctor.js +3 -0
  105. package/dist/cli/commands/plugin-doctor.js.map +1 -1
  106. package/dist/cli/commands/project-md-upsert.js +3 -0
  107. package/dist/cli/commands/project-md-upsert.js.map +1 -1
  108. package/dist/cli/commands/release-data.js +12 -0
  109. package/dist/cli/commands/release-data.js.map +1 -1
  110. package/dist/cli/commands/release-pass.js +10 -0
  111. package/dist/cli/commands/release-pass.js.map +1 -1
  112. package/dist/cli/commands/remove-source.js +1 -0
  113. package/dist/cli/commands/remove-source.js.map +1 -1
  114. package/dist/cli/commands/reseal.js +1 -0
  115. package/dist/cli/commands/reseal.js.map +1 -1
  116. package/dist/cli/commands/resume-summary.js +5 -0
  117. package/dist/cli/commands/resume-summary.js.map +1 -1
  118. package/dist/cli/commands/resume.js +1 -0
  119. package/dist/cli/commands/resume.js.map +1 -1
  120. package/dist/cli/commands/retirement.js +1 -0
  121. package/dist/cli/commands/retirement.js.map +1 -1
  122. package/dist/cli/commands/self.js +33 -0
  123. package/dist/cli/commands/self.js.map +1 -1
  124. package/dist/cli/commands/session-artifacts.js +1 -0
  125. package/dist/cli/commands/session-artifacts.js.map +1 -1
  126. package/dist/cli/commands/session-close.js +129 -30
  127. package/dist/cli/commands/session-close.js.map +1 -1
  128. package/dist/cli/commands/session-create.js +1 -0
  129. package/dist/cli/commands/session-create.js.map +1 -1
  130. package/dist/cli/commands/session-resume.js +1 -0
  131. package/dist/cli/commands/session-resume.js.map +1 -1
  132. package/dist/cli/commands/sessions.js +1 -0
  133. package/dist/cli/commands/sessions.js.map +1 -1
  134. package/dist/cli/commands/set-branch.js +1 -0
  135. package/dist/cli/commands/set-branch.js.map +1 -1
  136. package/dist/cli/commands/settle.js +1 -0
  137. package/dist/cli/commands/settle.js.map +1 -1
  138. package/dist/cli/commands/skill-index.js +1 -0
  139. package/dist/cli/commands/skill-index.js.map +1 -1
  140. package/dist/cli/commands/skills.js +1 -0
  141. package/dist/cli/commands/skills.js.map +1 -1
  142. package/dist/cli/commands/sources.js +1 -0
  143. package/dist/cli/commands/sources.js.map +1 -1
  144. package/dist/cli/commands/stack.js +1 -0
  145. package/dist/cli/commands/stack.js.map +1 -1
  146. package/dist/cli/commands/status.js +1 -0
  147. package/dist/cli/commands/status.js.map +1 -1
  148. package/dist/cli/commands/tool.js +5 -21
  149. package/dist/cli/commands/tool.js.map +1 -1
  150. package/dist/cli/commands/unknown-flags.js +67 -16
  151. package/dist/cli/commands/unknown-flags.js.map +1 -1
  152. package/dist/cli/commands/visibility.js +1 -0
  153. package/dist/cli/commands/visibility.js.map +1 -1
  154. package/dist/cli/commands/workspace-init.js +12 -0
  155. package/dist/cli/commands/workspace-init.js.map +1 -1
  156. package/dist/cli/commands/workspace-migrate.js +2 -13
  157. package/dist/cli/commands/workspace-migrate.js.map +1 -1
  158. package/dist/cli/commands/worktree.js +1 -0
  159. package/dist/cli/commands/worktree.js.map +1 -1
  160. package/dist/cli/help-groups.js +35 -0
  161. package/dist/cli/help-groups.js.map +1 -1
  162. package/dist/cli/main.js +39 -57
  163. package/dist/cli/main.js.map +1 -1
  164. package/dist/cli/output-mode.js +11 -2
  165. package/dist/cli/output-mode.js.map +1 -1
  166. package/dist/cli/parser.js +14 -5
  167. package/dist/cli/parser.js.map +1 -1
  168. package/dist/cli/registry.js.map +1 -1
  169. package/dist/cli/render.js +30 -1
  170. package/dist/cli/render.js.map +1 -1
  171. package/dist/domain/flow/answer.js +8 -0
  172. package/dist/domain/flow/answer.js.map +1 -1
  173. package/dist/domain/flow/authority.js +141 -14
  174. package/dist/domain/flow/authority.js.map +1 -1
  175. package/dist/domain/flow/execution-result.js +78 -7
  176. package/dist/domain/flow/execution-result.js.map +1 -1
  177. package/dist/domain/flow/route.js.map +1 -1
  178. package/dist/domain/flow/rules.js +5 -6
  179. package/dist/domain/flow/rules.js.map +1 -1
  180. package/dist/domain/flow/run-state.js +186 -30
  181. package/dist/domain/flow/run-state.js.map +1 -1
  182. package/dist/domain/harnesses.js +8 -1
  183. package/dist/domain/harnesses.js.map +1 -1
  184. package/dist/domain/sql-lexer.js +14 -1
  185. package/dist/domain/sql-lexer.js.map +1 -1
  186. package/package.json +1 -1
  187. package/skills/w/harness/HARNESS.md +3 -1
  188. package/skills/w/loops/CHASSIS.md +1 -1
  189. package/skills/w/roles/design/CONTRACT.md +10 -3
@@ -52,13 +52,17 @@ export function executionVerdict(result, action, declared, checkoutStates = null
52
52
  };
53
53
  }
54
54
  if (action.evidence.includes(SOURCE_BOUNDED_EVIDENCE)) {
55
- const validation = result.validations.find((item) => item.id === SOURCE_BOUNDED_EVIDENCE);
56
- const proof = validateCheckoutProof(validation?.proof, checkoutStates);
57
- if (proof !== null) {
58
- return {
59
- message: proof.message,
60
- detail: { code: proof.code, action: action.recovery, outcome: "needs_input" },
61
- };
55
+ // Every proof the result carries is judged, not only the first: a batch of
56
+ // several sources brings one per source, and a stale one among them must not
57
+ // ride on a fresh sibling.
58
+ for (const validation of result.validations.filter((item) => item.id === SOURCE_BOUNDED_EVIDENCE)) {
59
+ const proof = validateCheckoutProof(validation.proof, checkoutStates);
60
+ if (proof !== null) {
61
+ return {
62
+ message: proof.message,
63
+ detail: { code: proof.code, action: action.recovery, outcome: "needs_input" },
64
+ };
65
+ }
62
66
  }
63
67
  }
64
68
  const applied = new Set(result.effects.applied);
@@ -81,4 +85,71 @@ export function executionVerdict(result, action, declared, checkoutStates = null
81
85
  }
82
86
  return null;
83
87
  }
88
+ /**
89
+ * Whether a batch earned its credit with proofs of its OWN checkout — and which.
90
+ *
91
+ * The same `detail` in two batches decides nothing: what does is that at least
92
+ * one source of this batch changed since its base, and that the proof of that
93
+ * source did not already credit another batch. A source that did not change may
94
+ * carry the same proof it carried before — a two-source batch that legitimately
95
+ * touches one of them is still one batch of work.
96
+ */
97
+ export function batchCreditVerdict(result, input, recovery) {
98
+ const proofs = result.validations.flatMap((validation) => validation.id === SOURCE_BOUNDED_EVIDENCE && validation.proof !== undefined
99
+ ? [validation.proof]
100
+ : []);
101
+ const refused = (code, message) => ({
102
+ ok: false,
103
+ refusal: { message, detail: { code, action: recovery, outcome: "needs_input" } },
104
+ });
105
+ const credit = {};
106
+ for (const source of input.sources) {
107
+ const own = proofs.filter((proof) => proof.source === source);
108
+ if (own.length !== 1) {
109
+ return refused(own.length === 0 ? "WORKLINE_CHECKOUT_PROOF_MISSING" : "WORKLINE_CHECKOUT_PROOF_INVALID", own.length === 0
110
+ ? `el batch ${input.batch.id} exige una prueba de checkout por fuente y falta la de '${source}'`
111
+ : `el batch ${input.batch.id} trae ${own.length} pruebas de '${source}': va una por fuente`);
112
+ }
113
+ credit[source] = own[0].checkout_digest;
114
+ }
115
+ const creditedBy = new Map(input.batches
116
+ .filter((batch) => batch.id !== input.batch.id)
117
+ .flatMap((batch) => Object.values(batch.credit ?? {}).map((digest) => [digest, batch.id])));
118
+ const fresh = input.sources.filter((source) => !creditedBy.has(credit[source]));
119
+ if (fresh.length === 0) {
120
+ const reused = input.sources
121
+ .map((source) => `'${source}' ya acreditó ${creditedBy.get(credit[source])}`)
122
+ .join("; ");
123
+ return refused("PLAN_EXEC_PROOF_REUSED", `el batch ${input.batch.id} no trae ninguna prueba propia: ${reused}`);
124
+ }
125
+ // A batch that began before its base could be recorded is judged against the
126
+ // credits and the live checkout alone: a base rebuilt now would be invented.
127
+ const base = input.batch.base;
128
+ if (base === undefined || input.scoped === null)
129
+ return { ok: true, credit };
130
+ const scoped = input.scoped;
131
+ const changed = fresh.filter((source) => {
132
+ const before = base[source];
133
+ const now = scoped[source];
134
+ return typeof before === "string" && typeof now === "string" && before !== now;
135
+ });
136
+ if (changed.length > 0)
137
+ return { ok: true, credit };
138
+ const since = input.batch.iteration === 1 ? "el inicio de la corrida" : "el cierre del batch anterior";
139
+ const why = input.sources
140
+ .map((source) => {
141
+ if (base[source] === null || base[source] === undefined) {
142
+ return `'${source}' no se pudo observar al empezar el batch`;
143
+ }
144
+ if (scoped[source] === null || scoped[source] === undefined) {
145
+ return `'${source}' no se puede observar ahora`;
146
+ }
147
+ if (creditedBy.has(credit[source])) {
148
+ return `la prueba de '${source}' ya acreditó ${creditedBy.get(credit[source])}`;
149
+ }
150
+ return `'${source}' no cambió`;
151
+ })
152
+ .join("; ");
153
+ return refused("PLAN_EXEC_BATCH_UNCHANGED", `el batch ${input.batch.id} no cambió su checkout desde ${since}: ${why}`);
154
+ }
84
155
  //# sourceMappingURL=execution-result.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"execution-result.js","sourceRoot":"","sources":["../../../src/domain/flow/execution-result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAEL,qBAAqB,GACtB,MAAM,6CAA6C,CAAC;AAGrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAShE,MAAM,UAAU,gBAAgB,CAC9B,MAAkC,EAClC,MAA8B,EAC9B,QAAgC,EAChC,iBAAkD,IAAI;IAEtD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,oDAAoD;YAC7D,MAAM,EAAE;gBACN,IAAI,EAAE,qBAAqB;gBAC3B,MAAM,EACJ,qFAAqF;aACxF;SACF,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,2BAA2B,MAAM,CAAC,OAAO,kCAAkC;YACpF,MAAM,EAAE;gBACN,IAAI,EAAE,8BAA8B;gBACpC,MAAM,EAAE,MAAM,CAAC,QAAQ;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB;SACF,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5E,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,8BAA8B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC3D,MAAM,EAAE;gBACN,IAAI,EAAE,uBAAuB;gBAC7B,MAAM,EAAE,gHAAgH,MAAM,CAAC,QAAQ,EAAE;aAC1I;SACF,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,uBAAuB,CAAC,CAAC;QAC1F,MAAM,KAAK,GAAG,qBAAqB,CAAC,UAAU,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;QACvE,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO;gBACL,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;aAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,iDAAiD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC9E,MAAM,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;SACzF,CAAC;IACJ,CAAC;IACD,8EAA8E;IAC9E,0EAA0E;IAC1E,6EAA6E;IAC7E,sDAAsD;IACtD,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO;YACL,OAAO,EAAE,gEAAgE;YACzE,MAAM,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;SACzF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"execution-result.js","sourceRoot":"","sources":["../../../src/domain/flow/execution-result.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../src/domain/flow/route.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAI3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,UAAU;IACV,oBAAoB;IACpB,qBAAqB;CACb,CAAC;AA2DX;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAmC,EACnC,YAA+B,EAAE;IAEjC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,KAAK,MAAM,CAAC,EAAE,CAAC;QAClE,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IACD,IACE,SAAS,CAAC,IAAI,CACZ,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,WAAW,KAAK,YAAY,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CACpF,EACD,CAAC;QACD,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAAsD,EACtD,UAAkB;IAElB,OAAO,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,kBAAwC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,kBAAwC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAChG,CAAC"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../src/domain/flow/route.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAI3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,UAAU;IACV,oBAAoB;IACpB,qBAAqB;CACb,CAAC;AAqEX;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAmC,EACnC,YAA+B,EAAE;IAEjC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,KAAK,MAAM,CAAC,EAAE,CAAC;QAClE,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IACD,IACE,SAAS,CAAC,IAAI,CACZ,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,WAAW,KAAK,YAAY,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CACpF,EACD,CAAC;QACD,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAAsD,EACtD,UAAkB;IAElB,OAAO,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,kBAAwC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,kBAAwC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAChG,CAAC"}
@@ -21,7 +21,7 @@ import { DOCS_BOUNDARY, RUN_PLACEHOLDERS, conditionOf, } from "./authority.js";
21
21
  * is one observation sent twice, and a signal belonging to another boundary is
22
22
  * not this rule's evidence. Both would otherwise let a gate fire on noise.
23
23
  */
24
- export function thresholdFired(rule, journey, observations, batchIteration = null) {
24
+ export function thresholdFired(rule, journey, observations, iteration = {}) {
25
25
  const observed = journey.find((decision) => decision.id === rule.observed);
26
26
  if (observed === undefined)
27
27
  return false;
@@ -33,9 +33,8 @@ export function thresholdFired(rule, journey, observations, batchIteration = nul
33
33
  const vocabulary = new Set(declaredVocabulary.filter((signal) => counted.includes(signal)));
34
34
  const declared = observations
35
35
  .filter((observation) => observation.transition === rule.observed &&
36
- (batchIteration === null
37
- ? observation.batch_iteration === undefined
38
- : observation.batch_iteration === batchIteration))
36
+ observation.batch_iteration === iteration.batch_iteration &&
37
+ observation.reentry_iteration === iteration.reentry_iteration)
39
38
  .flatMap((observation) => observation.signals)
40
39
  .filter((signal) => vocabulary.has(signal));
41
40
  return new Set(declared).size >= rule.min;
@@ -48,7 +47,7 @@ export function thresholdFired(rule, journey, observations, batchIteration = nul
48
47
  * step nobody applied still has to be accounted for, and "it did not happen"
49
48
  * without a cause is indistinguishable from a step that was lost.
50
49
  */
51
- export function skipReason(decision, journey, observations, batchIteration = null) {
50
+ export function skipReason(decision, journey, observations, iteration = {}) {
52
51
  const condition = conditionOf(decision);
53
52
  if (condition === null)
54
53
  return null;
@@ -56,7 +55,7 @@ export function skipReason(decision, journey, observations, batchIteration = nul
56
55
  // That is the doctrine's own default — "borderline continues without asking" —
57
56
  // and it is the direction that assumes nothing: the alternative would emit a
58
57
  // question on zero observations and then read the answer as if it had cause.
59
- if (thresholdFired(condition.threshold, journey, observations, batchIteration))
58
+ if (thresholdFired(condition.threshold, journey, observations, iteration))
60
59
  return null;
61
60
  return condition.otherwise;
62
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/domain/flow/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/domain/flow/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EACL,aAAa,EAGb,gBAAgB,EAEhB,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAWxB;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAqB,EACrB,OAAgC,EAChC,YAA4C,EAC5C,YAA0B,EAAE;IAE5B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3E,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACzC,8EAA8E;IAC9E,gFAAgF;IAChF,8DAA8D;IAC9D,MAAM,kBAAkB,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,IAAI,kBAAkB,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,YAAY;SAC1B,MAAM,CACL,CAAC,WAAW,EAAE,EAAE,CACd,WAAW,CAAC,UAAU,KAAK,IAAI,CAAC,QAAQ;QACxC,WAAW,CAAC,eAAe,KAAK,SAAS,CAAC,eAAe;QACzD,WAAW,CAAC,iBAAiB,KAAK,SAAS,CAAC,iBAAiB,CAChE;SACA,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC;SAC7C,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC;AAC5C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACxB,QAAsB,EACtB,OAAgC,EAChC,YAA4C,EAC5C,YAA0B,EAAE;IAE5B,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,+EAA+E;IAC/E,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,cAAc,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACvF,OAAO,SAAS,CAAC,SAAS,CAAC;AAC7B,CAAC;AAoBD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,MAAuB,EAAE,OAAmB;IACrE,8EAA8E;IAC9E,8EAA8E;IAC9E,iDAAiD;IACjD,MAAM,KAAK,GAA6D;QACtE,WAAW,EAAE,OAAO,CAAC,OAAO;QAC5B,QAAQ,EAAE,OAAO,CAAC,IAAI;QACtB,QAAQ,EAAE,OAAO,CAAC,IAAI;KACvB,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE,CACpC,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7C,wEAAwE;QACxE,2EAA2E;QAC3E,2EAA2E;QAC3E,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;QACvC,OAAO,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnF,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,MAAM,KAAK,GAAoB;QAC7B,GAAG,MAAM;QACT,UAAU,EAAE;YACV,GAAG,MAAM,CAAC,UAAU;YACpB,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACtC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YACtC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC;SAC/E;KACF,CAAC;IACF,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACjF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,SAAS,kBAAkB,CAAC,MAAuB;IACjD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/F,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,MAAM,SAAS,GAAG,yCAAyC,CAAC;AAE5D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAuB,EAAE,IAAkB;IAC5E,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACpE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAChD,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;QACjE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -26,7 +26,7 @@ import { canonicalJson, semanticDigest } from "../../application/semantic-operat
26
26
  import { isEffectClass, touchesTheWorld } from "../capability/effects.js";
27
27
  import { AttemptLedger } from "../capability/protocol.js";
28
28
  import { normalizeObligations, validateDecisionNote } from "../decision-note.js";
29
- import { journeyOfFlow } from "./authority.js";
29
+ import { expandJourney, journeyOfFlow, } from "./authority.js";
30
30
  import { V11_JOURNEY_BASE } from "./journey-baseline.js";
31
31
  import { assuranceForRoute, isAssuranceStatus, isRouteDisposition, } from "./route.js";
32
32
  /**
@@ -40,7 +40,7 @@ import { assuranceForRoute, isAssuranceStatus, isRouteDisposition, } from "./rou
40
40
  * turning the cap off in silence while somebody alternates CLI versions over one
41
41
  * run. Failing with a cause is the requirement; failing silently is the defect.
42
42
  */
43
- export const FLOW_RUN_STATE_VERSION = 12;
43
+ export const FLOW_RUN_STATE_VERSION = 13;
44
44
  /**
45
45
  * The versions this CLI CONTINUES without adoption, newest first.
46
46
  *
@@ -50,8 +50,15 @@ export const FLOW_RUN_STATE_VERSION = 12;
50
50
  * cursor, the answers or the attempts. Every later version joins this set with its own
51
51
  * upgrade step, which is what keeps "v11 or later survives an update" true
52
52
  * without an exception per release.
53
+ *
54
+ * v13 added `reentries` and the `reentry_iteration` of attempts, observations and
55
+ * events. All three are absent on a run that never re-entered, which is every
56
+ * v12 run, so its upgrade step only re-stamps the version.
57
+ * It also added each batch's `base` and `credit`, a reseated run's `inherited_bases`
58
+ * and the `route-refused` trace kind. A v12 run has none of them either, and a
59
+ * batch without `base` is read as the one that was in flight when the CLI updated.
53
60
  */
54
- export const FLOW_RUN_STATE_CONTINUABLE = [FLOW_RUN_STATE_VERSION, 11];
61
+ export const FLOW_RUN_STATE_CONTINUABLE = [FLOW_RUN_STATE_VERSION, 12, 11];
55
62
  /**
56
63
  * The versions this CLI READS, newest first.
57
64
  *
@@ -75,6 +82,7 @@ export const FLOW_RUN_STATE_READABLE = [
75
82
  */
76
83
  const CONTINUABLE_UPGRADES = {
77
84
  11: (state) => ({ ...state, version: 12, journey_base: [...V11_JOURNEY_BASE[state.flow]] }),
85
+ 12: (state) => ({ ...state, version: 13 }),
78
86
  };
79
87
  /** The CLI-owned run state inside the session folder. Machine-local, dotted. */
80
88
  export const FLOW_RUN_STATE_FILE = ".flow-run.json";
@@ -111,12 +119,47 @@ export function attemptsAt(state, transition) {
111
119
  }
112
120
  /** The monotone-counter key for one boundary, scoped when that boundary repeats in a batch. */
113
121
  export function attemptCounterKey(state, transition) {
114
- const iteration = currentBatchIteration(state, transition);
115
- return attemptCounterKeyForIteration(transition, iteration ?? undefined);
122
+ return attemptCounterKeyForIteration(transition, iterationOf(state, transition));
116
123
  }
117
- /** Stable counter key for a historical attempt whose batch iteration is recorded on the row. */
124
+ /** Stable counter key for a historical attempt whose iteration is recorded on the row. */
118
125
  export function attemptCounterKeyForIteration(transition, iteration) {
119
- return iteration === undefined ? transition : `${transition}@batch-${iteration}`;
126
+ const batch = iteration.batch_iteration === undefined ? "" : `@batch-${iteration.batch_iteration}`;
127
+ const reentry = iteration.reentry_iteration === undefined ? "" : `@reentry-${iteration.reentry_iteration}`;
128
+ return `${transition}${batch}${reentry}`;
129
+ }
130
+ /**
131
+ * The iteration of `transition` where the run stands: its batch copy and its
132
+ * reentry copy. Spread it into any record keyed per boundary.
133
+ */
134
+ export function iterationOf(state, transition) {
135
+ const batch = currentBatchIteration(state, transition);
136
+ const reentry = currentReentryIteration(state, transition);
137
+ return {
138
+ ...(batch === null ? {} : { batch_iteration: batch }),
139
+ ...(reentry === null ? {} : { reentry_iteration: reentry }),
140
+ };
141
+ }
142
+ /** Whether a persisted record belongs to this iteration of its boundary. */
143
+ export function sameIteration(record, iteration) {
144
+ return (record.batch_iteration === iteration.batch_iteration &&
145
+ record.reentry_iteration === iteration.reentry_iteration);
146
+ }
147
+ /**
148
+ * Which reentry inserted the row of `transition` the cursor is on, or `null` on
149
+ * the row's own place. Read at the cursor and backwards from it, so it answers
150
+ * the same before the row is applied and right after.
151
+ */
152
+ export function currentReentryIteration(state, transition) {
153
+ if ((state.reentries ?? []).length === 0)
154
+ return null;
155
+ const { rows, copies } = expandJourney(state);
156
+ for (let index = Math.min(state.applied.length, rows.length - 1); index >= 0; index -= 1) {
157
+ if (rows[index]?.id !== transition)
158
+ continue;
159
+ const copy = copies[index] ?? 0;
160
+ return copy === 0 ? null : copy;
161
+ }
162
+ return null;
120
163
  }
121
164
  /**
122
165
  * The three numbers and the difference between them, computed once.
@@ -127,11 +170,8 @@ export function attemptCounterKeyForIteration(transition, iteration) {
127
170
  * directive and the recovery guard would end up disagreeing about the same run.
128
171
  */
129
172
  function spendAt(state, transition) {
130
- const iteration = currentBatchIteration(state, transition);
131
- const rows = state.attempts.filter((attempt) => attempt.transition === transition &&
132
- (iteration === null
133
- ? attempt.batch_iteration === undefined
134
- : attempt.batch_iteration === iteration));
173
+ const iteration = iterationOf(state, transition);
174
+ const rows = state.attempts.filter((attempt) => attempt.transition === transition && sameIteration(attempt, iteration));
135
175
  const key = attemptCounterKey(state, transition);
136
176
  const floor = state.attempt_floor?.[key] ?? 0;
137
177
  const granted = state.attempt_grants?.[key] ?? 0;
@@ -316,11 +356,10 @@ export function applyAttemptReconciliation(state, reconciliation) {
316
356
  grants[key] = repair.after;
317
357
  next = sealRunState({ ...withoutSeal(next), attempt_grants: grants });
318
358
  }
319
- const iteration = currentBatchIteration(next, reconciliation.transition);
320
359
  return withEvent(next, {
321
360
  kind: "reconciled",
322
361
  transition: reconciliation.transition,
323
- ...(iteration === null ? {} : { batch_iteration: iteration }),
362
+ ...iterationOf(next, reconciliation.transition),
324
363
  operation: "flow.attempt-reconciliation",
325
364
  repairs: reconciliation.repairs,
326
365
  });
@@ -350,11 +389,8 @@ function unanswerableAt(state) {
350
389
  return null;
351
390
  }
352
391
  export function recoveryBlockedAt(state, transition) {
353
- const iteration = currentBatchIteration(state, transition);
354
- const trace = state.events.filter((event) => event.transition === transition &&
355
- (iteration === null
356
- ? event.batch_iteration === undefined
357
- : event.batch_iteration === iteration));
392
+ const iteration = iterationOf(state, transition);
393
+ const trace = state.events.filter((event) => event.transition === transition && sameIteration(event, iteration));
358
394
  const material = [...trace].reverse().find(declaresMaterialEffect);
359
395
  if (material !== undefined)
360
396
  return { reason: "materialized", event: material };
@@ -377,6 +413,7 @@ function declaresMaterialEffect(event) {
377
413
  // more block a recovery than reading the file could.
378
414
  if (event.kind === "reconciled" ||
379
415
  event.kind === "aligned" ||
416
+ event.kind === "route-refused" ||
380
417
  event.kind === "restarted" ||
381
418
  event.kind === "annulled") {
382
419
  return false;
@@ -634,6 +671,46 @@ export function upgradeContinuable(state) {
634
671
  }
635
672
  return sealRunState(withoutSeal(current));
636
673
  }
674
+ /** Record a reentry of the journey, after every one already recorded. */
675
+ export function withReentry(state, reentry) {
676
+ return sealRunState({
677
+ ...withoutSeal(state),
678
+ reentries: [...(state.reentries ?? []), reentry],
679
+ });
680
+ }
681
+ /**
682
+ * Take back the last reentry, for the close that recorded its intention and then
683
+ * could not happen. The field goes back to absent when it empties, so the run
684
+ * serializes the bytes it had before the intention.
685
+ */
686
+ export function withoutLastReentry(state) {
687
+ const { reentries: _all, ...rest } = withoutSeal(state);
688
+ const kept = (state.reentries ?? []).slice(0, -1);
689
+ return sealRunState(kept.length === 0 ? rest : { ...rest, reentries: kept });
690
+ }
691
+ /** Seal the base of one batch; a batch that already has one keeps it. */
692
+ export function withPlanExecBatchBase(state, batchId, base) {
693
+ const batches = state.batches ?? [];
694
+ const target = batches.find((batch) => batch.id === batchId);
695
+ // A re-run of the acquisition on the same batch must not move its base: the
696
+ // batch would then be compared against its own half-done work.
697
+ if (target === undefined || target.base !== undefined)
698
+ return state;
699
+ return sealRunState({
700
+ ...withoutSeal(state),
701
+ batches: batches.map((batch) => (batch.id === batchId ? { ...batch, base } : batch)),
702
+ });
703
+ }
704
+ /** Record the proofs that credited one batch. */
705
+ export function withPlanExecBatchCredit(state, batchId, credit) {
706
+ const batches = state.batches ?? [];
707
+ if (!batches.some((batch) => batch.id === batchId))
708
+ return state;
709
+ return sealRunState({
710
+ ...withoutSeal(state),
711
+ batches: batches.map((batch) => (batch.id === batchId ? { ...batch, credit } : batch)),
712
+ });
713
+ }
637
714
  /** Record one inferred or declared batch, refusing duplicate ids at the caller's boundary. */
638
715
  export function withPlanExecBatch(state, batch) {
639
716
  const batches = state.batches ?? [];
@@ -954,7 +1031,7 @@ export function restatesLastEvent(state, event) {
954
1031
  if (last === undefined || last.kind !== "failed" || event.kind !== "failed")
955
1032
  return false;
956
1033
  return (last.transition === event.transition &&
957
- last.batch_iteration === event.batch_iteration &&
1034
+ sameIteration(last, event) &&
958
1035
  last.code === event.code &&
959
1036
  last.message === event.message);
960
1037
  }
@@ -975,7 +1052,7 @@ export function restatesLastEvent(state, event) {
975
1052
  */
976
1053
  export function withObservation(state, observation) {
977
1054
  const repeated = state.observations.some((past) => past.transition === observation.transition &&
978
- past.batch_iteration === observation.batch_iteration &&
1055
+ sameIteration(past, observation) &&
979
1056
  sameSignals(past.signals, observation.signals));
980
1057
  if (repeated)
981
1058
  return state;
@@ -1310,6 +1387,9 @@ function checkRecordShape(parsed, invalid) {
1310
1387
  if (version >= 12 && !isStringArray(parsed.journey_base)) {
1311
1388
  return invalid("no dice contra qué recorrido se escribió su cursor");
1312
1389
  }
1390
+ if (!isReentryArray(parsed.reentries)) {
1391
+ return invalid("declara una reentrada sin tipo, frontera, ocurrencia u origen");
1392
+ }
1313
1393
  if (parsed.exhausted_reruns !== undefined && !isStringArray(parsed.exhausted_reruns)) {
1314
1394
  return invalid("declara vueltas de fronteras agotadas que no son transiciones");
1315
1395
  }
@@ -1350,8 +1430,55 @@ function checkCommonRecordShape(parsed, invalid) {
1350
1430
  if (!isCounterMap(parsed.attempt_floor) || !isCounterMap(parsed.attempt_grants)) {
1351
1431
  return invalid("trae una contabilidad de intentos que no es un contador por transición");
1352
1432
  }
1433
+ if (!isInheritedBaseArray(parsed.inherited_bases)) {
1434
+ return invalid("hereda una base de batch sin sus fases o sin sus fuentes");
1435
+ }
1353
1436
  return null;
1354
1437
  }
1438
+ function isInheritedBaseArray(value) {
1439
+ if (value === undefined)
1440
+ return true;
1441
+ return (Array.isArray(value) &&
1442
+ value.every((entry) => isRecord(entry) &&
1443
+ Array.isArray(entry.phases) &&
1444
+ entry.phases.length > 0 &&
1445
+ entry.phases.every((phase) => Number.isInteger(phase) && phase > 0) &&
1446
+ isSourceMap(entry.base, true) &&
1447
+ entry.base !== undefined));
1448
+ }
1449
+ /**
1450
+ * The bases a reseated run inherits from the archived registry, read tolerantly:
1451
+ * the archive may be the very state that could not be continued, so anything
1452
+ * that is not a well-formed batch base is left behind rather than trusted.
1453
+ */
1454
+ export function inheritedBasesFrom(archived) {
1455
+ if (archived === null)
1456
+ return [];
1457
+ let parsed;
1458
+ try {
1459
+ parsed = JSON.parse(archived);
1460
+ }
1461
+ catch {
1462
+ return [];
1463
+ }
1464
+ if (!isRecord(parsed) || !Array.isArray(parsed.batches))
1465
+ return [];
1466
+ const inherited = parsed.batches.flatMap((batch) => {
1467
+ if (!isRecord(batch) || batch.base === undefined)
1468
+ return [];
1469
+ const candidate = { phases: batch.phases, base: batch.base };
1470
+ return isInheritedBaseArray([candidate]) ? [candidate] : [];
1471
+ });
1472
+ const earlier = isInheritedBaseArray(parsed.inherited_bases)
1473
+ ? (parsed.inherited_bases ?? [])
1474
+ : [];
1475
+ return [...earlier, ...inherited];
1476
+ }
1477
+ export function withInheritedBases(state, inherited) {
1478
+ if (inherited.length === 0)
1479
+ return state;
1480
+ return sealRunState({ ...withoutSeal(state), inherited_bases: [...inherited] });
1481
+ }
1355
1482
  /** Fields added by v10 that have no truthful default on a persisted run. */
1356
1483
  function checkV10RecordShape(parsed, invalid) {
1357
1484
  if (!isPlanExecBatchArray(parsed.batches)) {
@@ -1440,7 +1567,7 @@ function isRouteProposal(value) {
1440
1567
  !isRouteDisposition(control.recommendation) ||
1441
1568
  !isRecord(control.alternatives) ||
1442
1569
  !isNonEmptyString(control.alternatives.apply) ||
1443
- !isNonEmptyString(control.alternatives.omit) ||
1570
+ (control.alternatives.omit !== undefined && !isNonEmptyString(control.alternatives.omit)) ||
1444
1571
  !isNonEmptyString(control.alternatives.substitute) ||
1445
1572
  !isNonEmptyString(control.consequence) ||
1446
1573
  !isNonEmptyString(control.risk) ||
@@ -1542,7 +1669,9 @@ function isPlanExecBatchArray(value) {
1542
1669
  (entry.publication !== undefined &&
1543
1670
  entry.publication.status === "applied" &&
1544
1671
  entry.published_plan_digest !== entry.publication.after_plan_digest) ||
1545
- !PLAN_EXEC_BATCH_STAGES.includes(entry.stage)) {
1672
+ !PLAN_EXEC_BATCH_STAGES.includes(entry.stage) ||
1673
+ !isSourceMap(entry.base, true) ||
1674
+ !isSourceMap(entry.credit, false)) {
1546
1675
  return false;
1547
1676
  }
1548
1677
  ids.add(entry.id);
@@ -1550,6 +1679,14 @@ function isPlanExecBatchArray(value) {
1550
1679
  return true;
1551
1680
  });
1552
1681
  }
1682
+ /** Absent, or a non-empty alias → digest map; `nullable` admits an unobserved source. */
1683
+ function isSourceMap(value, nullable) {
1684
+ if (value === undefined)
1685
+ return true;
1686
+ if (!isRecord(value) || Object.keys(value).length === 0)
1687
+ return false;
1688
+ return Object.values(value).every((digest) => (nullable && digest === null) || (typeof digest === "string" && digest.length > 0));
1689
+ }
1553
1690
  function isPlanExecBatchPublication(value) {
1554
1691
  if (value === undefined)
1555
1692
  return true;
@@ -1862,10 +1999,8 @@ function isEvent(entry) {
1862
1999
  return false;
1863
2000
  if (typeof entry.transition !== "string" || typeof entry.operation !== "string")
1864
2001
  return false;
1865
- if (entry.batch_iteration !== undefined &&
1866
- (!Number.isInteger(entry.batch_iteration) || entry.batch_iteration < 1)) {
2002
+ if (!isIterationRecord(entry))
1867
2003
  return false;
1868
- }
1869
2004
  return EVENT_BODIES.get(entry.kind)?.(entry) === true;
1870
2005
  }
1871
2006
  const nonEmpty = (value) => typeof value === "string" && value.trim().length > 0;
@@ -1888,6 +2023,7 @@ const EVENT_BODIES = new Map(Object.entries({
1888
2023
  isStringArray(entry.tasks) &&
1889
2024
  nonEmpty(entry.digest),
1890
2025
  aligned: (entry) => Number.isInteger(entry.position) && entry.position >= 0 && nonEmpty(entry.reason),
2026
+ "route-refused": (entry) => isRouteDisposition(entry.disposition) && nonEmpty(entry.reason),
1891
2027
  failed: (entry) => typeof entry.code === "string" &&
1892
2028
  typeof entry.message === "string" &&
1893
2029
  typeof entry.recovery === "string" &&
@@ -1913,8 +2049,29 @@ function isObservationArray(value) {
1913
2049
  return value.every((entry) => isRecord(entry) &&
1914
2050
  typeof entry.transition === "string" &&
1915
2051
  isStringArray(entry.signals) &&
1916
- (entry.batch_iteration === undefined ||
1917
- (Number.isInteger(entry.batch_iteration) && entry.batch_iteration >= 1)));
2052
+ isIterationRecord(entry));
2053
+ }
2054
+ const REENTRY_KINDS = ["refine", "close", "reopen"];
2055
+ /** Absent, or reentries each with its kind, its boundary, its occurrence and its origin. */
2056
+ function isReentryArray(value) {
2057
+ if (value === undefined)
2058
+ return true;
2059
+ if (!Array.isArray(value))
2060
+ return false;
2061
+ return value.every((entry) => isRecord(entry) &&
2062
+ REENTRY_KINDS.includes(entry.kind) &&
2063
+ nonEmpty(entry.transition) &&
2064
+ Number.isInteger(entry.occurrence) &&
2065
+ entry.occurrence >= 1 &&
2066
+ // A redraft names where it re-enters; the other kinds repeat from their row.
2067
+ (entry.kind === "refine"
2068
+ ? nonEmpty(entry.from)
2069
+ : entry.from === null || nonEmpty(entry.from)));
2070
+ }
2071
+ /** Both iteration fields, each absent or a positive integer. */
2072
+ function isIterationRecord(entry) {
2073
+ const ordinal = (value) => value === undefined || (Number.isInteger(value) && value >= 1);
2074
+ return ordinal(entry.batch_iteration) && ordinal(entry.reentry_iteration);
1918
2075
  }
1919
2076
  /**
1920
2077
  * The two optional fields are checked as ABSENT-or-well-formed, never defaulted.
@@ -1950,8 +2107,7 @@ function isAttemptArray(value) {
1950
2107
  Number.isInteger(entry.attempt) &&
1951
2108
  typeof entry.request_digest === "string" &&
1952
2109
  typeof entry.transition === "string" &&
1953
- (entry.batch_iteration === undefined ||
1954
- (Number.isInteger(entry.batch_iteration) && entry.batch_iteration >= 1)) &&
2110
+ isIterationRecord(entry) &&
1955
2111
  (entry.parent_request_digest === null || typeof entry.parent_request_digest === "string"));
1956
2112
  }
1957
2113
  //# sourceMappingURL=run-state.js.map