@tacuchi/agent-workflow-cli 21.7.1 → 21.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/adapters/git-cli.js +217 -0
  2. package/dist/adapters/git-cli.js.map +1 -1
  3. package/dist/application/flow/flow-service.js +7 -0
  4. package/dist/application/flow/flow-service.js.map +1 -1
  5. package/dist/application/flow/internal-actions.js +5 -0
  6. package/dist/application/flow/internal-actions.js.map +1 -1
  7. package/dist/application/flow/submit.js +24 -6
  8. package/dist/application/flow/submit.js.map +1 -1
  9. package/dist/application/history-table.js +37 -0
  10. package/dist/application/history-table.js.map +1 -1
  11. package/dist/application/local-proposal.js +37 -0
  12. package/dist/application/local-proposal.js.map +1 -1
  13. package/dist/application/retirement/apply.js +448 -0
  14. package/dist/application/retirement/apply.js.map +1 -0
  15. package/dist/application/retirement/attribution.js +395 -0
  16. package/dist/application/retirement/attribution.js.map +1 -0
  17. package/dist/application/retirement/graph.js +196 -0
  18. package/dist/application/retirement/graph.js.map +1 -0
  19. package/dist/application/retirement/history-events.js +158 -0
  20. package/dist/application/retirement/history-events.js.map +1 -0
  21. package/dist/application/retirement/journal.js +113 -0
  22. package/dist/application/retirement/journal.js.map +1 -0
  23. package/dist/application/retirement/prepare.js +233 -0
  24. package/dist/application/retirement/prepare.js.map +1 -0
  25. package/dist/application/retirement/preview.js +101 -0
  26. package/dist/application/retirement/preview.js.map +1 -0
  27. package/dist/application/retirement/resolve.js +356 -0
  28. package/dist/application/retirement/resolve.js.map +1 -0
  29. package/dist/application/session-create-service.js +103 -12
  30. package/dist/application/session-create-service.js.map +1 -1
  31. package/dist/application/session-custody-recorder.js +137 -0
  32. package/dist/application/session-custody-recorder.js.map +1 -0
  33. package/dist/application/session-custody-service.js +171 -0
  34. package/dist/application/session-custody-service.js.map +1 -0
  35. package/dist/application/status-service.js +5 -0
  36. package/dist/application/status-service.js.map +1 -1
  37. package/dist/application/workline-index-service.js +31 -0
  38. package/dist/application/workline-index-service.js.map +1 -1
  39. package/dist/application/worktree-service.js +47 -1
  40. package/dist/application/worktree-service.js.map +1 -1
  41. package/dist/cli/commands/checkpoint-write.js +10 -2
  42. package/dist/cli/commands/checkpoint-write.js.map +1 -1
  43. package/dist/cli/commands/index.js +6 -0
  44. package/dist/cli/commands/index.js.map +1 -1
  45. package/dist/cli/commands/retirement.js +137 -0
  46. package/dist/cli/commands/retirement.js.map +1 -0
  47. package/dist/cli/commands/session-create.js +4 -1
  48. package/dist/cli/commands/session-create.js.map +1 -1
  49. package/dist/cli/context-id.js +21 -1
  50. package/dist/cli/context-id.js.map +1 -1
  51. package/dist/cli/help-groups.js +4 -0
  52. package/dist/cli/help-groups.js.map +1 -1
  53. package/dist/cli/render.js +4 -3
  54. package/dist/cli/render.js.map +1 -1
  55. package/dist/domain/flow/authority.js +50 -6
  56. package/dist/domain/flow/authority.js.map +1 -1
  57. package/dist/domain/flow/authorization.js +31 -3
  58. package/dist/domain/flow/authorization.js.map +1 -1
  59. package/dist/domain/retirement/proposal.js +83 -0
  60. package/dist/domain/retirement/proposal.js.map +1 -0
  61. package/dist/domain/retirement/selector.js +109 -0
  62. package/dist/domain/retirement/selector.js.map +1 -0
  63. package/dist/domain/session/custody.js +176 -0
  64. package/dist/domain/session/custody.js.map +1 -0
  65. package/dist/domain/workline-node.js +56 -0
  66. package/dist/domain/workline-node.js.map +1 -0
  67. package/package.json +1 -1
  68. package/skills/w/commands/discard.md +49 -0
  69. package/skills/w/commands/reset.md +50 -0
  70. package/skills/w/context/MANIFEST.json +147 -139
@@ -0,0 +1,176 @@
1
+ /**
2
+ * What a session RECEIVED, what it CREATED and what it CHANGED — sealed, and
3
+ * written before the session can produce a single effect.
4
+ *
5
+ * `SESSION.md`'s `## Origin` was the only record of where a run came from, and it
6
+ * is prose: it can say "derived from the plan 024" and still not answer the two
7
+ * questions a retirement has to answer before deleting anything. Which artifacts
8
+ * existed BEFORE this run, byte for byte? And which of the things that exist now
9
+ * are this run's, as opposed to somebody else's work that happens to sit in the
10
+ * same tree? Neither is derivable from names, dates or tags, and guessing either
11
+ * one wrong destroys work nobody can reconstruct.
12
+ *
13
+ * So custody is the authority and `## Origin` becomes its human projection:
14
+ *
15
+ * - **Born with the session, in the same operation.** A session that exists
16
+ * without custody could already have mutated something by the time anybody
17
+ * thinks to record a baseline, and a baseline taken afterwards is a fiction.
18
+ * - **A baseline is bytes or an explicit absence.** "The file was not there" is a
19
+ * fact a restore needs as much as its previous content; leaving it implicit is
20
+ * what turns a reset into a delete.
21
+ * - **Effects are receipts, never inferences.** A commit's SHAs come back from
22
+ * the commit that made them. Reading ownership off a commit MESSAGE would make
23
+ * the advisor's convention load-bearing, and a message is not evidence.
24
+ * - **Incomplete is a refusal, not a partial answer.** A custody that cannot say
25
+ * what it received blocks the mutation that would promise retirement later,
26
+ * because the alternative is promising a retirement that cannot be delivered.
27
+ *
28
+ * Custody lives INSIDE its session folder and dies with it. A durable record
29
+ * outside would outlive the thing it describes — a parallel history of deleted
30
+ * work, which is precisely the surface `S025/AC-04` says must not exist.
31
+ */
32
+ import { semanticDigest } from "../../application/semantic-operation/protocol.js";
33
+ /** Bumped only when a reader can no longer trust the older shape. */
34
+ export const CUSTODY_VERSION = 1;
35
+ /** Session-local file the record lives in. Dot-prefixed: it is not an artifact. */
36
+ export const CUSTODY_FILE = ".custody.json";
37
+ /** The one way to digest a baseline's bytes, shared with the proposal's bases. */
38
+ export function baselineDigest(text) {
39
+ return semanticDigest(text);
40
+ }
41
+ /** A baseline for a path that was not there. Explicit, never an absent field. */
42
+ export const ABSENT_BASELINE = {
43
+ existed: false,
44
+ digest: null,
45
+ bytes: null,
46
+ content: null,
47
+ };
48
+ /** A baseline that preserves the previous text, for what only we can restore. */
49
+ export function preservedBaseline(content) {
50
+ return {
51
+ existed: true,
52
+ digest: baselineDigest(content),
53
+ bytes: Buffer.byteLength(content, "utf8"),
54
+ content,
55
+ };
56
+ }
57
+ export function sealCustody(input) {
58
+ const body = {
59
+ version: CUSTODY_VERSION,
60
+ subject: input.subject,
61
+ subject_path: input.subjectPath,
62
+ parents: [...(input.parents ?? [])],
63
+ created: input.created,
64
+ artifacts: [...(input.artifacts ?? [])],
65
+ sources: [...(input.sources ?? [])],
66
+ effects: [...(input.effects ?? [])],
67
+ };
68
+ return { ...body, digest: custodyDigest(body) };
69
+ }
70
+ /**
71
+ * The seal, over the SET rather than the order things were appended in.
72
+ *
73
+ * Two custodies that recorded the same facts in a different order are the same
74
+ * custody, and a digest that disagreed would report tampering on a detail nobody
75
+ * can see. Content travels as its own digest so the seal stays a fixed size
76
+ * whatever the preserved bytes weigh.
77
+ */
78
+ export function custodyDigest(body) {
79
+ return semanticDigest({
80
+ version: body.version,
81
+ subject: body.subject,
82
+ subject_path: body.subject_path,
83
+ parents: [...body.parents].sort(nodeOrder),
84
+ created: body.created,
85
+ artifacts: [...body.artifacts]
86
+ .map((a) => ({
87
+ path: a.path,
88
+ role: a.role,
89
+ before: {
90
+ existed: a.before.existed,
91
+ digest: a.before.digest,
92
+ bytes: a.before.bytes,
93
+ content_digest: a.before.content === null ? null : baselineDigest(a.before.content),
94
+ },
95
+ }))
96
+ .sort((a, b) => order(a.path, b.path)),
97
+ sources: [...body.sources].sort((a, b) => order(a.alias, b.alias)),
98
+ effects: [...body.effects],
99
+ });
100
+ }
101
+ function nodeOrder(a, b) {
102
+ return order(`${a.kind}:${a.key}`, `${b.kind}:${b.key}`);
103
+ }
104
+ /** Code-unit ordering, the same reason `canonicalJson` avoids `localeCompare`. */
105
+ function order(a, b) {
106
+ return a < b ? -1 : a > b ? 1 : 0;
107
+ }
108
+ /**
109
+ * Whether this record can still answer "what did the session receive".
110
+ *
111
+ * Called at two very different moments and that is deliberate: before a mutation
112
+ * that promises retirement, and again before a retirement is prepared. The first
113
+ * refuses to make the promise; the second refuses to pretend it was kept. Both
114
+ * read the same rule, so a session that was allowed to mutate is never one whose
115
+ * retirement turns out to be unprovable.
116
+ */
117
+ export function custodyCompleteness(custody) {
118
+ const gaps = [];
119
+ if (custody.version !== CUSTODY_VERSION) {
120
+ gaps.push({
121
+ what: `versión de custodia ${custody.version}`,
122
+ why: `este CLI sella y lee la versión ${CUSTODY_VERSION}`,
123
+ });
124
+ }
125
+ if (custody.digest !== custodyDigest(stripDigest(custody))) {
126
+ gaps.push({
127
+ what: "sello de la custodia",
128
+ why: "el registro no coincide con su digest: fue editado fuera del CLI",
129
+ });
130
+ }
131
+ for (const artifact of custody.artifacts) {
132
+ if (artifact.role !== "input")
133
+ continue;
134
+ if (artifact.before.existed && artifact.before.digest === null) {
135
+ gaps.push({
136
+ what: `baseline de '${artifact.path}'`,
137
+ why: "la entrada existía y no se conservó su estado previo",
138
+ });
139
+ }
140
+ }
141
+ for (const source of custody.sources) {
142
+ if (source.baseline_head === null && source.unit_branch !== null) {
143
+ gaps.push({
144
+ what: `baseline git de '${source.alias}'`,
145
+ why: "la sesión tomó una unidad sobre una fuente cuyo HEAD no se registró",
146
+ });
147
+ }
148
+ }
149
+ return { complete: gaps.length === 0, gaps };
150
+ }
151
+ function stripDigest(custody) {
152
+ const { digest: _digest, ...body } = custody;
153
+ return body;
154
+ }
155
+ /**
156
+ * Every commit this session can prove is its own, per source.
157
+ *
158
+ * Two independent readings, and both are receipts rather than heuristics: the
159
+ * commits a typed commit reported making, and — for a session with its own unit
160
+ * — the range its branch advanced over its recorded baseline. The second is what
161
+ * covers commits the agent made with plain git inside its unit: the branch is
162
+ * the session's by convention and the baseline is sealed, so the range is
163
+ * exclusive by construction and needs nobody's commit message.
164
+ */
165
+ export function attributableCommits(custody, alias) {
166
+ const seen = new Set();
167
+ for (const effect of custody.effects) {
168
+ if (effect.kind !== "commit" && effect.kind !== "unit_integrated")
169
+ continue;
170
+ if (effect.alias !== alias || effect.after === null)
171
+ continue;
172
+ seen.add(effect.after);
173
+ }
174
+ return [...seen];
175
+ }
176
+ //# sourceMappingURL=custody.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custody.js","sourceRoot":"","sources":["../../../src/domain/session/custody.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The identity of a Workline node, said the same way by everybody who points at
3
+ * one.
4
+ *
5
+ * Provenance is a graph over four kinds of thing — a spec, a plan, a quick and a
6
+ * session — and until now each reader spelled them its own way: the index keys
7
+ * plans by `number`, sessions by folder, and a session's `## Origin` names its
8
+ * parent in prose. Prose is exactly what cannot carry an edge: two readings of
9
+ * "derived from the plan 024" can disagree about which document that is, and a
10
+ * retirement that guessed wrong would delete somebody else's work.
11
+ *
12
+ * So a node has ONE canonical id, `<kind>:<key>`, and every edge is a pair of
13
+ * those. The path is carried beside the id rather than inside it because a
14
+ * document can move: identity is `plan:024`, the path is where it lives today,
15
+ * and a stale path is a warning while a wrong id is a defect.
16
+ */
17
+ export const WORKLINE_KINDS = ["spec", "plan", "quick", "session"];
18
+ const KIND_SET = new Set(WORKLINE_KINDS);
19
+ export function isWorklineKind(value) {
20
+ return typeof value === "string" && KIND_SET.has(value);
21
+ }
22
+ /** `plan:024` — the one spelling of a node, in output and in a seal alike. */
23
+ export function formatNodeId(id) {
24
+ return `${id.kind}:${id.key}`;
25
+ }
26
+ const DOC_PATH_RE = /(?:^|\/)docs\/(specs|plans)\/(\d{3})-(spec|plan)(?:-[^/]*)?\.md$/i;
27
+ /**
28
+ * The node a document path IS — `docs/plans/024-plan-x.md` is `plan:024`.
29
+ *
30
+ * This is not inferring provenance from a name: the workspace's own layout fixes
31
+ * that a spec lives at `docs/specs/NNN-spec-*.md`, and the board already reads
32
+ * every spec and plan by exactly this shape. Identity is what the path declares;
33
+ * what the document is DERIVED from is a different question, answered by the
34
+ * document's own `Derived from` line or by a session's sealed custody.
35
+ */
36
+ export function nodeFromDocPath(path) {
37
+ const m = DOC_PATH_RE.exec(path.split("\\").join("/"));
38
+ if (m?.[2] === undefined)
39
+ return null;
40
+ return { kind: m[1]?.toLowerCase() === "specs" ? "spec" : "plan", key: m[2] };
41
+ }
42
+ /**
43
+ * Why an edge is believed.
44
+ *
45
+ * `custody` and `derived-from` are provable: one was sealed by the CLI when the
46
+ * node was born, the other is the plan's own machine-readable `Derived from`
47
+ * line. `origin-prose` is the legacy reading of a free-text `## Origin`, and it
48
+ * is kept SEPARATE precisely so a retirement can refuse to act on it — an edge
49
+ * nobody can prove is the one case where deleting is not recoverable.
50
+ */
51
+ export const EDGE_EVIDENCE = ["custody", "derived-from", "origin-prose"];
52
+ /** Whether an edge is strong enough for a destructive closure to include it. */
53
+ export function isProvable(evidence) {
54
+ return evidence === "custody" || evidence === "derived-from";
55
+ }
56
+ //# sourceMappingURL=workline-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workline-node.js","sourceRoot":"","sources":["../../src/domain/workline-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAa5E,MAAM,QAAQ,GAAwB,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;AAE9D,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,EAAkB;IAC7C,OAAO,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,WAAW,GAAG,mEAAmE,CAAC;AAExF;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAChF,CAAC;AAiBD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,cAAc,EAAE,cAAc,CAAU,CAAC;AAIlF,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,QAAsB;IAC/C,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,cAAc,CAAC;AAC/D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tacuchi/agent-workflow-cli",
3
- "version": "21.7.1",
3
+ "version": "21.9.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 via `.workflow/skills.toml`. Multi-empresa parametrization via `profile.json` cascade. Namespace auto-detected from any `.<ns>/sessions/` dir in CWD; default `workflow`.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,49 @@
1
+ ---
2
+ description: Use to retire a spec, plan, quick or session for good with everything it exclusively owns. `aw discard` resolves the closure from sealed provenance, previews it whole and applies it all-or-nothing on one approval. Never rewrites git history.
3
+ argument-hint: "<spec:NNN | plan:PPP | quick:NNN | session:NNN|carpeta | ruta>"
4
+ allowed-tools: ["Bash", "Read"]
5
+ ---
6
+
7
+ # discard — retire work and everything it exclusively owns
8
+
9
+ No loop, no session — the closure can include the session that would be driving it.
10
+ Output in the **user's language**.
11
+
12
+ **Hard floor:**
13
+
14
+ 1. **`prepare` first, always** — read-only: no session, no journal, no file, no ref,
15
+ so a wrong target costs nothing.
16
+ 2. **You never decide the scope.** It comes from sealed custody and each document's
17
+ `Derived from`; a descendant nobody can prove is a REFUSAL, not a guess.
18
+ 3. **One approval, over the exact digest.** `apply` recomputes under the workspace
19
+ lock and refuses if anything material moved. Approving is not applying.
20
+ 4. **Reverts are commits, never rewrites** — no `reset --hard`, rebase, amend, force
21
+ or push; a published commit's revert leaves its push pending and external.
22
+
23
+ ## Run
24
+
25
+ 1. `aw discard prepare <objetivo> --format human` — what disappears, which local
26
+ change is dropped, which SHA gets a revert, which unit is reconciled, which
27
+ `HISTORY` row it adds, and the **digest**.
28
+ 2. Show that preview and ask approval. If it touches git history, say so: approving
29
+ also authorizes commits.
30
+ 3. `aw discard apply <objetivo> --approval <digest> --format human`.
31
+ 4. A rejection names cause, candidates and next action; **nothing was applied**.
32
+ `024` resolves only while one node answers to it.
33
+
34
+ ## What the CLI decides (do not re-derive)
35
+
36
+ - **The closure**, in removal order; a node something outside also descends from
37
+ blocks the whole operation.
38
+ - **Attribution** of changes and commits, from baselines and receipts — never from a
39
+ message, an author or a tag.
40
+ - **Whether all-or-nothing holds**: two publication units, a conflicting revert, an
41
+ operation in progress or an unsyncable tree block before anything mutates.
42
+ - **What survives**: the originals stay reachable and the only durable Workline trace
43
+ is one append-only `HISTORY` row.
44
+
45
+ ## More context
46
+
47
+ `aw context-plan --command discard --root "${CLAUDE_PLUGIN_ROOT}/skills/w"` lists what to read.
48
+
49
+ - Back to before an **incomplete** session instead: `/w:reset`.
@@ -0,0 +1,50 @@
1
+ ---
2
+ description: Use to undo an incomplete session and put its document back as it was before that session ran. `aw reset` restores the inputs byte for byte and retires the session, all-or-nothing on one approval. Never rewrites git history.
3
+ argument-hint: "<plan:PPP | session:NNN|carpeta | ruta>"
4
+ allowed-tools: ["Bash", "Read"]
5
+ ---
6
+
7
+ # reset — put an incomplete session's inputs back
8
+
9
+ No loop, no session. Output in the **user's language**. It is **not**
10
+ `/w:plan-refine`: refining carries a document forward keeping validated phases, this
11
+ takes it back to the bytes it had before the session started.
12
+
13
+ **Hard floor:**
14
+
15
+ 1. **`prepare` first, always** — read-only, so a wrong target costs nothing.
16
+ 2. **Only an INCOMPLETE session.** One that converged does not become resettable by
17
+ being selected, and `.closed` is never the test: a session closed with work
18
+ pending is exactly this case.
19
+ 3. **The target must resolve to ONE incomplete session**; two is a rejection with its
20
+ candidates, and then you name the session.
21
+ 4. **One approval, over the exact digest.** `apply` recomputes under the lock and
22
+ refuses if the document moved since the preview.
23
+ 5. **Reverts are commits, never rewrites** — no `reset --hard`, rebase, amend, force
24
+ or push, whatever this command's name suggests.
25
+
26
+ ## Run
27
+
28
+ 1. `aw reset prepare <objetivo> --format human` — which session it resolved, which
29
+ paths go back to their previous bytes and whether they moved since the baseline,
30
+ what disappears, which SHA gets a revert, and the **digest**.
31
+ 2. Show that preview and ask approval; if it touches git history, say so.
32
+ 3. `aw reset apply <objetivo> --approval <digest> --format human`.
33
+ 4. A rejection names cause, candidates and next action; **nothing was applied**.
34
+
35
+ ## What the CLI decides (do not re-derive)
36
+
37
+ - **Which session** an artifact resolves to, and whether it is incomplete.
38
+ - **What "before" was**: the baseline sealed at creation. Never reconstructed from
39
+ names, dates or tags — without it, it fails closed.
40
+ - **Inputs vs outputs**: an input returns to its bytes, an output is removed, and a
41
+ document with work of its own blocks instead of being orphaned. A quick with no
42
+ base document is retired whole.
43
+ - **All-or-nothing**: either the scope is intact, or the result is complete, not
44
+ resumable, and leaves one append-only `HISTORY` row.
45
+
46
+ ## More context
47
+
48
+ `aw context-plan --command reset --root "${CLAUDE_PLUGIN_ROOT}/skills/w"` lists what to read.
49
+
50
+ - Deleting a document and everything under it: `/w:discard`.