@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
|
@@ -25,12 +25,12 @@ import { authorizeEffects, touchesTheWorld, } from "../../domain/capability/effe
|
|
|
25
25
|
import { AttemptLedger } from "../../domain/capability/protocol.js";
|
|
26
26
|
import { DEFAULT_CORE_DOCS_CANON, coreDocumentKindForPath } from "../../domain/docs-canon.js";
|
|
27
27
|
import { claimedSeal, parseFlowAnswer, spendsAttempt, } from "../../domain/flow/answer.js";
|
|
28
|
-
import { FIX_PREVIEW_TRANSITION, SETTLEMENT_READINGS, actionOf, alternativesOf, approvalGrantOf, effectsOf, internalActionOf, isRouteEvaluation, proposalContractOf, publishApprovalOf, routeControlOf, scopesSources, } from "../../domain/flow/authority.js";
|
|
28
|
+
import { FIX_PREVIEW_TRANSITION, SETTLEMENT_READINGS, actionOf, alternativesOf, approvalGrantOf, effectsOf, internalActionOf, isRouteEvaluation, occurrenceAt, proposalContractOf, publishApprovalOf, reentryOf, routeControlOf, scopesSources, } from "../../domain/flow/authority.js";
|
|
29
29
|
import { effectApprovalDigest } from "../../domain/flow/authorization.js";
|
|
30
30
|
import { PAUSE_LABEL, STOP_LABEL, stepOf, } from "../../domain/flow/directive.js";
|
|
31
|
-
import { executionVerdict } from "../../domain/flow/execution-result.js";
|
|
31
|
+
import { batchCreditVerdict, executionVerdict, } from "../../domain/flow/execution-result.js";
|
|
32
32
|
import { ROUTE_ACCEPT_LABEL, ROUTE_ADJUST_LABEL, isRouteDisposition, } from "../../domain/flow/route.js";
|
|
33
|
-
import { applyTransition, checkAgainstJourney,
|
|
33
|
+
import { applyTransition, checkAgainstJourney, iterationOf, restartInvocation, restatesLastEvent, sameIteration, settlementAmbiguous, withApproval, withAttempt, withBoundary, withContinuation, withDecisionPreparation, withEvent, withFixPreview, withHandoff, withObservation, withPlanExecBatchCredit, withPlanExecBatchStageForTransition, withProposal, withReentry, withRouteDecisions, withRouteProposal, withScope, withSelectedChoice, withSettlementDeclarations, } from "../../domain/flow/run-state.js";
|
|
34
34
|
import { withSpecBaseline } from "../../domain/lineage.js";
|
|
35
35
|
import { destinationsOf, observedEffects, sealProposal } from "../../domain/proposal.js";
|
|
36
36
|
import { baseDigest } from "../../domain/proposal.js";
|
|
@@ -46,11 +46,11 @@ import { semanticDigest } from "../semantic-operation/protocol.js";
|
|
|
46
46
|
import { resolveSessionTarget } from "../session-resolver.js";
|
|
47
47
|
import { sourceAliasesOfPlan, } from "../source-boundary-policy.js";
|
|
48
48
|
import { actionDigest, advanceFlowRun, awaitingCliRerun, directiveFor, effectsOfTransition, resolveBoundary, } from "./advance.js";
|
|
49
|
-
import { observeCheckout, withObservedCheckouts } from "./checkout-observation.js";
|
|
49
|
+
import { observeCheckout, observeScopedFingerprints, withObservedCheckouts, } from "./checkout-observation.js";
|
|
50
50
|
import { resolveCheckoutCandidates } from "./checkout-observation.js";
|
|
51
51
|
import { driveInternalActions } from "./internal-drive.js";
|
|
52
52
|
import { journeyForRun } from "./run-journey.js";
|
|
53
|
-
import { applyUnderLock, locateRun } from "./run-state-service.js";
|
|
53
|
+
import { applyUnderLock, locateRun, readRun } from "./run-state-service.js";
|
|
54
54
|
export async function submitFlow(fs, paths, input) {
|
|
55
55
|
const canon = await resolveCoreDocsCanon(fs, paths);
|
|
56
56
|
if (!canon.ok) {
|
|
@@ -126,9 +126,30 @@ async function observe(fs, paths, raw, session, git) {
|
|
|
126
126
|
scope: await observeScope(fs, paths, raw),
|
|
127
127
|
plans: plans.evidence,
|
|
128
128
|
checkouts: await observeCheckouts(fs, paths, session, git),
|
|
129
|
+
scoped: await observeBatchSources(fs, paths, session, git),
|
|
129
130
|
baselines: plans.baselines,
|
|
130
131
|
};
|
|
131
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* The scoped fingerprints a phase validation is judged against, read before the
|
|
135
|
+
* lock like every other observation. The run read here only decides WHETHER to
|
|
136
|
+
* measure: the decision under the lock re-reads it, and a run that moved in
|
|
137
|
+
* between answers a different seal and is refused as stale anyway.
|
|
138
|
+
*/
|
|
139
|
+
async function observeBatchSources(fs, paths, session, git) {
|
|
140
|
+
if (git === undefined)
|
|
141
|
+
return null;
|
|
142
|
+
// With a reader present, "not measured" is an empty map and never `null`: the
|
|
143
|
+
// judgment then finds every source unobservable and refuses, instead of
|
|
144
|
+
// skipping the one comparison the phase validation exists for.
|
|
145
|
+
const read = await readRun(fs, locateRun(paths, session));
|
|
146
|
+
if (!read.ok || read.state.boundary !== PHASE_VALIDATION || read.state.scope === null) {
|
|
147
|
+
return {};
|
|
148
|
+
}
|
|
149
|
+
const observed = await observeScopedFingerprints(fs, git, paths, session, read.state.scope.sources);
|
|
150
|
+
return observed.ok ? observed.base : {};
|
|
151
|
+
}
|
|
152
|
+
const PHASE_VALIDATION = "plan-exec.validation-execution";
|
|
132
153
|
/**
|
|
133
154
|
* Judge the plan bytes a proposal is carrying, and derive the seal each one gets.
|
|
134
155
|
*
|
|
@@ -385,6 +406,16 @@ async function decide(fs, paths, state, input, snapshot) {
|
|
|
385
406
|
action: "corré 'aw flow advance': el CLI corre una vez más la operación interna y, si reconoce su efecto, avanza sin cobrar",
|
|
386
407
|
});
|
|
387
408
|
}
|
|
409
|
+
// An internal action is credited only by the driver that ran it: that is what
|
|
410
|
+
// leaves its `executed` event in the trace. A result from outside, however well
|
|
411
|
+
// formed, is a claim nobody verified — and applying it used to publish nothing
|
|
412
|
+
// while marking the step done.
|
|
413
|
+
if (resolved.kind === "execution" && internalActionOf(resolved.stopped) !== null) {
|
|
414
|
+
return reject(state, resolved, `'${resolved.stopped.id}' la ejecuta el CLI: un resultado externo no la acredita`, {
|
|
415
|
+
code: "FLOW_INTERNAL_ACTION_EXTERNAL_RESULT",
|
|
416
|
+
action: `corré 'aw flow advance --session ${state.session}': el CLI corre la operación y la acredita; si la corrida no sale de esta frontera, '${restartInvocation(state.session)}' la destraba`,
|
|
417
|
+
}, cost);
|
|
418
|
+
}
|
|
388
419
|
// The action the run is waiting on is the one that was EMITTED, and the seal
|
|
389
420
|
// would already refuse a result about any other. What the persisted digest adds
|
|
390
421
|
// is the diagnosis: when the two differ, the invocation changed underneath a run
|
|
@@ -394,7 +425,7 @@ async function decide(fs, paths, state, input, snapshot) {
|
|
|
394
425
|
if (drifted !== null)
|
|
395
426
|
return drifted;
|
|
396
427
|
// 2 · The boundary in force decides what is admissible.
|
|
397
|
-
const admissible = admit(state, resolved, resolved.stopped, input, cost, snapshot.checkouts);
|
|
428
|
+
const admissible = admit(state, resolved, resolved.stopped, input, cost, snapshot.checkouts, snapshot.scoped);
|
|
398
429
|
if ("decision" in admissible)
|
|
399
430
|
return admissible.decision;
|
|
400
431
|
const parsed = admissible;
|
|
@@ -408,7 +439,12 @@ async function decide(fs, paths, state, input, snapshot) {
|
|
|
408
439
|
if (route.kind === "adjust") {
|
|
409
440
|
return adjustRouteProposal(state, journey);
|
|
410
441
|
}
|
|
411
|
-
const
|
|
442
|
+
const accepted = route.kind === "accept" ? withRouteDecisions(state, route.decisions) : state;
|
|
443
|
+
// Sealed with the transition it earned, in the same state publication: a batch
|
|
444
|
+
// is never seen validated without the proofs that validated it.
|
|
445
|
+
const routed = parsed.credit === undefined
|
|
446
|
+
? accepted
|
|
447
|
+
: withPlanExecBatchCredit(accepted, parsed.credit.batch, parsed.credit.proofs);
|
|
412
448
|
// The registry, not the Spanish consequence text, owns what a selected
|
|
413
449
|
// alternative does. A handoff must stop before any later plan-exec row can
|
|
414
450
|
// mark work, validate or commit; a decision selection is durably recorded
|
|
@@ -502,9 +538,12 @@ async function decide(fs, paths, state, input, snapshot) {
|
|
|
502
538
|
if (preview.preview !== null) {
|
|
503
539
|
selectedState = withFixPreview(selectedState, preview.preview);
|
|
504
540
|
}
|
|
541
|
+
// A redraft recorded by `grantOf` inserted rows after this boundary, so the
|
|
542
|
+
// transition is applied against the journey as it now reads.
|
|
543
|
+
const walked = journeyForRun(selectedState);
|
|
505
544
|
const outcome = holds
|
|
506
|
-
? holdAfterApproval(selectedState,
|
|
507
|
-
: applyAndAdvance(selectedState,
|
|
545
|
+
? holdAfterApproval(selectedState, walked, identity)
|
|
546
|
+
: applyAndAdvance(selectedState, walked, resolved.stopped, identity, parsed.answer);
|
|
508
547
|
return standalone === null ? outcome : withStandaloneGuidance(outcome, standalone);
|
|
509
548
|
}
|
|
510
549
|
/**
|
|
@@ -679,17 +718,28 @@ function routeAnswer(state, stopped, journey, answer) {
|
|
|
679
718
|
},
|
|
680
719
|
};
|
|
681
720
|
}
|
|
721
|
+
const { decision, control } = configuredControl;
|
|
722
|
+
const consequence = control.consequences[raw.disposition];
|
|
723
|
+
if (consequence === undefined) {
|
|
724
|
+
return {
|
|
725
|
+
kind: "failure",
|
|
726
|
+
failure: {
|
|
727
|
+
code: "FLOW_ROUTE_HARD_GATE",
|
|
728
|
+
message: `'${raw.transition}' no admite '${raw.disposition}': el registro no deja que una ruta la saltee`,
|
|
729
|
+
action: "declará apply o substitute para ese control; la evidencia que acredita el paso no se omite",
|
|
730
|
+
},
|
|
731
|
+
};
|
|
732
|
+
}
|
|
682
733
|
const substitution = routeSubstitution(raw.disposition, raw.substitution);
|
|
683
734
|
if ("failure" in substitution)
|
|
684
735
|
return { kind: "failure", failure: substitution.failure };
|
|
685
|
-
const { decision, control } = configuredControl;
|
|
686
736
|
controls.push({
|
|
687
737
|
transition: decision.id,
|
|
688
738
|
title: decision.title,
|
|
689
739
|
disposition: raw.disposition,
|
|
690
740
|
recommendation: control.recommendation,
|
|
691
741
|
alternatives: control.consequences,
|
|
692
|
-
consequence
|
|
742
|
+
consequence,
|
|
693
743
|
risk: control.risk,
|
|
694
744
|
reason: raw.reason.trim(),
|
|
695
745
|
substitution: substitution.value,
|
|
@@ -1216,11 +1266,11 @@ async function registerSelectedDecision(fs, paths, state, snapshot, resolved, co
|
|
|
1216
1266
|
* run that merely advanced would be indistinguishable from one that never decided.
|
|
1217
1267
|
*/
|
|
1218
1268
|
function standaloneDecisionEvent(state, transition, record) {
|
|
1219
|
-
const
|
|
1269
|
+
const rowIteration = iterationOf(state, transition);
|
|
1220
1270
|
return {
|
|
1221
1271
|
kind: "executed",
|
|
1222
1272
|
transition,
|
|
1223
|
-
...
|
|
1273
|
+
...rowIteration,
|
|
1224
1274
|
operation: "plan-exec.standalone-decision",
|
|
1225
1275
|
summary: record.decision,
|
|
1226
1276
|
output_digest: record.digest,
|
|
@@ -1396,6 +1446,26 @@ function sealFrom(state, stopped, answer, snapshot, baselines) {
|
|
|
1396
1446
|
})),
|
|
1397
1447
|
};
|
|
1398
1448
|
}
|
|
1449
|
+
/**
|
|
1450
|
+
* The redraft a confirmation row's alternative asked for, or `null`.
|
|
1451
|
+
*
|
|
1452
|
+
* It unseats any standing proposal and records a reentry from the flow's
|
|
1453
|
+
* authoring row, so the run walks the redraft and its gate again instead of
|
|
1454
|
+
* carrying on to a publication with nothing to publish and a finalize that
|
|
1455
|
+
* closes the session. Independent of whether a proposal is seated: a proposal
|
|
1456
|
+
* the run gave up on is exactly when redrafting matters most.
|
|
1457
|
+
*/
|
|
1458
|
+
function redraftOf(state, stopped, answer, journey) {
|
|
1459
|
+
const redraft = reentryOf(stopped);
|
|
1460
|
+
if (redraft === null || answer.choice !== redraft.label)
|
|
1461
|
+
return null;
|
|
1462
|
+
return withReentry(withProposal(state, null), {
|
|
1463
|
+
kind: "refine",
|
|
1464
|
+
transition: stopped.id,
|
|
1465
|
+
occurrence: occurrenceAt(journey, state.applied.length),
|
|
1466
|
+
from: redraft.from,
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1399
1469
|
/**
|
|
1400
1470
|
* The grant this answer produced, scoped to what it was given over.
|
|
1401
1471
|
*
|
|
@@ -1410,8 +1480,13 @@ function sealFrom(state, stopped, answer, snapshot, baselines) {
|
|
|
1410
1480
|
*/
|
|
1411
1481
|
function grantOf(state, resolved, answer, granted, journey) {
|
|
1412
1482
|
const stopped = resolved.stopped;
|
|
1483
|
+
if (stopped === null)
|
|
1484
|
+
return state;
|
|
1485
|
+
const redrafted = redraftOf(state, stopped, answer, journey);
|
|
1486
|
+
if (redrafted !== null)
|
|
1487
|
+
return redrafted;
|
|
1413
1488
|
const proposal = state.proposal;
|
|
1414
|
-
const approve =
|
|
1489
|
+
const approve = publishApprovalOf(stopped);
|
|
1415
1490
|
if (approve !== null && proposal !== null) {
|
|
1416
1491
|
if (answer.choice === approve) {
|
|
1417
1492
|
return withApproval(state, {
|
|
@@ -1420,13 +1495,11 @@ function grantOf(state, resolved, answer, granted, journey) {
|
|
|
1420
1495
|
classes: [...proposal.requires_approval],
|
|
1421
1496
|
});
|
|
1422
1497
|
}
|
|
1423
|
-
// Declining unseats the proposal
|
|
1424
|
-
// nothing: the publication downstream finds nothing to publish and is skipped
|
|
1425
|
-
// saying so, instead of stopping to ask for an authorization over bytes the
|
|
1498
|
+
// Declining unseats the proposal: no authorization is asked over bytes the
|
|
1426
1499
|
// person just turned down.
|
|
1427
1500
|
return withProposal(state, null);
|
|
1428
1501
|
}
|
|
1429
|
-
const link =
|
|
1502
|
+
const link = approvalGrantOf(stopped);
|
|
1430
1503
|
if (link !== null && answer.choice === link.approve) {
|
|
1431
1504
|
const target = journey.find((row) => row.id === link.transition);
|
|
1432
1505
|
// A link to a transition this journey does not walk grants nothing: the
|
|
@@ -1457,7 +1530,7 @@ function grantOf(state, resolved, answer, granted, journey) {
|
|
|
1457
1530
|
* a payload the boundary's own contract rejects, a decline (a real answer that
|
|
1458
1531
|
* applies nothing), and an execution result that did not earn its transition.
|
|
1459
1532
|
*/
|
|
1460
|
-
function admit(state, resolved, stopped, input, cost, checkouts) {
|
|
1533
|
+
function admit(state, resolved, stopped, input, cost, checkouts, scoped) {
|
|
1461
1534
|
const expectedApproval = resolved.kind === "authorization"
|
|
1462
1535
|
? effectApprovalDigest(stopped.id, resolved.authorization?.planned ?? [])
|
|
1463
1536
|
: null;
|
|
@@ -1520,22 +1593,53 @@ function admit(state, resolved, stopped, input, cost, checkouts) {
|
|
|
1520
1593
|
// An execution result has to EARN the transition. Anything short of a completed
|
|
1521
1594
|
// run with its evidence and its whole effect keeps the boundary standing: the
|
|
1522
1595
|
// work stays pending, with the recovery the action declared.
|
|
1523
|
-
if (resolved.kind
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1596
|
+
if (resolved.kind !== "execution")
|
|
1597
|
+
return parsed;
|
|
1598
|
+
return earned(state, resolved, stopped, parsed, cost, checkouts, scoped);
|
|
1599
|
+
}
|
|
1600
|
+
/** The execution verdict, then — at the phase validation — the batch's own credit. */
|
|
1601
|
+
function earned(state, resolved, stopped, parsed, cost, checkouts, scoped) {
|
|
1602
|
+
// The row's `effects` are the ceiling and the sealed proposal is what really
|
|
1603
|
+
// happens: demanding an overwrite from a publication that only creates files
|
|
1604
|
+
// would leave the transition pending for an effect nobody could produce.
|
|
1605
|
+
const verdict = executionVerdict(parsed.answer.result, resolved.action, effectsOfTransition(state, stopped), checkouts);
|
|
1606
|
+
if (verdict !== null) {
|
|
1607
|
+
const trace = declaredTrace(state, stopped, resolved, parsed.answer, verdict);
|
|
1608
|
+
return {
|
|
1609
|
+
decision: reject(state, resolved, verdict.message, verdict.detail, {
|
|
1610
|
+
...cost,
|
|
1611
|
+
...(trace === null ? {} : { trace }),
|
|
1612
|
+
}),
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
const credited = batchCredit(state, stopped, parsed.answer, resolved, scoped);
|
|
1616
|
+
if (credited === null)
|
|
1617
|
+
return parsed;
|
|
1618
|
+
if (!credited.ok) {
|
|
1619
|
+
return {
|
|
1620
|
+
decision: reject(state, resolved, credited.refusal.message, credited.refusal.detail, cost),
|
|
1621
|
+
};
|
|
1537
1622
|
}
|
|
1538
|
-
return parsed;
|
|
1623
|
+
return { ...parsed, credit: credited.credit };
|
|
1624
|
+
}
|
|
1625
|
+
/**
|
|
1626
|
+
* The phase validation's own judgment: the batch it closes must bring a proof of
|
|
1627
|
+
* each of its sources, of its own checkout. `null` on every other boundary, and
|
|
1628
|
+
* on a run with no batch standing, where there is nothing to credit.
|
|
1629
|
+
*/
|
|
1630
|
+
function batchCredit(state, stopped, answer, resolved, scoped) {
|
|
1631
|
+
if (stopped.id !== PHASE_VALIDATION || answer.result === null || state.scope === null) {
|
|
1632
|
+
return null;
|
|
1633
|
+
}
|
|
1634
|
+
const iteration = state.batch_loop?.iteration ?? null;
|
|
1635
|
+
const batches = state.batches ?? [];
|
|
1636
|
+
const batch = batches.find((entry) => entry.iteration === iteration);
|
|
1637
|
+
if (batch === undefined)
|
|
1638
|
+
return null;
|
|
1639
|
+
const verdict = batchCreditVerdict(answer.result, { batch, batches, sources: state.scope.sources, scoped }, resolved.action?.recovery ?? "");
|
|
1640
|
+
if (!verdict.ok)
|
|
1641
|
+
return verdict;
|
|
1642
|
+
return { ok: true, credit: { batch: batch.id, proofs: verdict.credit } };
|
|
1539
1643
|
}
|
|
1540
1644
|
/**
|
|
1541
1645
|
* The material fact a REFUSED external result still leaves behind — or `null`.
|
|
@@ -1557,11 +1661,11 @@ function declaredTrace(state, stopped, resolved, answer, verdict) {
|
|
|
1557
1661
|
if (!touchesTheWorld(applied) && verdict.detail.code !== "FLOW_EFFECT_PARTIAL")
|
|
1558
1662
|
return null;
|
|
1559
1663
|
const invocation = resolved.action?.invocation;
|
|
1560
|
-
const
|
|
1664
|
+
const rowIteration = iterationOf(state, stopped.id);
|
|
1561
1665
|
return {
|
|
1562
1666
|
kind: "failed",
|
|
1563
1667
|
transition: stopped.id,
|
|
1564
|
-
...
|
|
1668
|
+
...rowIteration,
|
|
1565
1669
|
// What was really run, named the way whoever ran it would recognize it: an
|
|
1566
1670
|
// external execution has no internal operation id to quote.
|
|
1567
1671
|
operation: invocation === undefined ? stopped.id : [invocation.program, ...invocation.args].join(" "),
|
|
@@ -1618,13 +1722,6 @@ function applyAndAdvance(approved, journey, stopped, identity, answer) {
|
|
|
1618
1722
|
? withObservation(approved, observationFor(approved, stopped.id, answer.signals))
|
|
1619
1723
|
: approved;
|
|
1620
1724
|
next = withPlanExecBatchStageForTransition(applyTransition(next, stopped.id, effectsOfTransition(next, stopped)), stopped.id);
|
|
1621
|
-
// A published proposal is spent, whoever published it. This is the degraded
|
|
1622
|
-
// path — no internal executor, so the caller ran the write and returned its
|
|
1623
|
-
// result — and leaving the proposal seated would keep a preview of bytes that
|
|
1624
|
-
// are already on disk standing in front of the next boundary.
|
|
1625
|
-
if (internalActionOf(stopped)?.operation === "proposal.publish") {
|
|
1626
|
-
next = withProposal(next, null);
|
|
1627
|
-
}
|
|
1628
1725
|
next = withAttempt(next, identity);
|
|
1629
1726
|
// The boundary follows the position, always: handing the engine a state whose
|
|
1630
1727
|
// boundary still names the transition just applied is exactly the incoherence
|
|
@@ -1779,7 +1876,7 @@ function resendCheck(state, resolved, cost) {
|
|
|
1779
1876
|
// The twin was refused: this is a retry of the same wrong answer, so it gets
|
|
1780
1877
|
// the same real diagnosis again and counts toward the cap, which is what
|
|
1781
1878
|
// eventually degrades the boundary instead of leaving the caller looping.
|
|
1782
|
-
if (twin !== undefined &&
|
|
1879
|
+
if (twin !== undefined && twinWasRefused(state, twin))
|
|
1783
1880
|
return null;
|
|
1784
1881
|
return reject(state, resolved, "esta respuesta ya se había aplicado: el recorrido no avanza dos veces", {
|
|
1785
1882
|
code: "FLOW_ANSWER_RESENT",
|
|
@@ -1787,6 +1884,19 @@ function resendCheck(state, resolved, cost) {
|
|
|
1787
1884
|
outcome: "completed",
|
|
1788
1885
|
}, cost);
|
|
1789
1886
|
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Whether the attempt a resend matches never advanced anything.
|
|
1889
|
+
*
|
|
1890
|
+
* Its transition missing from `applied` says so. So does its transition being
|
|
1891
|
+
* the boundary still standing at the same iteration: a repeated row (a batch or
|
|
1892
|
+
* a redraft copy) has its id in `applied` from an earlier walk, and that earlier
|
|
1893
|
+
* walk is not this one.
|
|
1894
|
+
*/
|
|
1895
|
+
function twinWasRefused(state, twin) {
|
|
1896
|
+
if (!state.applied.includes(twin.transition))
|
|
1897
|
+
return true;
|
|
1898
|
+
return (twin.transition === state.boundary && sameIteration(twin, iterationOf(state, twin.transition)));
|
|
1899
|
+
}
|
|
1790
1900
|
/**
|
|
1791
1901
|
* A rejection, expressed as the recalculated directive.
|
|
1792
1902
|
*
|
|
@@ -1848,7 +1958,7 @@ function reject(state, resolved, message, detail, cost) {
|
|
|
1848
1958
|
*/
|
|
1849
1959
|
function attemptIdentity(state, input, seal, transition) {
|
|
1850
1960
|
const digest = semanticDigest({ payload: input.raw, approval: input.approval });
|
|
1851
|
-
const
|
|
1961
|
+
const rowIteration = iterationOf(state, transition);
|
|
1852
1962
|
const prior = state.attempts.filter((past) => past.invocation_id === seal);
|
|
1853
1963
|
const twin = prior.find((past) => past.request_digest === digest);
|
|
1854
1964
|
// The next ordinal, asked with the SAME expression `AttemptLedger.record`
|
|
@@ -1872,18 +1982,18 @@ function attemptIdentity(state, input, seal, transition) {
|
|
|
1872
1982
|
// The seal moves with the state; the transition does not while the run
|
|
1873
1983
|
// stands there. It is what the cap counts over.
|
|
1874
1984
|
transition,
|
|
1875
|
-
...
|
|
1985
|
+
...rowIteration,
|
|
1876
1986
|
};
|
|
1877
1987
|
}
|
|
1878
1988
|
function isRecord(value) {
|
|
1879
1989
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1880
1990
|
}
|
|
1881
1991
|
function observationFor(state, transition, signals) {
|
|
1882
|
-
const
|
|
1992
|
+
const rowIteration = iterationOf(state, transition);
|
|
1883
1993
|
return {
|
|
1884
1994
|
transition,
|
|
1885
1995
|
signals,
|
|
1886
|
-
...
|
|
1996
|
+
...rowIteration,
|
|
1887
1997
|
};
|
|
1888
1998
|
}
|
|
1889
1999
|
//# sourceMappingURL=submit.js.map
|