@tacuchi/agent-workflow-cli 21.6.0 → 21.7.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/dist/application/artifacts-service.js +10 -0
- package/dist/application/artifacts-service.js.map +1 -1
- package/dist/application/capability/design-handler.js +224 -12
- package/dist/application/capability/design-handler.js.map +1 -1
- package/dist/application/capability/dispatcher.js +20 -6
- package/dist/application/capability/dispatcher.js.map +1 -1
- package/dist/application/capability/durable-effect.js +23 -157
- package/dist/application/capability/durable-effect.js.map +1 -1
- package/dist/application/checkpoint-service.js +49 -3
- package/dist/application/checkpoint-service.js.map +1 -1
- package/dist/application/checkpoint-write-service.js +5 -0
- package/dist/application/checkpoint-write-service.js.map +1 -1
- package/dist/application/design/design-gate-service.js +18 -0
- package/dist/application/design/design-gate-service.js.map +1 -1
- package/dist/application/design/design-index-service.js +2 -0
- package/dist/application/design/design-index-service.js.map +1 -1
- package/dist/application/design/design-resolver-service.js +18 -1
- package/dist/application/design/design-resolver-service.js.map +1 -1
- package/dist/application/design/design-simple-service.js +217 -0
- package/dist/application/design/design-simple-service.js.map +1 -0
- package/dist/application/flow/advance.js +96 -11
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/flow-service.js +12 -1
- package/dist/application/flow/flow-service.js.map +1 -1
- package/dist/application/flow/internal-actions.js +221 -0
- package/dist/application/flow/internal-actions.js.map +1 -0
- package/dist/application/flow/internal-drive.js +293 -0
- package/dist/application/flow/internal-drive.js.map +1 -0
- package/dist/application/flow/submit.js +242 -84
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/local-proposal.js +171 -0
- package/dist/application/local-proposal.js.map +1 -0
- package/dist/application/parsers/decisiones.js +13 -0
- package/dist/application/parsers/decisiones.js.map +1 -1
- package/dist/application/paths-service.js +11 -1
- package/dist/application/paths-service.js.map +1 -1
- package/dist/application/resume-service.js +22 -26
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/semantic-operation/protocol.js +10 -2
- package/dist/application/semantic-operation/protocol.js.map +1 -1
- package/dist/application/session-artifacts.js +53 -0
- package/dist/application/session-artifacts.js.map +1 -1
- package/dist/application/session-close-service.js +5 -0
- package/dist/application/session-close-service.js.map +1 -1
- package/dist/application/session-narrative.js +294 -0
- package/dist/application/session-narrative.js.map +1 -0
- package/dist/application/status-service.js +1 -0
- package/dist/application/status-service.js.map +1 -1
- package/dist/application/workline-index-service.js +2 -0
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/cli/commands/capability.js +1 -1
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/designs.js +4 -1
- package/dist/cli/commands/designs.js.map +1 -1
- package/dist/cli/commands/flow.js +14 -0
- package/dist/cli/commands/flow.js.map +1 -1
- package/dist/cli/commands/session-artifacts.js +55 -2
- package/dist/cli/commands/session-artifacts.js.map +1 -1
- package/dist/domain/design/capability.js +35 -4
- package/dist/domain/design/capability.js.map +1 -1
- package/dist/domain/design/direct.js.map +1 -1
- package/dist/domain/design/expansion.js +137 -0
- package/dist/domain/design/expansion.js.map +1 -0
- package/dist/domain/design/manifest.js +61 -8
- package/dist/domain/design/manifest.js.map +1 -1
- package/dist/domain/design/reference.js +57 -10
- package/dist/domain/design/reference.js.map +1 -1
- package/dist/domain/design/simple.js +164 -0
- package/dist/domain/design/simple.js.map +1 -0
- package/dist/domain/flow/answer.js +90 -12
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +266 -60
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/authorization.js +36 -15
- package/dist/domain/flow/authorization.js.map +1 -1
- package/dist/domain/flow/directive.js +10 -6
- package/dist/domain/flow/directive.js.map +1 -1
- package/dist/domain/flow/execution-result.js +72 -0
- package/dist/domain/flow/execution-result.js.map +1 -0
- package/dist/domain/flow/run-state.js +165 -13
- package/dist/domain/flow/run-state.js.map +1 -1
- package/dist/domain/host-verification.js +8 -8
- package/dist/domain/host-verification.js.map +1 -1
- package/dist/domain/proposal.js +91 -0
- package/dist/domain/proposal.js.map +1 -0
- package/dist/domain/session/narrative.js +126 -0
- package/dist/domain/session/narrative.js.map +1 -0
- package/package.json +1 -1
- package/skills/w/SKILL.md +1 -1
- package/skills/w/loops/CHASSIS.md +1 -1
- package/skills/w/loops/plan-new-loop/LOOP.md +5 -6
- package/skills/w/loops/plan-refine-loop/LOOP.md +7 -7
- package/skills/w/loops/spec-refine-loop/LOOP.md +6 -4
- package/skills/w/modules/DESIGN-REFERENCES.md +50 -56
- package/skills/w/roles/design/CONTRACT.md +73 -6
- package/skills/w/roles/design/ROLE.md +21 -3
- package/skills/w/schemas/design/design-manifest.v1.schema.json +4 -0
|
@@ -31,6 +31,14 @@ export const CHASSIS_SCOPE = "chassis";
|
|
|
31
31
|
export const COMMAND_SCOPE_PREFIX = "cmd:";
|
|
32
32
|
/** The four migration tranches the plan cuts over one at a time. */
|
|
33
33
|
export const FLOW_TRANCHES = ["quick", "spec", "plan", "chassis"];
|
|
34
|
+
/** The proposal contract of an authoring row, or `null` when it proposes nothing. */
|
|
35
|
+
export function proposalContractOf(decision) {
|
|
36
|
+
return decision.proposes ?? null;
|
|
37
|
+
}
|
|
38
|
+
/** The approve label of a row that decides a standing proposal, or `null`. */
|
|
39
|
+
export function publishApprovalOf(decision) {
|
|
40
|
+
return decision.publishes?.approve ?? null;
|
|
41
|
+
}
|
|
34
42
|
/** A decision computes a verdict; writing is the exception that declares itself. */
|
|
35
43
|
export const DEFAULT_TRANSITION_EFFECTS = ["read_only"];
|
|
36
44
|
/** What applying this transition does. */
|
|
@@ -46,10 +54,75 @@ export function effectsOf(decision) {
|
|
|
46
54
|
* folder and its correlative — and both are facts the engine owns.
|
|
47
55
|
*/
|
|
48
56
|
export const RUN_PLACEHOLDERS = ["{session}", "{code}"];
|
|
57
|
+
/**
|
|
58
|
+
* The Workline operations this CLI materializes inside its own process.
|
|
59
|
+
*
|
|
60
|
+
* A CLOSED union, and closed is the whole point of it. An action executed
|
|
61
|
+
* internally is one nobody read as a command line first, so what may run that way
|
|
62
|
+
* has to be enumerable, auditable and impossible to widen with data: the row names
|
|
63
|
+
* an operation, never a program. `invocation.program` and `invocation.args` are
|
|
64
|
+
* NEVER interpreted — they stay as the equivalent command a person would run to
|
|
65
|
+
* obtain the same reading, which is what keeps the two comparable.
|
|
66
|
+
*
|
|
67
|
+
* The four members are exactly the deterministic surface the plan names: the
|
|
68
|
+
* board, the sessions' own artifacts (their reading and their seeding), the close
|
|
69
|
+
* and the publication of an already approved proposal. Everything that runs code,
|
|
70
|
+
* touches git or produces a judgment is deliberately NOT here.
|
|
71
|
+
*
|
|
72
|
+
* Publishing is the one that writes documents the engine does not author, and it
|
|
73
|
+
* is admissible for a reason the others do not need: it writes NOTHING of its own
|
|
74
|
+
* — only the exact bytes a person approved, under the seal they approved them by.
|
|
75
|
+
*/
|
|
76
|
+
export const INTERNAL_ACTION_OPERATIONS = [
|
|
77
|
+
/** Project the workspace board — what `aw status --json` returns. */
|
|
78
|
+
"workspace.board",
|
|
79
|
+
/** Read, and where the command seeds them, a session's own artifacts. */
|
|
80
|
+
"session.artifacts",
|
|
81
|
+
/** Close the session and upsert its HISTORY row. */
|
|
82
|
+
"session.close",
|
|
83
|
+
/** Write the run's approved proposal, all of it or none of it. */
|
|
84
|
+
"proposal.publish",
|
|
85
|
+
];
|
|
86
|
+
/**
|
|
87
|
+
* The effect classes each internal operation can really apply.
|
|
88
|
+
*
|
|
89
|
+
* Read by the guard, not by the runtime: at runtime the executor reports what it
|
|
90
|
+
* ACTUALLY applied and the same `executionVerdict` that judges an external result
|
|
91
|
+
* refuses anything short of the row's declared effects. This table is what makes
|
|
92
|
+
* the mismatch a failing test instead of a run that discovers it — a row declaring
|
|
93
|
+
* `mutate_overwrite` while its operation only reads can never be satisfied, and
|
|
94
|
+
* finding that out at the boundary is finding it out too late.
|
|
95
|
+
*/
|
|
96
|
+
export const INTERNAL_OPERATION_EFFECTS = {
|
|
97
|
+
"workspace.board": ["read_only"],
|
|
98
|
+
"session.artifacts": ["read_only", "local_additive"],
|
|
99
|
+
"session.close": ["read_only", "local_additive", "mutate_overwrite"],
|
|
100
|
+
// Creating and replacing, both real — and which of the two happens is decided
|
|
101
|
+
// by the proposal, not by the row: what the row declares here is the ceiling.
|
|
102
|
+
"proposal.publish": ["local_additive", "mutate_overwrite"],
|
|
103
|
+
};
|
|
49
104
|
/** The delegated action of a transition, or `null` when the engine applies it itself. */
|
|
50
105
|
export function actionOf(decision) {
|
|
51
106
|
return decision.action ?? null;
|
|
52
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* What this transition runs in-process, or `null` when whoever called it must.
|
|
110
|
+
*
|
|
111
|
+
* One predicate for every caller — the walk, the driver and the guard — so none of
|
|
112
|
+
* them can answer "does the CLI run this itself?" differently from the others.
|
|
113
|
+
*
|
|
114
|
+
* An action with no `execution` at all cannot happen through the type, and it is
|
|
115
|
+
* still read defensively: the answer for a malformed row is "not the CLI's", which
|
|
116
|
+
* fails closed. Throwing instead would take down every caller that merely ASKS the
|
|
117
|
+
* question — and asking it is now on the path of every boundary.
|
|
118
|
+
*/
|
|
119
|
+
export function internalActionOf(decision) {
|
|
120
|
+
const action = actionOf(decision);
|
|
121
|
+
if (action === null || action.execution?.kind !== "internal")
|
|
122
|
+
return null;
|
|
123
|
+
const { kind: _internal, ...plan } = action.execution;
|
|
124
|
+
return plan;
|
|
125
|
+
}
|
|
53
126
|
/** What makes this transition happen at all, or `null` when it always does. */
|
|
54
127
|
export function conditionOf(decision) {
|
|
55
128
|
return decision.condition ?? null;
|
|
@@ -397,9 +470,14 @@ export const FLOW_DECISIONS = [
|
|
|
397
470
|
// judged. `quick` has none because it has no document to write it into, and
|
|
398
471
|
// the two plan-authoring flows converge on a document they hand to the next
|
|
399
472
|
// flow rather than on one they mark green.
|
|
473
|
+
//
|
|
474
|
+
// SPEC's used to be a promotion of its own, `status: ready-for-plan` written
|
|
475
|
+
// after the save. It is now the publication: the stamp travels inside the
|
|
476
|
+
// approved bytes, so the row that marks the criteria green is the row that
|
|
477
|
+
// writes them — one document, one write.
|
|
400
478
|
realized_by: {
|
|
401
479
|
kind: "transitions",
|
|
402
|
-
ids: ["spec-refine.
|
|
480
|
+
ids: ["spec-refine.publication", "plan-exec.plan-done"],
|
|
403
481
|
},
|
|
404
482
|
},
|
|
405
483
|
{
|
|
@@ -459,6 +537,7 @@ export const FLOW_DECISIONS = [
|
|
|
459
537
|
target: ".",
|
|
460
538
|
input: null,
|
|
461
539
|
},
|
|
540
|
+
execution: { kind: "internal", operation: "session.close" },
|
|
462
541
|
evidence: ["chassis.sesion-cerrada"],
|
|
463
542
|
idempotent: true,
|
|
464
543
|
recovery: "una sesión que no cerró deja la corrida abierta: no la marques finalizada — reparás la fila del registro con 'aw history-update' y volvés a cerrar",
|
|
@@ -519,6 +598,7 @@ export const FLOW_DECISIONS = [
|
|
|
519
598
|
// "I looked". Read-only, so it never stops to be authorized.
|
|
520
599
|
action: {
|
|
521
600
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
601
|
+
execution: { kind: "internal", operation: "workspace.board" },
|
|
522
602
|
evidence: ["quick.board-listed"],
|
|
523
603
|
idempotent: true,
|
|
524
604
|
recovery: "volvé a correr 'aw status --json' y devolvé su salida real; si el tablero no se puede leer, resolvé eso antes de seguir",
|
|
@@ -576,6 +656,7 @@ export const FLOW_DECISIONS = [
|
|
|
576
656
|
target: SESSION_TARGET,
|
|
577
657
|
input: null,
|
|
578
658
|
},
|
|
659
|
+
execution: { kind: "internal", operation: "session.artifacts" },
|
|
579
660
|
evidence: ["quick.session-present"],
|
|
580
661
|
idempotent: true,
|
|
581
662
|
recovery: "creá la sesión con 'aw session-create --type quick --name <slug>-quick --objetivo \"<objetivo>\"' y volvé a devolver la lectura",
|
|
@@ -625,6 +706,11 @@ export const FLOW_DECISIONS = [
|
|
|
625
706
|
target: SESSION_TARGET,
|
|
626
707
|
input: null,
|
|
627
708
|
},
|
|
709
|
+
execution: {
|
|
710
|
+
kind: "internal",
|
|
711
|
+
operation: "session.artifacts",
|
|
712
|
+
dump: ["objetivo", "checkpoint"],
|
|
713
|
+
},
|
|
628
714
|
evidence: [
|
|
629
715
|
"quick.objetivo-sembrado",
|
|
630
716
|
"quick.criterios-sembrados",
|
|
@@ -646,6 +732,10 @@ export const FLOW_DECISIONS = [
|
|
|
646
732
|
// --source resolves no target and passes unconditionally.
|
|
647
733
|
action: {
|
|
648
734
|
invocation: { program: "aw", args: ["sources", "--verbose"], target: ".", input: null },
|
|
735
|
+
execution: {
|
|
736
|
+
kind: "external",
|
|
737
|
+
reason: "la rama esperada de cada fuente es un veredicto sobre git, y un workspace sin fuentes declaradas no lo tiene: leerlo desde adentro diría 'verificada' donde no hay nada que verificar",
|
|
738
|
+
},
|
|
649
739
|
evidence: ["quick.rama-verificada"],
|
|
650
740
|
idempotent: true,
|
|
651
741
|
recovery: "resolvé la rama de la fuente que no coincide y volvé a leer las fuentes: nunca limpies ni cambies de rama sin confirmación",
|
|
@@ -699,6 +789,7 @@ export const FLOW_DECISIONS = [
|
|
|
699
789
|
target: SESSION_TARGET,
|
|
700
790
|
input: null,
|
|
701
791
|
},
|
|
792
|
+
execution: { kind: "internal", operation: "session.artifacts", dump: ["scripts"] },
|
|
702
793
|
evidence: ["quick.scripts-derivados"],
|
|
703
794
|
idempotent: true,
|
|
704
795
|
recovery: "escribí el DDL o DML en el SCRIPTS.sql de la sesión y volvé a devolver el dump; ejecutarlo no es una alternativa que este contrato admita",
|
|
@@ -745,6 +836,10 @@ export const FLOW_DECISIONS = [
|
|
|
745
836
|
target: SESSION_TARGET,
|
|
746
837
|
input: null,
|
|
747
838
|
},
|
|
839
|
+
execution: {
|
|
840
|
+
kind: "external",
|
|
841
|
+
reason: "los criterios verdes exigen haber CORRIDO la prueba del entregable, y correr código nunca es una operación interna",
|
|
842
|
+
},
|
|
748
843
|
evidence: ["quick.criterios-verdes"],
|
|
749
844
|
idempotent: true,
|
|
750
845
|
recovery: "arreglá lo que el criterio reprobó y volvé a correr sus validaciones: la transición sigue pendiente hasta que su salida real vuelva en verde",
|
|
@@ -809,6 +904,7 @@ export const FLOW_DECISIONS = [
|
|
|
809
904
|
target: SESSION_TARGET,
|
|
810
905
|
input: null,
|
|
811
906
|
},
|
|
907
|
+
execution: { kind: "internal", operation: "session.artifacts" },
|
|
812
908
|
evidence: ["spec.session-present"],
|
|
813
909
|
idempotent: true,
|
|
814
910
|
recovery: "creá la sesión con 'aw session-create --type refine --name <slug>-spec-refine --objetivo \"<objetivo>\"' y volvé a devolver la lectura",
|
|
@@ -1025,15 +1121,37 @@ export const FLOW_DECISIONS = [
|
|
|
1025
1121
|
target: SESSION_TARGET,
|
|
1026
1122
|
input: null,
|
|
1027
1123
|
},
|
|
1124
|
+
execution: {
|
|
1125
|
+
kind: "external",
|
|
1126
|
+
reason: "el checklist de ready-for-plan es un juicio sobre lo que dice la spec, no la lectura del artefacto que lo contiene",
|
|
1127
|
+
},
|
|
1028
1128
|
evidence: ["spec.ready-for-plan-checklist"],
|
|
1029
1129
|
idempotent: true,
|
|
1030
1130
|
recovery: "lo que el checklist reprobó vuelve al loop como gap: resolvelo y volvé a evaluar el gate con su estado real",
|
|
1031
1131
|
},
|
|
1032
1132
|
},
|
|
1133
|
+
{
|
|
1134
|
+
id: "spec-refine.save-proposal",
|
|
1135
|
+
scope: "spec-refine",
|
|
1136
|
+
title: "entregar los bytes exactos de la spec refinada, con su status ya sellado",
|
|
1137
|
+
authority: "agent",
|
|
1138
|
+
ownership: "cli-owned",
|
|
1139
|
+
document: SPEC_LOOP,
|
|
1140
|
+
attribution: SPEC_ATTRIBUTION,
|
|
1141
|
+
// The stamp travels INSIDE these bytes, and that is the whole reason the
|
|
1142
|
+
// separate promotion row is gone: `status: ready-for-plan` is a projection of
|
|
1143
|
+
// the same save, so writing it apart made the person confirm one half and
|
|
1144
|
+
// authorize the other. One document, one proposal, one write.
|
|
1145
|
+
proposes: {
|
|
1146
|
+
destinations: ["docs/specs"],
|
|
1147
|
+
effects: ["local_additive", "mutate_overwrite"],
|
|
1148
|
+
limits: { maxArtifacts: 8, maxArtifactBytes: 256 * 1024 },
|
|
1149
|
+
},
|
|
1150
|
+
},
|
|
1033
1151
|
{
|
|
1034
1152
|
id: "spec-refine.save-confirmation",
|
|
1035
1153
|
scope: "spec-refine",
|
|
1036
|
-
title: "
|
|
1154
|
+
title: "aprobar la vista previa de la spec y guardarla",
|
|
1037
1155
|
authority: "human",
|
|
1038
1156
|
ownership: "cli-owned",
|
|
1039
1157
|
document: SPEC_LOOP,
|
|
@@ -1042,37 +1160,35 @@ export const FLOW_DECISIONS = [
|
|
|
1042
1160
|
// was promoting the status and asking for the overwrite afterwards, so the
|
|
1043
1161
|
// person would have been confirming a write that already happened. The
|
|
1044
1162
|
// doctrine's own line is `edit_in_place_with_confirm(spec) + stamp`.
|
|
1163
|
+
publishes: { approve: "Aprobar y guardar" },
|
|
1045
1164
|
alternatives: [
|
|
1046
1165
|
{
|
|
1047
|
-
label: "
|
|
1048
|
-
consequence: "la
|
|
1166
|
+
label: "Aprobar y guardar",
|
|
1167
|
+
consequence: "se escriben exactamente los archivos de la vista previa —la spec en su lugar, sellada como ready-for-plan— y no se vuelve a preguntar por esos efectos",
|
|
1049
1168
|
recommended: true,
|
|
1050
1169
|
},
|
|
1051
1170
|
{
|
|
1052
|
-
label: "
|
|
1053
|
-
consequence: "el refinamiento sigue abierto y la spec queda como está",
|
|
1171
|
+
label: "Refinar",
|
|
1172
|
+
consequence: "el refinamiento sigue abierto, no se escribe nada y la spec queda como está",
|
|
1054
1173
|
recommended: false,
|
|
1055
1174
|
},
|
|
1056
1175
|
],
|
|
1057
1176
|
},
|
|
1058
1177
|
{
|
|
1059
|
-
id: "spec-refine.
|
|
1178
|
+
id: "spec-refine.publication",
|
|
1060
1179
|
scope: "spec-refine",
|
|
1061
|
-
title: "
|
|
1180
|
+
title: "publicar la propuesta aprobada de la spec en un solo acto",
|
|
1062
1181
|
authority: "cli",
|
|
1063
1182
|
ownership: "cli-owned",
|
|
1064
1183
|
document: SPEC_LOOP,
|
|
1065
1184
|
attribution: SPEC_ATTRIBUTION,
|
|
1066
|
-
effects: ["mutate_overwrite"],
|
|
1067
|
-
// The stamp is a write on a document the engine does not edit, so what it
|
|
1068
|
-
// demands back is the board's own reading of that document's status. The
|
|
1069
|
-
// effect is not self-authorizable: the run stops to be authorized before this
|
|
1070
|
-
// invocation is ever named.
|
|
1185
|
+
effects: ["local_additive", "mutate_overwrite"],
|
|
1071
1186
|
action: {
|
|
1072
|
-
invocation: { program: "aw", args: ["
|
|
1073
|
-
|
|
1187
|
+
invocation: { program: "aw", args: ["flow", "advance"], target: ".", input: null },
|
|
1188
|
+
execution: { kind: "internal", operation: "proposal.publish" },
|
|
1189
|
+
evidence: ["spec.propuesta-publicada"],
|
|
1074
1190
|
idempotent: true,
|
|
1075
|
-
recovery: "
|
|
1191
|
+
recovery: "la publicación es todo-o-nada: si falló, nada quedó escrito y se reintenta el mismo contenido sin volver a aprobar; si la base cambió, volvé a redactar la propuesta sobre el documento vigente",
|
|
1076
1192
|
},
|
|
1077
1193
|
},
|
|
1078
1194
|
// ── PLAN — new ────────────────────────────────────────────────────────────
|
|
@@ -1094,6 +1210,7 @@ export const FLOW_DECISIONS = [
|
|
|
1094
1210
|
// that somebody looked. Suggesting is the outcome; it never blocks.
|
|
1095
1211
|
action: {
|
|
1096
1212
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
1213
|
+
execution: { kind: "internal", operation: "workspace.board" },
|
|
1097
1214
|
evidence: ["plan.spec-status-leido"],
|
|
1098
1215
|
idempotent: true,
|
|
1099
1216
|
recovery: "volvé a correr 'aw status --json' y devolvé su salida real; sin el status de la spec no hay nada que sugerir ni que dar por listo",
|
|
@@ -1115,6 +1232,7 @@ export const FLOW_DECISIONS = [
|
|
|
1115
1232
|
target: SESSION_TARGET,
|
|
1116
1233
|
input: null,
|
|
1117
1234
|
},
|
|
1235
|
+
execution: { kind: "internal", operation: "session.artifacts" },
|
|
1118
1236
|
evidence: ["plan.session-present"],
|
|
1119
1237
|
idempotent: true,
|
|
1120
1238
|
recovery: "creá la sesión con 'aw session-create --type refine --name <slug>-plan-new --objetivo \"<objetivo>\"' y volvé a devolver la lectura",
|
|
@@ -1248,32 +1366,72 @@ export const FLOW_DECISIONS = [
|
|
|
1248
1366
|
target: SESSION_TARGET,
|
|
1249
1367
|
input: null,
|
|
1250
1368
|
},
|
|
1369
|
+
execution: {
|
|
1370
|
+
kind: "external",
|
|
1371
|
+
reason: "la coherencia del plan es un juicio sobre lo que dice, no la lectura del artefacto que lo contiene",
|
|
1372
|
+
},
|
|
1251
1373
|
evidence: ["plan.coherence-checklist"],
|
|
1252
1374
|
idempotent: true,
|
|
1253
1375
|
recovery: "lo que el checklist reprobó vuelve al loop como gap: resolvelo y volvé a evaluar el gate con su estado real",
|
|
1254
1376
|
},
|
|
1255
1377
|
},
|
|
1378
|
+
{
|
|
1379
|
+
id: "plan-new.save-proposal",
|
|
1380
|
+
scope: "plan-new",
|
|
1381
|
+
title: "entregar los bytes exactos del plan y de los hermanos que se extraigan",
|
|
1382
|
+
authority: "agent",
|
|
1383
|
+
ownership: "cli-owned",
|
|
1384
|
+
document: PLAN_NEW_LOOP,
|
|
1385
|
+
attribution: PLAN_ATTRIBUTION,
|
|
1386
|
+
// The generation used to write with NO effect row at all: the person confirmed
|
|
1387
|
+
// and the document appeared, with the engine crediting nothing. The proposal
|
|
1388
|
+
// is what makes that write visible — enumerated, weighed and sealed before it
|
|
1389
|
+
// is approved.
|
|
1390
|
+
proposes: {
|
|
1391
|
+
destinations: ["docs/plans"],
|
|
1392
|
+
effects: ["local_additive"],
|
|
1393
|
+
limits: { maxArtifacts: 8, maxArtifactBytes: 256 * 1024 },
|
|
1394
|
+
},
|
|
1395
|
+
},
|
|
1256
1396
|
{
|
|
1257
1397
|
id: "plan-new.save-confirmation",
|
|
1258
1398
|
scope: "plan-new",
|
|
1259
|
-
title: "
|
|
1399
|
+
title: "aprobar la vista previa del plan y guardarlo",
|
|
1260
1400
|
authority: "human",
|
|
1261
1401
|
ownership: "cli-owned",
|
|
1262
1402
|
document: PLAN_NEW_LOOP,
|
|
1263
1403
|
attribution: PLAN_ATTRIBUTION,
|
|
1404
|
+
publishes: { approve: "Aprobar y guardar" },
|
|
1264
1405
|
alternatives: [
|
|
1265
1406
|
{
|
|
1266
|
-
label: "
|
|
1267
|
-
consequence: "
|
|
1407
|
+
label: "Aprobar y guardar",
|
|
1408
|
+
consequence: "se escriben exactamente los archivos de la vista previa en docs/plans, hermanos incluidos si el split fue aceptado",
|
|
1268
1409
|
recommended: true,
|
|
1269
1410
|
},
|
|
1270
1411
|
{
|
|
1271
|
-
label: "
|
|
1412
|
+
label: "Refinar",
|
|
1272
1413
|
consequence: "la generación sigue abierta y no se escribe ningún documento",
|
|
1273
1414
|
recommended: false,
|
|
1274
1415
|
},
|
|
1275
1416
|
],
|
|
1276
1417
|
},
|
|
1418
|
+
{
|
|
1419
|
+
id: "plan-new.publication",
|
|
1420
|
+
scope: "plan-new",
|
|
1421
|
+
title: "publicar la propuesta aprobada del plan en un solo acto",
|
|
1422
|
+
authority: "cli",
|
|
1423
|
+
ownership: "cli-owned",
|
|
1424
|
+
document: PLAN_NEW_LOOP,
|
|
1425
|
+
attribution: PLAN_ATTRIBUTION,
|
|
1426
|
+
effects: ["local_additive"],
|
|
1427
|
+
action: {
|
|
1428
|
+
invocation: { program: "aw", args: ["flow", "advance"], target: ".", input: null },
|
|
1429
|
+
execution: { kind: "internal", operation: "proposal.publish" },
|
|
1430
|
+
evidence: ["plan.propuesta-publicada"],
|
|
1431
|
+
idempotent: true,
|
|
1432
|
+
recovery: "la publicación es todo-o-nada: si falló, no quedó ningún documento a medias y se reintenta el mismo contenido sin volver a aprobar",
|
|
1433
|
+
},
|
|
1434
|
+
},
|
|
1277
1435
|
{
|
|
1278
1436
|
id: "plan-new.adoption",
|
|
1279
1437
|
scope: "plan-new",
|
|
@@ -1300,6 +1458,7 @@ export const FLOW_DECISIONS = [
|
|
|
1300
1458
|
target: SESSION_TARGET,
|
|
1301
1459
|
input: null,
|
|
1302
1460
|
},
|
|
1461
|
+
execution: { kind: "internal", operation: "session.artifacts" },
|
|
1303
1462
|
evidence: ["plan.session-present"],
|
|
1304
1463
|
idempotent: true,
|
|
1305
1464
|
recovery: "creá o reabrí la sesión con 'aw session-create' o 'aw session-resume --code <NNN> --reopen' y volvé a devolver la lectura",
|
|
@@ -1384,75 +1543,89 @@ export const FLOW_DECISIONS = [
|
|
|
1384
1543
|
target: SESSION_TARGET,
|
|
1385
1544
|
input: null,
|
|
1386
1545
|
},
|
|
1546
|
+
execution: {
|
|
1547
|
+
kind: "external",
|
|
1548
|
+
reason: "la forma ejecutable del plan es un juicio sobre lo que dice, no la lectura del artefacto que lo contiene",
|
|
1549
|
+
},
|
|
1387
1550
|
evidence: ["plan.executability-checklist"],
|
|
1388
1551
|
idempotent: true,
|
|
1389
1552
|
recovery: "lo que el checklist reprobó vuelve al loop como gap: resolvelo y volvé a evaluar el gate con su estado real",
|
|
1390
1553
|
},
|
|
1391
1554
|
},
|
|
1555
|
+
{
|
|
1556
|
+
id: "plan-refine.split-in-place",
|
|
1557
|
+
scope: "plan-refine",
|
|
1558
|
+
title: "reducir el plan original y extraer los hermanos sin mover trabajo completado",
|
|
1559
|
+
authority: "agent",
|
|
1560
|
+
ownership: "cli-owned",
|
|
1561
|
+
document: PLAN_REFINE_SPLIT,
|
|
1562
|
+
attribution: PLAN_ATTRIBUTION,
|
|
1563
|
+
// It used to be a delegated WRITE after the confirmation, which is what made
|
|
1564
|
+
// the refinement ask twice: once to confirm the plan and again to authorize
|
|
1565
|
+
// the siblings. Reducing the original and extracting the siblings is drafting
|
|
1566
|
+
// — it decides what the bytes are — so it happens BEFORE the proposal and its
|
|
1567
|
+
// result is visible where it belongs, as files enumerated in the preview.
|
|
1568
|
+
// Nothing is credited here: this row no longer claims a write happened.
|
|
1569
|
+
condition: {
|
|
1570
|
+
threshold: splitThreshold("plan-refine.split-signal"),
|
|
1571
|
+
otherwise: "el umbral de dos señales no disparó: el plan conserva su número y su alcance, y no se extrae ningún hermano",
|
|
1572
|
+
},
|
|
1573
|
+
},
|
|
1574
|
+
{
|
|
1575
|
+
id: "plan-refine.save-proposal",
|
|
1576
|
+
scope: "plan-refine",
|
|
1577
|
+
title: "entregar los bytes exactos del plan refinado, ya normalizado, sin bloques condicionales vacíos y sin tocar estados ni casillas",
|
|
1578
|
+
authority: "agent",
|
|
1579
|
+
ownership: "cli-owned",
|
|
1580
|
+
document: PLAN_REFINE_LOOP,
|
|
1581
|
+
attribution: PLAN_ATTRIBUTION,
|
|
1582
|
+
// The normalization rule lives in this row's own contract now, and that is the
|
|
1583
|
+
// merge that removes a write: normalizing the form is not a second edit of the
|
|
1584
|
+
// plan, it is what the drafted bytes already are. A separate row for it wrote
|
|
1585
|
+
// the same document twice and asked to be authorized for the second half.
|
|
1586
|
+
proposes: {
|
|
1587
|
+
destinations: ["docs/plans"],
|
|
1588
|
+
effects: ["local_additive", "mutate_overwrite"],
|
|
1589
|
+
limits: { maxArtifacts: 8, maxArtifactBytes: 256 * 1024 },
|
|
1590
|
+
},
|
|
1591
|
+
},
|
|
1392
1592
|
{
|
|
1393
1593
|
id: "plan-refine.save-confirmation",
|
|
1394
1594
|
scope: "plan-refine",
|
|
1395
|
-
title: "
|
|
1595
|
+
title: "aprobar la vista previa del plan refinado y guardarlo",
|
|
1396
1596
|
authority: "human",
|
|
1397
1597
|
ownership: "cli-owned",
|
|
1398
1598
|
document: PLAN_REFINE_LOOP,
|
|
1399
1599
|
attribution: PLAN_ATTRIBUTION,
|
|
1600
|
+
publishes: { approve: "Aprobar y guardar" },
|
|
1400
1601
|
alternatives: [
|
|
1401
1602
|
{
|
|
1402
|
-
label: "
|
|
1403
|
-
consequence: "el plan
|
|
1603
|
+
label: "Aprobar y guardar",
|
|
1604
|
+
consequence: "se escriben exactamente los archivos de la vista previa —el plan en su lugar y los hermanos extraídos, si los hay— y no se vuelve a preguntar por esos efectos",
|
|
1404
1605
|
recommended: true,
|
|
1405
1606
|
},
|
|
1406
1607
|
{
|
|
1407
|
-
label: "
|
|
1408
|
-
consequence: "el refinamiento sigue abierto y el plan queda como está",
|
|
1608
|
+
label: "Refinar",
|
|
1609
|
+
consequence: "el refinamiento sigue abierto, no se escribe nada y el plan queda como está",
|
|
1409
1610
|
recommended: false,
|
|
1410
1611
|
},
|
|
1411
1612
|
],
|
|
1412
1613
|
},
|
|
1413
1614
|
{
|
|
1414
|
-
id: "plan-refine.
|
|
1415
|
-
scope: "plan-refine",
|
|
1416
|
-
title: "reducir el plan original y extraer los hermanos sin mover trabajo completado",
|
|
1417
|
-
authority: "cli",
|
|
1418
|
-
ownership: "cli-owned",
|
|
1419
|
-
document: PLAN_REFINE_SPLIT,
|
|
1420
|
-
attribution: PLAN_ATTRIBUTION,
|
|
1421
|
-
effects: ["local_additive", "mutate_overwrite"],
|
|
1422
|
-
// AFTER the confirmation, and the doctrine's own sequence is why: the save
|
|
1423
|
-
// branch reads `Guardar planes → edit original reduced (confirmation) + write
|
|
1424
|
-
// extracted siblings`. The registry had both writes ahead of the gate and of
|
|
1425
|
-
// the confirmation — the same defect the SPEC tranche found in its stamp, so
|
|
1426
|
-
// the order moved to where the document puts it.
|
|
1427
|
-
action: {
|
|
1428
|
-
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
1429
|
-
evidence: ["plan.hermanos-extraidos"],
|
|
1430
|
-
idempotent: true,
|
|
1431
|
-
recovery: "reducí el original en su lugar, escribí los hermanos extraídos y volvé a devolver la lectura; una tarea ya marcada nunca se muda a un hermano",
|
|
1432
|
-
},
|
|
1433
|
-
condition: {
|
|
1434
|
-
threshold: splitThreshold("plan-refine.split-signal"),
|
|
1435
|
-
otherwise: "el umbral de dos señales no disparó: el plan conserva su número y su alcance, y no se extrae ningún hermano",
|
|
1436
|
-
},
|
|
1437
|
-
},
|
|
1438
|
-
{
|
|
1439
|
-
id: "plan-refine.normalize-on-write",
|
|
1615
|
+
id: "plan-refine.publication",
|
|
1440
1616
|
scope: "plan-refine",
|
|
1441
|
-
title: "
|
|
1617
|
+
title: "publicar la propuesta aprobada del plan refinado en un solo acto",
|
|
1442
1618
|
authority: "cli",
|
|
1443
1619
|
ownership: "cli-owned",
|
|
1444
1620
|
document: PLAN_REFINE_LOOP,
|
|
1445
1621
|
attribution: PLAN_ATTRIBUTION,
|
|
1446
|
-
effects: ["mutate_overwrite"],
|
|
1447
|
-
// A write on a document the engine does not edit, so it is delegated like
|
|
1448
|
-
// every other one. It had neither action nor evidence, which meant the run
|
|
1449
|
-
// recorded "normalized" for something nothing performed — the phantom
|
|
1450
|
-
// confirmation this whole contract exists to refuse.
|
|
1622
|
+
effects: ["local_additive", "mutate_overwrite"],
|
|
1451
1623
|
action: {
|
|
1452
|
-
invocation: { program: "aw", args: ["
|
|
1453
|
-
|
|
1624
|
+
invocation: { program: "aw", args: ["flow", "advance"], target: ".", input: null },
|
|
1625
|
+
execution: { kind: "internal", operation: "proposal.publish" },
|
|
1626
|
+
evidence: ["plan.propuesta-publicada"],
|
|
1454
1627
|
idempotent: true,
|
|
1455
|
-
recovery: "
|
|
1628
|
+
recovery: "la publicación es todo-o-nada: el original reducido y sus hermanos entran juntos o no entra ninguno; si la base cambió, volvé a redactar la propuesta sobre el plan vigente",
|
|
1456
1629
|
},
|
|
1457
1630
|
},
|
|
1458
1631
|
// ── PLAN — exec ───────────────────────────────────────────────────────────
|
|
@@ -1472,6 +1645,7 @@ export const FLOW_DECISIONS = [
|
|
|
1472
1645
|
target: SESSION_TARGET,
|
|
1473
1646
|
input: null,
|
|
1474
1647
|
},
|
|
1648
|
+
execution: { kind: "internal", operation: "session.artifacts" },
|
|
1475
1649
|
evidence: ["plan.session-present"],
|
|
1476
1650
|
idempotent: true,
|
|
1477
1651
|
recovery: "creá la sesión con 'aw session-create --type exec --name <slug>-plan-exec --objetivo \"<objetivo>\"' y volvé a devolver la lectura",
|
|
@@ -1491,6 +1665,10 @@ export const FLOW_DECISIONS = [
|
|
|
1491
1665
|
// the gate's finding, not a detail to wave through.
|
|
1492
1666
|
action: {
|
|
1493
1667
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
1668
|
+
execution: {
|
|
1669
|
+
kind: "external",
|
|
1670
|
+
reason: "la forma ejecutable del plan es un juicio sobre lo que dice, no la lectura del tablero que lo lista",
|
|
1671
|
+
},
|
|
1494
1672
|
evidence: ["plan.forma-ejecutable"],
|
|
1495
1673
|
idempotent: true,
|
|
1496
1674
|
recovery: "volvé a correr 'aw status --json' y devolvé su salida real; si el plan no se puede leer, eso ES el hallazgo del gate",
|
|
@@ -1615,6 +1793,10 @@ export const FLOW_DECISIONS = [
|
|
|
1615
1793
|
// its current branch, the expected one and whether they match.
|
|
1616
1794
|
action: {
|
|
1617
1795
|
invocation: { program: "aw", args: ["sources", "--verbose"], target: ".", input: null },
|
|
1796
|
+
execution: {
|
|
1797
|
+
kind: "external",
|
|
1798
|
+
reason: "la rama esperada de cada fuente es un veredicto sobre git, y un workspace sin fuentes declaradas no lo tiene",
|
|
1799
|
+
},
|
|
1618
1800
|
evidence: ["plan.rama-verificada"],
|
|
1619
1801
|
idempotent: true,
|
|
1620
1802
|
recovery: "resolvé la rama de la fuente que no coincide y volvé a leer las fuentes: nunca limpies ni cambies de rama sin confirmación",
|
|
@@ -1698,6 +1880,10 @@ export const FLOW_DECISIONS = [
|
|
|
1698
1880
|
// ticked boxes. "I marked it" is the one thing this contract will not take.
|
|
1699
1881
|
action: {
|
|
1700
1882
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
1883
|
+
execution: {
|
|
1884
|
+
kind: "external",
|
|
1885
|
+
reason: "marcar la casilla reescribe el plan-doc, y este motor no lo edita",
|
|
1886
|
+
},
|
|
1701
1887
|
evidence: ["plan.casillas-marcadas"],
|
|
1702
1888
|
idempotent: true,
|
|
1703
1889
|
recovery: "marcá la casilla de la tarea cuyo trabajo local terminó y volvé a devolver la lectura del tablero; marcar de nuevo lo ya marcado no rompe nada",
|
|
@@ -1719,6 +1905,10 @@ export const FLOW_DECISIONS = [
|
|
|
1719
1905
|
// when a state and its boxes disagree.
|
|
1720
1906
|
action: {
|
|
1721
1907
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
1908
|
+
execution: {
|
|
1909
|
+
kind: "external",
|
|
1910
|
+
reason: "escribir el '> Estado:' de la fase reescribe el plan-doc, y este motor no lo edita",
|
|
1911
|
+
},
|
|
1722
1912
|
evidence: ["plan.estado-de-fase-aplicado"],
|
|
1723
1913
|
idempotent: true,
|
|
1724
1914
|
recovery: "escribí el '> Estado:' que la fase realmente tiene —con su '> Bloqueo:' si quedó bloqueada— y volvé a devolver la lectura; una fase sin su prueba corrida no pasa a validada",
|
|
@@ -1745,6 +1935,10 @@ export const FLOW_DECISIONS = [
|
|
|
1745
1935
|
target: SESSION_TARGET,
|
|
1746
1936
|
input: null,
|
|
1747
1937
|
},
|
|
1938
|
+
execution: {
|
|
1939
|
+
kind: "external",
|
|
1940
|
+
reason: "correr las pruebas de fase es ejecutar código, nunca una operación interna",
|
|
1941
|
+
},
|
|
1748
1942
|
evidence: ["plan.validaciones-de-fase-verdes"],
|
|
1749
1943
|
idempotent: true,
|
|
1750
1944
|
recovery: "arreglá lo que la validación reprobó y volvé a correr las pruebas afectadas: la transición sigue pendiente hasta que su salida real vuelva en verde",
|
|
@@ -1787,6 +1981,10 @@ export const FLOW_DECISIONS = [
|
|
|
1787
1981
|
// so it is read, not asserted.
|
|
1788
1982
|
action: {
|
|
1789
1983
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
1984
|
+
execution: {
|
|
1985
|
+
kind: "external",
|
|
1986
|
+
reason: "la validación final es el gate de convergencia del recorrido: darlo por verde desde una lectura sería aprobarlo sin correrlo",
|
|
1987
|
+
},
|
|
1790
1988
|
evidence: ["plan.validacion-final-verde"],
|
|
1791
1989
|
idempotent: true,
|
|
1792
1990
|
recovery: "un chequeo diferido nunca cuenta como aprobado: deja su fase bloqueada y el plan abierto, así que corré lo que falte y volvé a leer el tablero",
|
|
@@ -1845,6 +2043,10 @@ export const FLOW_DECISIONS = [
|
|
|
1845
2043
|
},
|
|
1846
2044
|
action: {
|
|
1847
2045
|
invocation: { program: "aw", args: ["status", "--json"], target: ".", input: null },
|
|
2046
|
+
execution: {
|
|
2047
|
+
kind: "external",
|
|
2048
|
+
reason: "sellar el done reescribe el plan-doc, y este motor no lo edita",
|
|
2049
|
+
},
|
|
1848
2050
|
evidence: ["plan.estado-done-sellado"],
|
|
1849
2051
|
idempotent: true,
|
|
1850
2052
|
recovery: "escribí '> Estado: done' y su '> Cierre:' en la línea de abajo y volvé a devolver la lectura; si el tablero no lo lee cerrado, la transición sigue pendiente",
|
|
@@ -1873,6 +2075,10 @@ export const FLOW_DECISIONS = [
|
|
|
1873
2075
|
// clean or explicitly acknowledged").
|
|
1874
2076
|
action: {
|
|
1875
2077
|
invocation: { program: "aw", args: ["sources", "--verbose"], target: ".", input: null },
|
|
2078
|
+
execution: {
|
|
2079
|
+
kind: "external",
|
|
2080
|
+
reason: "crear un commit es un efecto sobre git que este ejecutor no aplica",
|
|
2081
|
+
},
|
|
1876
2082
|
evidence: ["plan.commits-por-fuente"],
|
|
1877
2083
|
idempotent: false,
|
|
1878
2084
|
recovery: "una fuente que quedó con cambios sin commitear deja el batch SIN commitear: registralo así en CHECKPOINT y BACKLOG en vez de commitear a medias",
|