@tacuchi/agent-workflow-cli 25.1.2 → 25.3.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/README.md +3 -1
- package/dist/adapters/node-process.js +35 -0
- package/dist/adapters/node-process.js.map +1 -1
- package/dist/application/amend-service.js +393 -0
- package/dist/application/amend-service.js.map +1 -0
- package/dist/application/decision-note-service.js +20 -3
- package/dist/application/decision-note-service.js.map +1 -1
- package/dist/application/doctor/actions.js +158 -0
- package/dist/application/doctor/actions.js.map +1 -0
- package/dist/application/doctor/apply.js +399 -0
- package/dist/application/doctor/apply.js.map +1 -0
- package/dist/application/doctor/auth-dsn.js +143 -0
- package/dist/application/doctor/auth-dsn.js.map +1 -0
- package/dist/application/doctor/auth-flow.js +28 -0
- package/dist/application/doctor/auth-flow.js.map +1 -0
- package/dist/application/doctor/auth-registry.js +12 -0
- package/dist/application/doctor/auth-registry.js.map +1 -0
- package/dist/application/doctor/hosts.js +41 -0
- package/dist/application/doctor/hosts.js.map +1 -0
- package/dist/application/doctor/native-host-state.js +211 -0
- package/dist/application/doctor/native-host-state.js.map +1 -0
- package/dist/application/doctor/prepare.js +262 -0
- package/dist/application/doctor/prepare.js.map +1 -0
- package/dist/application/doctor/provider-installation.js +124 -0
- package/dist/application/doctor/provider-installation.js.map +1 -0
- package/dist/application/doctor/provider-mcps.js +650 -0
- package/dist/application/doctor/provider-mcps.js.map +1 -0
- package/dist/application/doctor/provider-plugins-hooks.js +112 -0
- package/dist/application/doctor/provider-plugins-hooks.js.map +1 -0
- package/dist/application/doctor/provider-skills.js +212 -0
- package/dist/application/doctor/provider-skills.js.map +1 -0
- package/dist/application/doctor/provider-tools-auth.js +201 -0
- package/dist/application/doctor/provider-tools-auth.js.map +1 -0
- package/dist/application/doctor/provider-visibility.js +149 -0
- package/dist/application/doctor/provider-visibility.js.map +1 -0
- package/dist/application/doctor/repair-runner.js +169 -0
- package/dist/application/doctor/repair-runner.js.map +1 -0
- package/dist/application/doctor/report.js +155 -0
- package/dist/application/doctor/report.js.map +1 -0
- package/dist/application/doctor/types.js +5 -0
- package/dist/application/doctor/types.js.map +1 -0
- package/dist/application/flow/advance.js +152 -13
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/flow-service.js +18 -7
- package/dist/application/flow/flow-service.js.map +1 -1
- package/dist/application/flow/internal-actions.js +167 -7
- package/dist/application/flow/internal-actions.js.map +1 -1
- package/dist/application/flow/run-projection.js +6 -1
- package/dist/application/flow/run-projection.js.map +1 -1
- package/dist/application/flow/submit.js +330 -7
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/mcp-doctor-service.js +1 -1
- package/dist/application/mcp-doctor-service.js.map +1 -1
- package/dist/application/mcp-host-reader.js +134 -26
- package/dist/application/mcp-host-reader.js.map +1 -1
- package/dist/application/mcp-host-receipt-service.js +9 -7
- package/dist/application/mcp-host-receipt-service.js.map +1 -1
- package/dist/application/plan-current-point.js +54 -0
- package/dist/application/plan-current-point.js.map +1 -0
- package/dist/application/plan-exec-decision-service.js +143 -4
- package/dist/application/plan-exec-decision-service.js.map +1 -1
- package/dist/application/plan-locator.js +78 -0
- package/dist/application/plan-locator.js.map +1 -0
- package/dist/application/plan-open-run.js +129 -0
- package/dist/application/plan-open-run.js.map +1 -0
- package/dist/application/reseal-service.js +14 -44
- package/dist/application/reseal-service.js.map +1 -1
- package/dist/application/resume-service.js +9 -3
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/self/install-skill.js +10 -2
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/mcp-config.js +1 -1
- package/dist/application/self/mcp-config.js.map +1 -1
- package/dist/application/session-narrative.js +15 -0
- package/dist/application/session-narrative.js.map +1 -1
- package/dist/application/settle-service.js +442 -0
- package/dist/application/settle-service.js.map +1 -0
- package/dist/application/source-boundary-policy.js +87 -6
- package/dist/application/source-boundary-policy.js.map +1 -1
- package/dist/application/workline-index-service.js +165 -62
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/cli/commands/amend.js +122 -0
- package/dist/cli/commands/amend.js.map +1 -0
- package/dist/cli/commands/doctor.js +300 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/index.js +6 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/settle.js +197 -0
- package/dist/cli/commands/settle.js.map +1 -0
- package/dist/cli/commands/status.js +2 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/dispatch-plan.js +47 -0
- package/dist/cli/dispatch-plan.js.map +1 -0
- package/dist/cli/help-groups.js +15 -0
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/main.js +54 -10
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/parser.js +26 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/domain/decision-note.js +166 -3
- package/dist/domain/decision-note.js.map +1 -1
- package/dist/domain/decision-preview.js.map +1 -1
- package/dist/domain/doctor/auth.js +65 -0
- package/dist/domain/doctor/auth.js.map +1 -0
- package/dist/domain/doctor/model.js +82 -0
- package/dist/domain/doctor/model.js.map +1 -0
- package/dist/domain/doctor/operations.js +114 -0
- package/dist/domain/doctor/operations.js.map +1 -0
- package/dist/domain/effective-contract.js +4 -3
- package/dist/domain/effective-contract.js.map +1 -1
- package/dist/domain/flow/answer.js +10 -0
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +124 -0
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/directive.js +8 -1
- package/dist/domain/flow/directive.js.map +1 -1
- package/dist/domain/flow/run-state.js +276 -34
- package/dist/domain/flow/run-state.js.map +1 -1
- package/dist/domain/obligation-correspondence.js +95 -0
- package/dist/domain/obligation-correspondence.js.map +1 -0
- package/dist/domain/reconciliation.js +142 -25
- package/dist/domain/reconciliation.js.map +1 -1
- package/dist/domain/redaction.js +40 -0
- package/dist/domain/redaction.js.map +1 -1
- package/dist/domain/settlement.js +129 -0
- package/dist/domain/settlement.js.map +1 -0
- package/package.json +1 -1
- package/skills/w/SKILL.md +2 -1
- package/skills/w/commands/README.md +2 -1
- package/skills/w/commands/doctor.md +31 -0
- package/skills/w/commands/resume.md +2 -2
- package/skills/w/context/MANIFEST.json +4 -0
- package/skills/w/loops/plan-exec-loop/LOOP.md +31 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHETHER A LEGACY OBLIGATION IS ACTUALLY A HANDOFF THE PLAN ALREADY DECLARED.
|
|
3
|
+
*
|
|
4
|
+
* A note published before obligations carried a class says only what the work
|
|
5
|
+
* is. Read as compensation — the safe half — it blocks a closure forever when
|
|
6
|
+
* the work was never this lineage's to do. And the plan very often says so
|
|
7
|
+
* already: it enumerates that same step under its operative handoff or its open
|
|
8
|
+
* questions, because whoever wrote the note was copying it from there.
|
|
9
|
+
*
|
|
10
|
+
* So the reading is an IDENTITY test over something the plan enumerates, never a
|
|
11
|
+
* judgement about words. No token list, no vocabulary, no similarity score: a
|
|
12
|
+
* detector of words would silently reclassify compensation as handoff the day
|
|
13
|
+
* somebody phrased it differently, and the failure would be a plan closing over
|
|
14
|
+
* work nobody did. Containment in either direction is what makes the test
|
|
15
|
+
* survive the two edits that actually happen — the note quoting a longer plan
|
|
16
|
+
* item, and the plan item quoting a shorter note — and the minimum length is
|
|
17
|
+
* what stops a common fragment from matching everything.
|
|
18
|
+
*/
|
|
19
|
+
/** Below this, a containment is a coincidence rather than a citation. */
|
|
20
|
+
const MIN_CORRESPONDENCE_CHARS = 24;
|
|
21
|
+
/**
|
|
22
|
+
* The sections of a plan whose items are handoffs by construction.
|
|
23
|
+
*
|
|
24
|
+
* `## Handoff` in any of its spellings (`## Handoff operativo` included) and the
|
|
25
|
+
* open questions: the first is work explicitly handed to somebody else, the
|
|
26
|
+
* second is work explicitly NOT taken on. Nothing else counts — a step named in
|
|
27
|
+
* the tasks is precisely the work the lineage owes.
|
|
28
|
+
*/
|
|
29
|
+
const HANDOFF_SECTION_RE = /^##\s+(handoff\b.*|open questions|preguntas abiertas)\s*$/i;
|
|
30
|
+
const SECTION_RE = /^##\s+/;
|
|
31
|
+
const FENCE_RE = /^\s*(?:```|~~~)/;
|
|
32
|
+
const ITEM_RE = /^\s*(?:[-*+]|\d+[.)])\s+(.*)$/;
|
|
33
|
+
const CHECKBOX_RE = /^\[[ xX]\]\s*/;
|
|
34
|
+
/** Collapse every run of whitespace so a rewrap is not a different sentence. */
|
|
35
|
+
function normalizeForCorrespondence(text) {
|
|
36
|
+
return text.replace(/\s+/gu, " ").trim();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The enumerated items of the plan's handoff and open-question sections.
|
|
40
|
+
*
|
|
41
|
+
* Enumerated and not "every line": prose under those headings is context, and
|
|
42
|
+
* matching against it would make a paragraph that merely mentions the work read
|
|
43
|
+
* as a declaration that somebody else owns it.
|
|
44
|
+
*/
|
|
45
|
+
export function planHandoffItems(planText) {
|
|
46
|
+
const items = [];
|
|
47
|
+
let inside = false;
|
|
48
|
+
let fenced = false;
|
|
49
|
+
for (const line of planText.split(/\r?\n/u)) {
|
|
50
|
+
// A fenced block is quoted text, not structure. Plans quote their own
|
|
51
|
+
// template, so a fence holding `## Handoff operativo` would otherwise open a
|
|
52
|
+
// section that does not exist and let its example lines pass as handoffs.
|
|
53
|
+
if (FENCE_RE.test(line)) {
|
|
54
|
+
fenced = !fenced;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (fenced)
|
|
58
|
+
continue;
|
|
59
|
+
if (SECTION_RE.test(line)) {
|
|
60
|
+
inside = HANDOFF_SECTION_RE.test(line);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!inside)
|
|
64
|
+
continue;
|
|
65
|
+
const item = ITEM_RE.exec(line)?.[1];
|
|
66
|
+
if (item === undefined)
|
|
67
|
+
continue;
|
|
68
|
+
const normalized = normalizeForCorrespondence(item.replace(CHECKBOX_RE, ""));
|
|
69
|
+
if (normalized.length > 0)
|
|
70
|
+
items.push(normalized);
|
|
71
|
+
}
|
|
72
|
+
return items;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The plan item this obligation cites, or `null` when it cites none.
|
|
76
|
+
*
|
|
77
|
+
* Returning the item rather than a boolean is deliberate: a reading that
|
|
78
|
+
* reclassifies work has to be able to say WHICH line of the plan it read, or
|
|
79
|
+
* nobody can check it.
|
|
80
|
+
*/
|
|
81
|
+
export function correspondingPlanItem(text, items) {
|
|
82
|
+
const needle = normalizeForCorrespondence(text);
|
|
83
|
+
if (needle.length === 0)
|
|
84
|
+
return null;
|
|
85
|
+
for (const item of items) {
|
|
86
|
+
const shorter = needle.length <= item.length ? needle : item;
|
|
87
|
+
const longer = needle.length <= item.length ? item : needle;
|
|
88
|
+
if (shorter.length < MIN_CORRESPONDENCE_CHARS)
|
|
89
|
+
continue;
|
|
90
|
+
if (longer.includes(shorter))
|
|
91
|
+
return item;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=obligation-correspondence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obligation-correspondence.js","sourceRoot":"","sources":["../../src/domain/obligation-correspondence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,yEAAyE;AACzE,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAG,4DAA4D,CAAC;AACxF,MAAM,UAAU,GAAG,QAAQ,CAAC;AAC5B,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AACnC,MAAM,OAAO,GAAG,+BAA+B,CAAC;AAChD,MAAM,WAAW,GAAG,eAAe,CAAC;AAEpC,gFAAgF;AAChF,SAAS,0BAA0B,CAAC,IAAY;IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,sEAAsE;QACtE,6EAA6E;QAC7E,0EAA0E;QAC1E,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC,MAAM,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,MAAM;YAAE,SAAS;QACrB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,MAAM,UAAU,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,KAAwB;IAC1E,MAAM,MAAM,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,IAAI,OAAO,CAAC,MAAM,GAAG,wBAAwB;YAAE,SAAS;QACxD,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { correspondingPlanItem, planHandoffItems } from "./obligation-correspondence.js";
|
|
1
2
|
/**
|
|
2
3
|
* Project what the composed contract still owes.
|
|
3
4
|
*
|
|
@@ -5,46 +6,162 @@
|
|
|
5
6
|
* is the one place that already decided which notes are in force. Walking the
|
|
6
7
|
* chain again here would be a second answer to that question.
|
|
7
8
|
*/
|
|
8
|
-
export function reconciliationOf(contract, chain) {
|
|
9
|
+
export function reconciliationOf(contract, chain, planText) {
|
|
9
10
|
const resumeOf = new Map(chain.map((note) => [note.id, note.resume_point]));
|
|
11
|
+
// Read once for the whole reconciliation: every legacy obligation of one plan
|
|
12
|
+
// is judged against one reading of that plan's own enumerated handoffs.
|
|
13
|
+
const items = planText === undefined ? [] : planHandoffItems(planText);
|
|
10
14
|
const pending = [];
|
|
15
|
+
const handoffs = [];
|
|
11
16
|
for (const obligation of contract.obligations) {
|
|
12
17
|
const resume = resumeOf.get(obligation.by);
|
|
13
18
|
// An obligation whose note is not in the chain handed over cannot say where
|
|
14
19
|
// to resume, and inventing a point would send the run somewhere nobody
|
|
15
20
|
// decided. It stays pending — which is the safe half — and names its note.
|
|
16
|
-
|
|
21
|
+
const cited = obligation.declared ? null : correspondingPlanItem(obligation.text, items);
|
|
22
|
+
const entry = {
|
|
17
23
|
text: obligation.text,
|
|
18
24
|
by: obligation.by,
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
index: obligation.index,
|
|
26
|
+
declared_point: resume ?? `${obligation.by} (nota ausente de la cadena)`,
|
|
27
|
+
// A declared class is the note's own word and is never second-guessed. An
|
|
28
|
+
// undeclared one reads as a handoff only when the plan itself enumerates
|
|
29
|
+
// that exact work; anything else keeps the safe reading.
|
|
30
|
+
kind: obligation.declared ? obligation.kind : cited === null ? "compensation" : "handoff",
|
|
31
|
+
legacy: !obligation.declared,
|
|
32
|
+
...(cited === null ? {} : { corresponds_to: cited }),
|
|
33
|
+
};
|
|
34
|
+
(entry.kind === "handoff" ? handoffs : pending).push(entry);
|
|
21
35
|
}
|
|
36
|
+
return { pending, handoffs, closable: pending.length === 0 };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* WHAT A PLAN OWES AND HOW SOMEBODY GETS OUT OF IT — said once, for everybody.
|
|
40
|
+
*
|
|
41
|
+
* Three surfaces used to describe this one situation in three sets of words: the
|
|
42
|
+
* refusal that would not let the plan be sealed, the board's headline, and the
|
|
43
|
+
* action under the pipeline row. They drifted, as three texts about one fact
|
|
44
|
+
* always do — and the drift was not cosmetic. One of them sent the reader back
|
|
45
|
+
* to the point a note recorded at birth, one offered no command at all, and none
|
|
46
|
+
* of them mentioned the command that actually settles anything. So the exit is
|
|
47
|
+
* derived HERE, and each surface takes the part it renders.
|
|
48
|
+
*
|
|
49
|
+
* `null` means nothing is owed. Otherwise there is always a `command`: a refusal
|
|
50
|
+
* with no exit is a wall, and this whole phase exists because the board had one.
|
|
51
|
+
*/
|
|
52
|
+
export function obligationExit(reconciliation, context) {
|
|
53
|
+
const owed = whatIsOwed(reconciliation);
|
|
54
|
+
if (owed === null)
|
|
55
|
+
return null;
|
|
56
|
+
if (owed.repair !== undefined)
|
|
57
|
+
return unreadableExit(owed.text, owed.repair, context);
|
|
58
|
+
return owed.kind === "compensation"
|
|
59
|
+
? compensationExit(owed.text, context)
|
|
60
|
+
: handoffExit(owed.text, context);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The first thing owed, and of which class — compensation before handoff.
|
|
64
|
+
*
|
|
65
|
+
* A plan owing both is held by the compensation, so that is what its exit has to
|
|
66
|
+
* be about; the handoff is still listed underneath. And "not closable with
|
|
67
|
+
* nothing named" is the composition refusing itself — reported as the shape it
|
|
68
|
+
* is, because falling through to the handoffs there would describe a plan that
|
|
69
|
+
* cannot be read as one that merely delegated some work.
|
|
70
|
+
*/
|
|
71
|
+
function whatIsOwed(reconciliation) {
|
|
72
|
+
const [compensation] = reconciliation.pending;
|
|
73
|
+
if (compensation !== undefined) {
|
|
74
|
+
return {
|
|
75
|
+
kind: "compensation",
|
|
76
|
+
text: named(compensation, reconciliation.pending.length),
|
|
77
|
+
...(compensation.repair === undefined ? {} : { repair: compensation.repair }),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (!reconciliation.closable) {
|
|
81
|
+
return { kind: "compensation", text: "el contrato efectivo no se puede componer" };
|
|
82
|
+
}
|
|
83
|
+
const [handoff] = reconciliation.handoffs;
|
|
84
|
+
if (handoff === undefined)
|
|
85
|
+
return null;
|
|
86
|
+
return { kind: "handoff", text: named(handoff, reconciliation.handoffs.length) };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* How a surface says that a class is a READING, not the note's own word.
|
|
90
|
+
*
|
|
91
|
+
* One phrase for every surface that shows it, because two spellings of it is
|
|
92
|
+
* two answers to "did a person ratify this?" — and that question is the whole
|
|
93
|
+
* point of keeping the distinction.
|
|
94
|
+
*/
|
|
95
|
+
export function readingMark(kind) {
|
|
96
|
+
return `clase no declarada, leída ${kind === "handoff" ? "traspaso" : "compensación"}`;
|
|
97
|
+
}
|
|
98
|
+
/** `DEC-001 — revalidar F1 (+2 más)`: the cause, the work, and the rest of them. */
|
|
99
|
+
function named(obligation, total) {
|
|
100
|
+
const more = total - 1;
|
|
101
|
+
const rest = more > 0 ? ` (+${more} más)` : "";
|
|
102
|
+
// A fabricated pending has no cause to keep: its `by` is a label the
|
|
103
|
+
// projection invented for a note nobody wrote, and printing it as the author
|
|
104
|
+
// of the work would be the second wrong text about the same fact.
|
|
105
|
+
const cause = obligation.repair === undefined ? `${obligation.by} — ` : "";
|
|
106
|
+
// And an undeclared class travels as what it is. The non-blocking reading is
|
|
107
|
+
// the one most worth flagging: a legacy handoff makes the plan closable, and a
|
|
108
|
+
// board asserting it as the note's own word hides that nobody ratified it.
|
|
109
|
+
const read = obligation.legacy ? ` (${readingMark(obligation.kind)})` : "";
|
|
110
|
+
return `${cause}${obligation.text}${read}${rest}`;
|
|
111
|
+
}
|
|
112
|
+
function compensationExit(owed, context) {
|
|
113
|
+
const settle = `aw settle prepare ${context.plan}`;
|
|
114
|
+
const run = context.run;
|
|
22
115
|
return {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
116
|
+
kind: "compensation",
|
|
117
|
+
owed,
|
|
118
|
+
point: context.current_point,
|
|
119
|
+
command: run === null ? settle : run.command,
|
|
120
|
+
// With a run open the settlement rows are inside it, and the hedge is not
|
|
121
|
+
// padding: the cursor only ever grows, so a run already past them cannot go
|
|
122
|
+
// back — and for that one the exit is the command, once its journey ends.
|
|
123
|
+
action: run === null
|
|
124
|
+
? `no hay corrida abierta sobre '${context.plan}': leé y declará el saldo con '${settle}', y aplicalo con el digest que devuelve`
|
|
125
|
+
: `la sesión ${run.session} ${run.why}, y la frontera de saldo de una corrida es donde se declara la evidencia: si todavía no la pasó, seguila con '${run.command}'; si ya la pasó, la salida es '${settle}' cuando el recorrido termine`,
|
|
126
|
+
headline: `COMPENSACIÓN VIGENTE por ${owed}: retomá en ${context.current_point}, ni ejecutable ni cerrable tal cual`,
|
|
26
127
|
};
|
|
27
128
|
}
|
|
28
129
|
/**
|
|
29
|
-
*
|
|
130
|
+
* The exit of a lineage nobody can read — the repair, and nothing about phases.
|
|
30
131
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
132
|
+
* `point` carries the plan's current point anyway, because a caller may still
|
|
133
|
+
* want to say where the plan stands; what changes is that no TEXT offers it,
|
|
134
|
+
* since a broken chain is not fixed by going back to a phase. The old board
|
|
135
|
+
* printed `retomá en <repair>` — the right instruction under the wrong label —
|
|
136
|
+
* and F4's rule that a declared point never reaches a surface would have dropped
|
|
137
|
+
* it altogether: the one actionable sentence in the whole situation.
|
|
35
138
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
139
|
+
function unreadableExit(owed, repair, context) {
|
|
140
|
+
const settle = `aw settle prepare ${context.plan}`;
|
|
141
|
+
const run = context.run;
|
|
142
|
+
return {
|
|
143
|
+
kind: "compensation",
|
|
144
|
+
owed,
|
|
145
|
+
point: context.current_point,
|
|
146
|
+
command: run === null ? settle : run.command,
|
|
147
|
+
action: `${repair}. Después de eso el linaje vuelve a leerse${run === null
|
|
148
|
+
? `, y la salida es '${settle}'`
|
|
149
|
+
: `, y la sesión ${run.session} —que ${run.why}— sigue con '${run.command}'`}`,
|
|
150
|
+
headline: `LINAJE ILEGIBLE por ${owed} — ${repair}: ni ejecutable ni cerrable tal cual`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function handoffExit(owed, context) {
|
|
154
|
+
const settle = `aw settle prepare ${context.plan}`;
|
|
155
|
+
const run = context.run;
|
|
156
|
+
return {
|
|
157
|
+
kind: "handoff",
|
|
158
|
+
owed,
|
|
159
|
+
point: context.current_point,
|
|
160
|
+
command: run === null ? settle : run.command,
|
|
161
|
+
action: run === null
|
|
162
|
+
? `el traspaso no bloquea nada: reconocelo con '${settle}', y saldalo ahí mismo cuando el trabajo de afuera esté hecho`
|
|
163
|
+
: `el traspaso no bloquea nada: la sesión ${run.session} ${run.why}, así que lo ve en la frontera de saldo de esa corrida; fuera de una corrida se reconoce con '${settle}'`,
|
|
164
|
+
headline: `TRASPASO VIGENTE por ${owed}: es trabajo de afuera y no bloquea el cierre; el plan está en ${context.current_point}`,
|
|
165
|
+
};
|
|
49
166
|
}
|
|
50
167
|
//# sourceMappingURL=reconciliation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciliation.js","sourceRoot":"","sources":["../../src/domain/reconciliation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reconciliation.js","sourceRoot":"","sources":["../../src/domain/reconciliation.ts"],"names":[],"mappings":"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"}
|
package/dist/domain/redaction.js
CHANGED
|
@@ -20,6 +20,46 @@ export function isSensitiveKey(key) {
|
|
|
20
20
|
.toLowerCase();
|
|
21
21
|
return SENSITIVE_KEY.test(normalized);
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Whether one string carries credential-shaped material.
|
|
25
|
+
*
|
|
26
|
+
* The boolean core of the MCP receipt's `assertSecretFree`, lifted here because
|
|
27
|
+
* a second caller appeared — the custody gate over a declared authentication
|
|
28
|
+
* flow's `argv` — and two copies of this expression is how one surface starts
|
|
29
|
+
* accepting what the other rejects. The extra pattern beside the redactor's own
|
|
30
|
+
* is deliberate: `redactSensitiveText` only rewrites an assignment when it can
|
|
31
|
+
* see a VALUE after it, and a bare `--token=` with nothing behind it is still a
|
|
32
|
+
* request for a credential.
|
|
33
|
+
*/
|
|
34
|
+
export function carriesSecretMaterial(value) {
|
|
35
|
+
return (redactSensitiveText(value) !== value ||
|
|
36
|
+
/(?:^|[?&;\s-])(?:password|passwd|secret|token|api[-_]?key|dsn|pgpassword|pgpassfile)\s*=/i.test(value));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether one argument is a flag ASKING for a credential, value or not.
|
|
40
|
+
*
|
|
41
|
+
* Two expressions, and the union is the point: neither list alone is the answer.
|
|
42
|
+
* The literal one catches the spellings written without a separator (`--apikey`),
|
|
43
|
+
* which the normalized key list cannot see; `isSensitiveKey` catches the compound
|
|
44
|
+
* names (`--access-token`, `--client-secret`, `--credentials`, `--private-key`,
|
|
45
|
+
* `--connection-string`) that the literal list missed — and those were being let
|
|
46
|
+
* through by the custody gate, which is the whole reason this is not one list any
|
|
47
|
+
* more. Deriving the second half from `SENSITIVE_KEY` also means a name added
|
|
48
|
+
* there is a name blocked here, instead of a third list to keep in sync.
|
|
49
|
+
*
|
|
50
|
+
* What no name list can cover is a flag that does not say what it carries
|
|
51
|
+
* (`--pat`, `-t`). Those still pass, and the caller's docblock says so rather
|
|
52
|
+
* than implying this predicate is a complete defense.
|
|
53
|
+
*/
|
|
54
|
+
export function isSecretFlag(value) {
|
|
55
|
+
if (/^--?(?:token|secret|password|passwd|pwd|api[-_]?key|key|auth|dsn|database[-_]?url|pgpassword|pgpassfile)(?:=|$)/i.test(value)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (!value.startsWith("-"))
|
|
59
|
+
return false;
|
|
60
|
+
const name = value.replace(/^-+/, "").split("=")[0] ?? "";
|
|
61
|
+
return name.length > 0 && isSensitiveKey(name);
|
|
62
|
+
}
|
|
23
63
|
/** Safe predicate for configuration shapes that must never reflect credentials. */
|
|
24
64
|
export function containsSensitiveData(value) {
|
|
25
65
|
if (typeof value === "string")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redaction.js","sourceRoot":"","sources":["../../src/domain/redaction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,cAAc,GAAG,kEAAkE,CAAC;AAC1F,MAAM,iBAAiB,GACrB,2SAA2S,CAAC;AAC9S,MAAM,aAAa,GACjB,4QAA4Q,CAAC;AAE/Q,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI;SACR,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC;SAChC,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,UAAU,GAAG,GAAG;SACnB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;IACjB,OAAO,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,mBAAmB,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;IAC3E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAC/B,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,qBAAqB,CAAC,MAAM,CAAC,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACjE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;YAC3C,GAAG;YACH,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC;SAC3D,CAAC,CACH,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
1
|
+
{"version":3,"file":"redaction.js","sourceRoot":"","sources":["../../src/domain/redaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The successor of one carrier note, or `null` when it would change nothing.
|
|
3
|
+
*
|
|
4
|
+
* Everything but the settled obligations crosses over: the decision, its reason,
|
|
5
|
+
* the assertions it amends, its scope, its consumers and its evidence. What the
|
|
6
|
+
* settlement adds is the evidence each discharge produced — evidence that still
|
|
7
|
+
* counts is exactly what `evidence_preserved` is for — and what it removes is
|
|
8
|
+
* the obligations somebody actually did.
|
|
9
|
+
*
|
|
10
|
+
* `null` and not an empty note: publishing a successor identical in force to its
|
|
11
|
+
* predecessor would grow the chain by one record per attempt and say nothing.
|
|
12
|
+
*/
|
|
13
|
+
export function deriveSettlementNote(carrier, settlements, at) {
|
|
14
|
+
const mine = settlements.filter((settlement) => settlement.note === carrier.id);
|
|
15
|
+
const failures = checkSettlements(carrier, mine);
|
|
16
|
+
if (failures.length > 0)
|
|
17
|
+
return { ok: false, failures };
|
|
18
|
+
const byIndex = new Map(mine.map((settlement) => [settlement.index, settlement]));
|
|
19
|
+
const kept = [];
|
|
20
|
+
const classified = [];
|
|
21
|
+
const settled = [];
|
|
22
|
+
const evidence = [];
|
|
23
|
+
for (const [index, obligation] of carrier.obligations.entries()) {
|
|
24
|
+
const settlement = byIndex.get(index);
|
|
25
|
+
if (settlement !== undefined && settlement.outcome === "settled") {
|
|
26
|
+
settled.push(obligation.text);
|
|
27
|
+
if (settlement.evidence !== undefined)
|
|
28
|
+
evidence.push(settlement.evidence);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const held = settlement?.outcome === "handoff" ? reclassified(obligation, "handoff") : obligation;
|
|
32
|
+
kept.push(held);
|
|
33
|
+
// Anything still unclassed leaves carrying the reading the board already
|
|
34
|
+
// reported FOR THAT POSITION — that is what "clasifica lo que queda" means,
|
|
35
|
+
// and without it the successor could not be appended at all. The position is
|
|
36
|
+
// the carrier's, never the survivors': dropping one shifts the rest.
|
|
37
|
+
classified.push(held.declared ? held : reclassified(held, at.resolved.get(index) ?? held.kind));
|
|
38
|
+
}
|
|
39
|
+
if (settled.length === 0 && sameObligations(carrier.obligations, classified)) {
|
|
40
|
+
return { ok: true, draft: null, settled: [] };
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
ok: true,
|
|
44
|
+
settled,
|
|
45
|
+
draft: {
|
|
46
|
+
schema: carrier.schema,
|
|
47
|
+
lineage: {
|
|
48
|
+
spec: carrier.lineage.spec,
|
|
49
|
+
plan: carrier.lineage.plan,
|
|
50
|
+
// The settling run when there is one; the carrier's own when `aw settle`
|
|
51
|
+
// acts on a plan whose run is long closed. Either way it is a real
|
|
52
|
+
// session and a real phase, never a placeholder.
|
|
53
|
+
execution: { session: at.session, phase: at.phase },
|
|
54
|
+
},
|
|
55
|
+
decision: carrier.decision,
|
|
56
|
+
reason: carrier.reason,
|
|
57
|
+
supersedes_assertions: [...carrier.supersedes_assertions],
|
|
58
|
+
supersedes_note: carrier.id,
|
|
59
|
+
scope: carrier.scope,
|
|
60
|
+
consumers: [...carrier.consumers],
|
|
61
|
+
evidence_preserved: [...carrier.evidence_preserved, ...evidence],
|
|
62
|
+
evidence_invalidated: [...carrier.evidence_invalidated],
|
|
63
|
+
obligations: classified,
|
|
64
|
+
resume_point: carrier.resume_point,
|
|
65
|
+
date: at.date,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function reclassified(obligation, kind) {
|
|
70
|
+
return { text: obligation.text, kind, declared: true };
|
|
71
|
+
}
|
|
72
|
+
function sameObligations(before, after) {
|
|
73
|
+
return (before.length === after.length &&
|
|
74
|
+
before.every((obligation, index) => {
|
|
75
|
+
const other = after[index];
|
|
76
|
+
return (other !== undefined &&
|
|
77
|
+
other.text === obligation.text &&
|
|
78
|
+
other.kind === obligation.kind &&
|
|
79
|
+
other.declared === obligation.declared);
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Every way a settlement can fail to name real work, each with its own code.
|
|
84
|
+
*
|
|
85
|
+
* A settlement that points at an obligation the note does not carry, or that
|
|
86
|
+
* claims work is done without saying what proves it, is not a slightly worse
|
|
87
|
+
* settlement: it is a discharge nobody can audit, and the chain would record it
|
|
88
|
+
* as authoritative.
|
|
89
|
+
*/
|
|
90
|
+
function checkSettlements(carrier, settlements) {
|
|
91
|
+
const failures = [];
|
|
92
|
+
const seen = new Set();
|
|
93
|
+
for (const settlement of settlements) {
|
|
94
|
+
const obligation = carrier.obligations[settlement.index];
|
|
95
|
+
if (obligation === undefined) {
|
|
96
|
+
failures.push({
|
|
97
|
+
code: "SETTLEMENT_OBLIGATION_ABSENT",
|
|
98
|
+
message: `${carrier.id} no tiene una obligación en la posición ${settlement.index}`,
|
|
99
|
+
action: `esa nota carga ${carrier.obligations.length} obligación(es): saldá una que exista`,
|
|
100
|
+
});
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (seen.has(settlement.index)) {
|
|
104
|
+
failures.push({
|
|
105
|
+
code: "SETTLEMENT_OBLIGATION_REPEATED",
|
|
106
|
+
message: `${carrier.id} recibe dos saldos para la misma obligación: ${obligation.text}`,
|
|
107
|
+
action: "una obligación se salda una vez; decidí cuál de las dos lecturas vale",
|
|
108
|
+
});
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
seen.add(settlement.index);
|
|
112
|
+
if (settlement.outcome === "settled" && (settlement.evidence ?? "").trim().length === 0) {
|
|
113
|
+
failures.push({
|
|
114
|
+
code: "SETTLEMENT_EVIDENCE_MISSING",
|
|
115
|
+
message: `se declara cumplida '${obligation.text}' sin decir qué lo prueba`,
|
|
116
|
+
action: "declará la evidencia del saldo: un comando corrido, una prueba o una inspección; sin eso no es un saldo, es una afirmación",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (settlement.outcome !== "settled" && settlement.evidence !== undefined) {
|
|
120
|
+
failures.push({
|
|
121
|
+
code: "SETTLEMENT_EVIDENCE_UNEXPECTED",
|
|
122
|
+
message: `'${obligation.text}' no se declara cumplida y aun así trae evidencia`,
|
|
123
|
+
action: "la evidencia acredita un saldo: sacala, o declará la obligación cumplida",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return failures;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=settlement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlement.js","sourceRoot":"","sources":["../../src/domain/settlement.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tacuchi/agent-workflow-cli",
|
|
3
|
-
"version": "25.
|
|
3
|
+
"version": "25.3.0",
|
|
4
4
|
"description": "Runtime CLI for Workline — the stages + loops + artifacts system for agent work. Bundles the universal `w` skill set under `skills/w/` (slash commands `/w:*`: spec-new/spec-refine, plan-new/plan-exec, quick, persist, workspace-init, export-*); `self install --target <host>` copies SKILL + commands + hooks into the host. Pluggable capability skills resolve through `.workflow/skills.toml`. Namespace auto-detected from any `.<ns>/sessions/` dir in CWD; default `workflow`.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/skills/w/SKILL.md
CHANGED
|
@@ -111,10 +111,11 @@ The flows are **composable with host-native work, never exclusive**. The host is
|
|
|
111
111
|
- `/w:quick` — starts `quick-loop` (shortcut, no `docs/`; escalates live to SPEC when the objective exceeds a quick).
|
|
112
112
|
- `/w:export-scripts` · `/w:export-manuals` · `/w:export-diagrams` · `/w:export-reports` — promote artifacts to `docs/`.
|
|
113
113
|
|
|
114
|
-
### Transversal skills (no flow) — `/w:status` · `/w:fix-git` · `/w:generate-launch` · `/w:persist` · `/w:resume`
|
|
114
|
+
### Transversal skills (no flow) — `/w:status` · `/w:doctor` · `/w:fix-git` · `/w:generate-launch` · `/w:persist` · `/w:resume`
|
|
115
115
|
|
|
116
116
|
**Flow-independent invocable** skills: triggered with `/w:` like any command, but they do **not** belong to SPEC/PLAN/QUICK, do **not** manage `docs/`, and do **not** count in **6 flow commands / 5 loops**. *(In the bundle they are packaged under `commands/` so `/w:` can invoke them; in the design they are the `workflow-skills/` category.)*
|
|
117
117
|
|
|
118
|
+
- `/w:doctor` — read-only diagnosis of the Workline install, MCPs, skills, auth, hooks and workspace visibility across every detected host, with coverage per category and the verdict in the exit code; repairs only what is attributable to Workline, over a sealed batch the person approves by digest. Backed by `aw doctor`.
|
|
118
119
|
- `/w:status` — read-only workspace dashboard (Done/Missing/Discarded, dates humanized in the user's language), opportunistically enriched with host context when the host exposes cheap memory. Writes nothing; backed by `aw status`.
|
|
119
120
|
- `/w:fix-git` — resolves an in-progress merge's conflicts in any repo (identifies origin↔destination, analyzes intent, *structured-choice* on ambiguity). No session, never touches `docs/`; git-safe; backed by `aw merge-state`.
|
|
120
121
|
- `/w:generate-launch` — (re)generates the per-source launch scripts (`.workflow/launch/<alias>/`) by detecting each source's stack; idempotent (preserves hand-edited scripts, `--force` overwrites). Complements the launch flow's on-demand generation. No session, never touches `docs/`; backed by `aw generate-launch`.
|
|
@@ -21,6 +21,7 @@ Every invoked directory is a usable implicit workspace. The closest ancestor wit
|
|
|
21
21
|
| [`plan-refine`](plan-refine.md) | Refines the plan **in place** before executing (aux, optional) | starts `plan-refine-loop` |
|
|
22
22
|
| [`plan-exec`](plan-exec.md) | Executes the plan (code/DB/git) and maintains it as a living doc | starts `plan-exec-loop` |
|
|
23
23
|
| [`quick`](quick.md) | Lightweight shortcut for scoped work; never touches `docs/` | starts `quick-loop` |
|
|
24
|
+
| [`doctor`](doctor.md) | Read-only diagnosis across every host + repair of what Workline owns | single-pass (transversal) |
|
|
24
25
|
| [`status`](status.md) | Read-only workspace dashboard | single-pass (transversal) |
|
|
25
26
|
| [`fix-git`](fix-git.md) | Resolves an in-progress merge, git-safe | single-pass (transversal) |
|
|
26
27
|
| [`generate-launch`](generate-launch.md) | (Re)generates the per-source launch scripts (`.workflow/launch/<alias>/`) | single-pass (transversal) |
|
|
@@ -33,7 +34,7 @@ Every invoked directory is a usable implicit workspace. The closest ancestor wit
|
|
|
33
34
|
|
|
34
35
|
> **Intentional asymmetry:** in SPEC, `spec-new` generates the draft single-pass (no loop) and the loop lives in `spec-refine`; in PLAN, all 3 commands start loops. Total: **6 flow commands / 5 loops**.
|
|
35
36
|
>
|
|
36
|
-
> **Transversal (no flow):** `status`, `fix-git`, `generate-launch`, `persist` and `resume` belong to no SPEC/PLAN/QUICK flow and do not count in 6/5. In the design they are their own category (`workflow-skills/`); here they are packaged under `commands/` so `/w:` can invoke them — see [`../harness/HARNESS.md`](../harness/HARNESS.md) § *Command packaging*.
|
|
37
|
+
> **Transversal (no flow):** `status`, `doctor`, `fix-git`, `generate-launch`, `persist` and `resume` belong to no SPEC/PLAN/QUICK flow and do not count in 6/5. In the design they are their own category (`workflow-skills/`); here they are packaged under `commands/` so `/w:` can invoke them — see [`../harness/HARNESS.md`](../harness/HARNESS.md) § *Command packaging*.
|
|
37
38
|
|
|
38
39
|
## Schema of each command file
|
|
39
40
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use when the user asks if the install, MCPs, skills or auth are healthy across hosts, or to repair what Workline owns.
|
|
3
|
+
argument-hint: "(none) | prepare --select <id>… | apply --approval <digest> --select <id>…"
|
|
4
|
+
allowed-tools:
|
|
5
|
+
[
|
|
6
|
+
"Bash",
|
|
7
|
+
"Read",
|
|
8
|
+
]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# doctor — diagnosis across every host
|
|
12
|
+
|
|
13
|
+
The report is read-only and leaves no trace. `prepare` seals and is logged; `apply` is the only step that writes. No loop, no session.
|
|
14
|
+
|
|
15
|
+
## Run
|
|
16
|
+
|
|
17
|
+
1. `aw doctor --format human` — emits coverage, findings and a verdict for every detected host. **The exit code IS the verdict**, and `ok:true` keeps the report printing even when it blocks. The default pass asks Claude and Codex for their MCPs, which connects them; `--skip-native` declines it and leaves that coverage `omitida`.
|
|
18
|
+
2. **Relay it verbatim** — never paraphrase, re-sort, add or drop a line.
|
|
19
|
+
3. `aw doctor prepare --format human`, with no selection, lists what can be repaired (`automatizable`); the report's `accionable` count also includes manual findings no batch accepts, so take the listing, not the count. **One option per listed finding**, in its order, plus the `flow` slot. Canonical [option shape](../loops/CHASSIS.md#structured-choice-design--batching) and [host binding](../harness/HARNESS.md#harness-binding-matrix); the id is the label, `impacto` + `acción` the sentence.
|
|
20
|
+
4. `aw doctor prepare --select <id> … --format human` seals that batch. Relay its preview and ask for **its digest**: the approval is over what the preview shows.
|
|
21
|
+
5. `aw doctor apply --approval <digest> --select <id> … --format human` applies in order and re-checks each resource. Relay it action by action: that is where a partial batch matters.
|
|
22
|
+
|
|
23
|
+
> **Nothing here is re-derived.** Ownership, effects, order and what the digest covers are the CLI's answers; never call a resource ours. `EVIDENCE_MISSING` names both digests: the state moved, so run `prepare` again.
|
|
24
|
+
|
|
25
|
+
> **`--verify-connection` authorizes leaving the machine** to verify a credential. Without it every deep verification degrades and says so: a present variable never reads as a working one. The CLI never holds a secret: guidance names the variable, not its value.
|
|
26
|
+
|
|
27
|
+
Degradation is declared, never silent: with no structured-choice, list the options as labeled markdown with the `flow` control among them.
|
|
28
|
+
|
|
29
|
+
## More context
|
|
30
|
+
|
|
31
|
+
`aw context-plan --command doctor --signal <s> --root "${CLAUDE_PLUGIN_ROOT}/skills/w"` returns the extra documents a case needs; read exactly what it lists.
|
|
@@ -32,10 +32,10 @@ No target → **every** pending item as `candidates` in the CLI's order, `propos
|
|
|
32
32
|
|
|
33
33
|
## What the CLI decides (do not re-derive)
|
|
34
34
|
|
|
35
|
-
- **Priority**: unrefined spec → refined spec with no plan → plan not `done
|
|
35
|
+
- **Priority**: unrefined spec → refined spec with no plan → plan not `done` → live handoff; started first. A loose session is a notice, never a candidate.
|
|
36
36
|
- **Ties**: equal priority and progress → no single recommendation; date never splits.
|
|
37
37
|
- **Spec→plan link**: `Derived from` or `## Origin`, never the slug; unproven stays unplanned.
|
|
38
|
-
- **The route**: `/w:spec-refine`, `/w:plan-new`, `/w:plan-exec`, `aw session-resume --reopen`.
|
|
38
|
+
- **The route**: `/w:spec-refine`, `/w:plan-new`, `/w:plan-exec`, `aw settle prepare`, `aw session-resume --reopen`.
|
|
39
39
|
|
|
40
40
|
> A plan is not finished because its boxes are ticked: re-entry is the first phase not `validada`, a `bloqueada` phase with its declared reason, or — phases green, plan never closed — the final validation. One declaring `done` over open work comes back as inconsistent. An obligation leaving it neither runnable nor closable is said before its percentage.
|
|
41
41
|
|
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
"quick.db-touched": "the task read from or wrote to a database, so there is a statement to derive into the session script"
|
|
66
66
|
},
|
|
67
67
|
"commands": {
|
|
68
|
+
"doctor": {
|
|
69
|
+
"core": ["commands/doctor.md"],
|
|
70
|
+
"modules": [{ "path": "modules/PLAN-MODE.md", "signal": "plan-mode" }]
|
|
71
|
+
},
|
|
68
72
|
"discard": {
|
|
69
73
|
"core": ["commands/discard.md"],
|
|
70
74
|
"modules": []
|