@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.
- package/CHANGELOG.md +30 -0
- package/dist/adapters/git-cli.js +86 -7
- package/dist/adapters/git-cli.js.map +1 -1
- package/dist/application/capability/readiness.js +26 -10
- package/dist/application/capability/readiness.js.map +1 -1
- package/dist/application/capability/wrapper.js +10 -3
- package/dist/application/capability/wrapper.js.map +1 -1
- package/dist/application/dev-only-services.js +5 -7
- package/dist/application/dev-only-services.js.map +1 -1
- package/dist/application/doctor/provider-mcps.js +1 -1
- package/dist/application/doctor/provider-mcps.js.map +1 -1
- package/dist/application/flow/advance.js +41 -7
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/checkout-observation.js +49 -0
- package/dist/application/flow/checkout-observation.js.map +1 -1
- package/dist/application/flow/close-at-boundary.js +144 -0
- package/dist/application/flow/close-at-boundary.js.map +1 -0
- package/dist/application/flow/flow-service.js +4 -3
- package/dist/application/flow/flow-service.js.map +1 -1
- package/dist/application/flow/internal-actions.js +64 -1
- package/dist/application/flow/internal-actions.js.map +1 -1
- package/dist/application/flow/internal-drive.js +23 -18
- package/dist/application/flow/internal-drive.js.map +1 -1
- package/dist/application/flow/reopen-run.js +152 -0
- package/dist/application/flow/reopen-run.js.map +1 -0
- package/dist/application/flow/run-journey.js +11 -8
- package/dist/application/flow/run-journey.js.map +1 -1
- package/dist/application/flow/run-projection.js +16 -5
- package/dist/application/flow/run-projection.js.map +1 -1
- package/dist/application/flow/run-state-service.js +1 -1
- package/dist/application/flow/run-state-service.js.map +1 -1
- package/dist/application/flow/submit.js +158 -48
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/hook-sql-mutation-guard.js +147 -12
- package/dist/application/hook-sql-mutation-guard.js.map +1 -1
- package/dist/application/self/install-skill.js +35 -11
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/install-targets.js +73 -2
- package/dist/application/self/install-targets.js.map +1 -1
- package/dist/application/self/uninstall.js +21 -7
- package/dist/application/self/uninstall.js.map +1 -1
- package/dist/application/session-narrative.js +9 -0
- package/dist/application/session-narrative.js.map +1 -1
- package/dist/application/session-resume-service.js +65 -16
- package/dist/application/session-resume-service.js.map +1 -1
- package/dist/cli/ascii.js +84 -0
- package/dist/cli/ascii.js.map +1 -0
- package/dist/cli/commands/amend.js +1 -0
- package/dist/cli/commands/amend.js.map +1 -1
- package/dist/cli/commands/capability.js +15 -0
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/check-branch.js +1 -0
- package/dist/cli/commands/check-branch.js.map +1 -1
- package/dist/cli/commands/checkpoint-read.js +1 -0
- package/dist/cli/commands/checkpoint-read.js.map +1 -1
- package/dist/cli/commands/checkpoint-write.js +4 -1
- package/dist/cli/commands/checkpoint-write.js.map +1 -1
- package/dist/cli/commands/claims.js +1 -0
- package/dist/cli/commands/claims.js.map +1 -1
- package/dist/cli/commands/code-scan.js +1 -0
- package/dist/cli/commands/code-scan.js.map +1 -1
- package/dist/cli/commands/context-budget.js +1 -0
- package/dist/cli/commands/context-budget.js.map +1 -1
- package/dist/cli/commands/context-plan.js +1 -0
- package/dist/cli/commands/context-plan.js.map +1 -1
- package/dist/cli/commands/cut-intent.js +1 -0
- package/dist/cli/commands/cut-intent.js.map +1 -1
- package/dist/cli/commands/designs.js +1 -0
- package/dist/cli/commands/designs.js.map +1 -1
- package/dist/cli/commands/dev-only.js +4 -0
- package/dist/cli/commands/dev-only.js.map +1 -1
- package/dist/cli/commands/doctor.js +5 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/export.js +13 -0
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/fix-git.js +1 -0
- package/dist/cli/commands/fix-git.js.map +1 -1
- package/dist/cli/commands/flow.js +11 -0
- package/dist/cli/commands/flow.js.map +1 -1
- package/dist/cli/commands/generate-launch.js +1 -0
- package/dist/cli/commands/generate-launch.js.map +1 -1
- package/dist/cli/commands/git-flow.js +1 -0
- package/dist/cli/commands/git-flow.js.map +1 -1
- package/dist/cli/commands/history-update.js +7 -9
- package/dist/cli/commands/history-update.js.map +1 -1
- package/dist/cli/commands/hook.js +11 -3
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/cli/commands/host-doctor.js +1 -0
- package/dist/cli/commands/host-doctor.js.map +1 -1
- package/dist/cli/commands/host-memory.js +2 -9
- package/dist/cli/commands/host-memory.js.map +1 -1
- package/dist/cli/commands/mcp.js +30 -4
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/merge-state.js +1 -0
- package/dist/cli/commands/merge-state.js.map +1 -1
- package/dist/cli/commands/multiroot.js +16 -0
- package/dist/cli/commands/multiroot.js.map +1 -1
- package/dist/cli/commands/persist.js +1 -0
- package/dist/cli/commands/persist.js.map +1 -1
- package/dist/cli/commands/plan.js +1 -0
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/plugin-cache.js +4 -0
- package/dist/cli/commands/plugin-cache.js.map +1 -1
- package/dist/cli/commands/plugin-doctor.js +3 -0
- package/dist/cli/commands/plugin-doctor.js.map +1 -1
- package/dist/cli/commands/project-md-upsert.js +3 -0
- package/dist/cli/commands/project-md-upsert.js.map +1 -1
- package/dist/cli/commands/release-data.js +12 -0
- package/dist/cli/commands/release-data.js.map +1 -1
- package/dist/cli/commands/release-pass.js +10 -0
- package/dist/cli/commands/release-pass.js.map +1 -1
- package/dist/cli/commands/remove-source.js +1 -0
- package/dist/cli/commands/remove-source.js.map +1 -1
- package/dist/cli/commands/reseal.js +1 -0
- package/dist/cli/commands/reseal.js.map +1 -1
- package/dist/cli/commands/resume-summary.js +5 -0
- package/dist/cli/commands/resume-summary.js.map +1 -1
- package/dist/cli/commands/resume.js +1 -0
- package/dist/cli/commands/resume.js.map +1 -1
- package/dist/cli/commands/retirement.js +1 -0
- package/dist/cli/commands/retirement.js.map +1 -1
- package/dist/cli/commands/self.js +33 -0
- package/dist/cli/commands/self.js.map +1 -1
- package/dist/cli/commands/session-artifacts.js +1 -0
- package/dist/cli/commands/session-artifacts.js.map +1 -1
- package/dist/cli/commands/session-close.js +129 -30
- package/dist/cli/commands/session-close.js.map +1 -1
- package/dist/cli/commands/session-create.js +1 -0
- package/dist/cli/commands/session-create.js.map +1 -1
- package/dist/cli/commands/session-resume.js +1 -0
- package/dist/cli/commands/session-resume.js.map +1 -1
- package/dist/cli/commands/sessions.js +1 -0
- package/dist/cli/commands/sessions.js.map +1 -1
- package/dist/cli/commands/set-branch.js +1 -0
- package/dist/cli/commands/set-branch.js.map +1 -1
- package/dist/cli/commands/settle.js +1 -0
- package/dist/cli/commands/settle.js.map +1 -1
- package/dist/cli/commands/skill-index.js +1 -0
- package/dist/cli/commands/skill-index.js.map +1 -1
- package/dist/cli/commands/skills.js +1 -0
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/sources.js +1 -0
- package/dist/cli/commands/sources.js.map +1 -1
- package/dist/cli/commands/stack.js +1 -0
- package/dist/cli/commands/stack.js.map +1 -1
- package/dist/cli/commands/status.js +1 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/tool.js +5 -21
- package/dist/cli/commands/tool.js.map +1 -1
- package/dist/cli/commands/unknown-flags.js +67 -16
- package/dist/cli/commands/unknown-flags.js.map +1 -1
- package/dist/cli/commands/visibility.js +1 -0
- package/dist/cli/commands/visibility.js.map +1 -1
- package/dist/cli/commands/workspace-init.js +12 -0
- package/dist/cli/commands/workspace-init.js.map +1 -1
- package/dist/cli/commands/workspace-migrate.js +2 -13
- package/dist/cli/commands/workspace-migrate.js.map +1 -1
- package/dist/cli/commands/worktree.js +1 -0
- package/dist/cli/commands/worktree.js.map +1 -1
- package/dist/cli/help-groups.js +35 -0
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/main.js +39 -57
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output-mode.js +11 -2
- package/dist/cli/output-mode.js.map +1 -1
- package/dist/cli/parser.js +14 -5
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/render.js +30 -1
- package/dist/cli/render.js.map +1 -1
- package/dist/domain/flow/answer.js +8 -0
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +141 -14
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/execution-result.js +78 -7
- package/dist/domain/flow/execution-result.js.map +1 -1
- package/dist/domain/flow/route.js.map +1 -1
- package/dist/domain/flow/rules.js +5 -6
- package/dist/domain/flow/rules.js.map +1 -1
- package/dist/domain/flow/run-state.js +186 -30
- package/dist/domain/flow/run-state.js.map +1 -1
- package/dist/domain/harnesses.js +8 -1
- package/dist/domain/harnesses.js.map +1 -1
- package/dist/domain/sql-lexer.js +14 -1
- package/dist/domain/sql-lexer.js.map +1 -1
- package/package.json +1 -1
- package/skills/w/harness/HARNESS.md +3 -1
- package/skills/w/loops/CHASSIS.md +1 -1
- 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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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,
|
|
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;
|
|
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,
|
|
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
|
-
|
|
37
|
-
|
|
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,
|
|
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,
|
|
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":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EACL,aAAa,EAGb,gBAAgB,EAEhB,WAAW,GACZ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/domain/flow/rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 =
|
|
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
|
-
|
|
115
|
-
return attemptCounterKeyForIteration(transition, iteration ?? undefined);
|
|
122
|
+
return attemptCounterKeyForIteration(transition, iterationOf(state, transition));
|
|
116
123
|
}
|
|
117
|
-
/** Stable counter key for a historical attempt whose
|
|
124
|
+
/** Stable counter key for a historical attempt whose iteration is recorded on the row. */
|
|
118
125
|
export function attemptCounterKeyForIteration(transition, iteration) {
|
|
119
|
-
|
|
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 =
|
|
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
|
-
...(
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1917
|
-
|
|
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
|
|
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
|