@tacuchi/agent-workflow-cli 25.6.0 → 25.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.
Files changed (148) hide show
  1. package/CHANGELOG.md +4368 -0
  2. package/README.md +1 -1
  3. package/dist/adapters/git-cli.js +74 -6
  4. package/dist/adapters/git-cli.js.map +1 -1
  5. package/dist/adapters/node-file-system.js +39 -2
  6. package/dist/adapters/node-file-system.js.map +1 -1
  7. package/dist/application/branch-resolver.js +34 -1
  8. package/dist/application/branch-resolver.js.map +1 -1
  9. package/dist/application/checkpoint-write-service.js +161 -39
  10. package/dist/application/checkpoint-write-service.js.map +1 -1
  11. package/dist/application/dates.js +12 -0
  12. package/dist/application/dates.js.map +1 -1
  13. package/dist/application/fix-git-service.js +83 -13
  14. package/dist/application/fix-git-service.js.map +1 -1
  15. package/dist/application/flow/advance.js +24 -3
  16. package/dist/application/flow/advance.js.map +1 -1
  17. package/dist/application/flow/annul-service.js +159 -0
  18. package/dist/application/flow/annul-service.js.map +1 -0
  19. package/dist/application/flow/flow-service.js +212 -49
  20. package/dist/application/flow/flow-service.js.map +1 -1
  21. package/dist/application/flow/internal-actions.js +23 -3
  22. package/dist/application/flow/internal-actions.js.map +1 -1
  23. package/dist/application/flow/internal-drive.js +51 -19
  24. package/dist/application/flow/internal-drive.js.map +1 -1
  25. package/dist/application/flow/run-projection.js +21 -5
  26. package/dist/application/flow/run-projection.js.map +1 -1
  27. package/dist/application/flow/run-state-service.js +108 -35
  28. package/dist/application/flow/run-state-service.js.map +1 -1
  29. package/dist/application/flow/submit.js +63 -144
  30. package/dist/application/flow/submit.js.map +1 -1
  31. package/dist/application/git-flow-service.js +325 -72
  32. package/dist/application/git-flow-service.js.map +1 -1
  33. package/dist/application/hook-sql-mutation-guard.js +155 -27
  34. package/dist/application/hook-sql-mutation-guard.js.map +1 -1
  35. package/dist/application/host-memory/claude-code.js +65 -0
  36. package/dist/application/host-memory/claude-code.js.map +1 -0
  37. package/dist/application/host-memory/codex.js +225 -0
  38. package/dist/application/host-memory/codex.js.map +1 -0
  39. package/dist/application/host-memory/destination.js +52 -0
  40. package/dist/application/host-memory/destination.js.map +1 -0
  41. package/dist/application/host-memory/reader.js +9 -0
  42. package/dist/application/host-memory/reader.js.map +1 -0
  43. package/dist/application/host-memory/report.js +136 -0
  44. package/dist/application/host-memory/report.js.map +1 -0
  45. package/dist/application/lifecycle-target.js +3 -1
  46. package/dist/application/lifecycle-target.js.map +1 -1
  47. package/dist/application/local-proposal.js +13 -3
  48. package/dist/application/local-proposal.js.map +1 -1
  49. package/dist/application/logging/log-events.js +22 -0
  50. package/dist/application/logging/log-events.js.map +1 -1
  51. package/dist/application/parsers/spec-relation.js +20 -7
  52. package/dist/application/parsers/spec-relation.js.map +1 -1
  53. package/dist/application/persist-service.js +45 -1
  54. package/dist/application/persist-service.js.map +1 -1
  55. package/dist/application/plan-exec-batch-service.js +47 -2
  56. package/dist/application/plan-exec-batch-service.js.map +1 -1
  57. package/dist/application/plan-lineage-seal.js +93 -0
  58. package/dist/application/plan-lineage-seal.js.map +1 -0
  59. package/dist/application/plan-lint-service.js +153 -0
  60. package/dist/application/plan-lint-service.js.map +1 -0
  61. package/dist/application/prod-consent.js +75 -0
  62. package/dist/application/prod-consent.js.map +1 -0
  63. package/dist/application/reseal-service.js +9 -3
  64. package/dist/application/reseal-service.js.map +1 -1
  65. package/dist/application/self/install-skill.js +5 -1
  66. package/dist/application/self/install-skill.js.map +1 -1
  67. package/dist/application/self/update-self.js +204 -8
  68. package/dist/application/self/update-self.js.map +1 -1
  69. package/dist/application/session-create-service.js +49 -0
  70. package/dist/application/session-create-service.js.map +1 -1
  71. package/dist/application/session-custody-recorder.js +4 -0
  72. package/dist/application/session-custody-recorder.js.map +1 -1
  73. package/dist/application/session-narrative.js +27 -0
  74. package/dist/application/session-narrative.js.map +1 -1
  75. package/dist/application/session-resolver.js +28 -9
  76. package/dist/application/session-resolver.js.map +1 -1
  77. package/dist/application/source-boundary-policy.js +168 -34
  78. package/dist/application/source-boundary-policy.js.map +1 -1
  79. package/dist/application/working-branch-service.js +68 -0
  80. package/dist/application/working-branch-service.js.map +1 -0
  81. package/dist/application/workline-graph.js +7 -2
  82. package/dist/application/workline-graph.js.map +1 -1
  83. package/dist/cli/commands/checkpoint-write.js +18 -8
  84. package/dist/cli/commands/checkpoint-write.js.map +1 -1
  85. package/dist/cli/commands/fix-git.js +45 -6
  86. package/dist/cli/commands/fix-git.js.map +1 -1
  87. package/dist/cli/commands/flow.js +50 -5
  88. package/dist/cli/commands/flow.js.map +1 -1
  89. package/dist/cli/commands/git-flow.js +103 -29
  90. package/dist/cli/commands/git-flow.js.map +1 -1
  91. package/dist/cli/commands/host-memory.js +33 -0
  92. package/dist/cli/commands/host-memory.js.map +1 -0
  93. package/dist/cli/commands/index.js +6 -0
  94. package/dist/cli/commands/index.js.map +1 -1
  95. package/dist/cli/commands/persist.js +5 -0
  96. package/dist/cli/commands/persist.js.map +1 -1
  97. package/dist/cli/commands/plan.js +50 -0
  98. package/dist/cli/commands/plan.js.map +1 -0
  99. package/dist/cli/commands/resume-summary.js +4 -2
  100. package/dist/cli/commands/resume-summary.js.map +1 -1
  101. package/dist/cli/commands/set-branch.js +40 -6
  102. package/dist/cli/commands/set-branch.js.map +1 -1
  103. package/dist/cli/help-groups.js +6 -0
  104. package/dist/cli/help-groups.js.map +1 -1
  105. package/dist/cli/main.js +6 -2
  106. package/dist/cli/main.js.map +1 -1
  107. package/dist/cli/parser.js +20 -1
  108. package/dist/cli/parser.js.map +1 -1
  109. package/dist/cli/tui/components/git-flow-actions.js +65 -20
  110. package/dist/cli/tui/components/git-flow-actions.js.map +1 -1
  111. package/dist/cli/tui/tabs/project-tab.js +101 -12
  112. package/dist/cli/tui/tabs/project-tab.js.map +1 -1
  113. package/dist/domain/changelog-contract.js +172 -0
  114. package/dist/domain/changelog-contract.js.map +1 -0
  115. package/dist/domain/database-tools.js +1 -189
  116. package/dist/domain/database-tools.js.map +1 -1
  117. package/dist/domain/flow/answer.js +3 -0
  118. package/dist/domain/flow/answer.js.map +1 -1
  119. package/dist/domain/flow/authority.js +12 -0
  120. package/dist/domain/flow/authority.js.map +1 -1
  121. package/dist/domain/flow/journey-baseline.js +131 -0
  122. package/dist/domain/flow/journey-baseline.js.map +1 -0
  123. package/dist/domain/flow/run-state.js +257 -62
  124. package/dist/domain/flow/run-state.js.map +1 -1
  125. package/dist/domain/host-memory/model.js +2 -0
  126. package/dist/domain/host-memory/model.js.map +1 -0
  127. package/dist/domain/host-memory/provenance.js +43 -0
  128. package/dist/domain/host-memory/provenance.js.map +1 -0
  129. package/dist/domain/host-memory/topic.js +26 -0
  130. package/dist/domain/host-memory/topic.js.map +1 -0
  131. package/dist/domain/lineage.js +11 -3
  132. package/dist/domain/lineage.js.map +1 -1
  133. package/dist/domain/proposal.js +7 -0
  134. package/dist/domain/proposal.js.map +1 -1
  135. package/dist/domain/session/custody.js.map +1 -1
  136. package/dist/domain/sql-lexer.js +227 -0
  137. package/dist/domain/sql-lexer.js.map +1 -0
  138. package/package.json +2 -2
  139. package/skills/w/SKILL.md +9 -9
  140. package/skills/w/commands/README.md +2 -1
  141. package/skills/w/commands/recall.md +39 -0
  142. package/skills/w/context/MANIFEST.json +4 -0
  143. package/skills/w/harness/HARNESS.md +9 -5
  144. package/skills/w/hooks/README.md +27 -16
  145. package/skills/w/loops/CHASSIS.md +16 -12
  146. package/skills/w/loops/CODE-POLICIES.md +11 -6
  147. package/skills/w/loops/plan-exec-loop/LOOP.md +9 -9
  148. package/skills/w/modules/COMPACTION.md +1 -1
@@ -0,0 +1,227 @@
1
+ /** PostgreSQL lexical scan shared by the serve-db read-only policy and the sql-mutation-guard hook. */
2
+ export function scanSql(sql) {
3
+ const state = createSqlScanState();
4
+ while (state.index < sql.length) {
5
+ if (!scanSqlCharacter(sql, state))
6
+ return { ok: false };
7
+ }
8
+ flushSqlToken(state);
9
+ closeStatement(state, sql.length);
10
+ return state.blockCommentDepth === 0
11
+ ? {
12
+ ok: true,
13
+ tokens: state.tokens,
14
+ semicolons: state.semicolons,
15
+ contentAfterSemicolon: state.contentAfterSemicolon,
16
+ statements: state.statements,
17
+ }
18
+ : { ok: false };
19
+ }
20
+ function createSqlScanState() {
21
+ return {
22
+ tokens: [],
23
+ index: 0,
24
+ semicolons: 0,
25
+ contentAfterSemicolon: false,
26
+ token: "",
27
+ blockCommentDepth: 0,
28
+ statements: [],
29
+ statement: openStatement(0),
30
+ };
31
+ }
32
+ function openStatement(start) {
33
+ return { start, end: start, tokens: [], marks: [] };
34
+ }
35
+ function closeStatement(state, end) {
36
+ state.statement.end = end;
37
+ state.statements.push(state.statement);
38
+ state.statement = openStatement(end + 1);
39
+ }
40
+ function mark(state, value) {
41
+ if (!state.statement.marks.includes(value))
42
+ state.statement.marks.push(value);
43
+ }
44
+ function scanSqlCharacter(sql, state) {
45
+ if (state.blockCommentDepth > 0) {
46
+ consumeBlockComment(sql, state);
47
+ return true;
48
+ }
49
+ const char = sql[state.index] ?? "";
50
+ const next = sql[state.index + 1] ?? "";
51
+ if (consumeSqlComment(sql, state, char, next))
52
+ return true;
53
+ markContentAfterSemicolon(state, char, next);
54
+ const literal = consumeSqlLiteral(sql, state, char);
55
+ if (literal !== undefined)
56
+ return literal;
57
+ consumePlainSqlCharacter(state, char);
58
+ state.index += 1;
59
+ return true;
60
+ }
61
+ function consumeSqlComment(sql, state, char, next) {
62
+ if (char === "-" && next === "-") {
63
+ consumeLineComment(sql, state);
64
+ return true;
65
+ }
66
+ if (char !== "/" || next !== "*")
67
+ return false;
68
+ flushSqlToken(state);
69
+ openBlockComment(sql, state);
70
+ return true;
71
+ }
72
+ /** MySQL runs the body of a `/*! … *\/` comment as SQL. */
73
+ function openBlockComment(sql, state) {
74
+ if (sql[state.index + 2] === "!")
75
+ mark(state, "executable-comment");
76
+ state.blockCommentDepth += 1;
77
+ state.index += 2;
78
+ }
79
+ /** Returns undefined when the current byte remains regular SQL punctuation. */
80
+ function consumeSqlLiteral(sql, state, char) {
81
+ if (char === "'" || char === '"')
82
+ return consumeQuotedSql(sql, state, char);
83
+ if (char !== "$" || !canOpenDollarQuoted(sql, state))
84
+ return undefined;
85
+ const dollarQuoted = consumeDollarQuotedSql(sql, state);
86
+ if (dollarQuoted === "consumed")
87
+ return true;
88
+ return dollarQuoted === "unterminated" ? false : undefined;
89
+ }
90
+ function consumePlainSqlCharacter(state, char) {
91
+ if (/[A-Za-z0-9_]/.test(char)) {
92
+ state.token += char;
93
+ return;
94
+ }
95
+ flushSqlToken(state);
96
+ if (char === ";") {
97
+ state.semicolons += 1;
98
+ closeStatement(state, state.index);
99
+ }
100
+ else if (char === "(" || char === ")" || char === ",") {
101
+ state.statement.tokens.push(char);
102
+ }
103
+ else if (char === "#") {
104
+ mark(state, "hash");
105
+ }
106
+ else if (char === "`") {
107
+ mark(state, "backtick");
108
+ }
109
+ }
110
+ function consumeBlockComment(sql, state) {
111
+ const char = sql[state.index] ?? "";
112
+ const next = sql[state.index + 1] ?? "";
113
+ if (char === "/" && next === "*") {
114
+ openBlockComment(sql, state);
115
+ return;
116
+ }
117
+ if (char === "*" && next === "/") {
118
+ state.blockCommentDepth -= 1;
119
+ state.index += 2;
120
+ return;
121
+ }
122
+ state.index += 1;
123
+ }
124
+ function consumeLineComment(sql, state) {
125
+ flushSqlToken(state);
126
+ state.index += 2;
127
+ while (state.index < sql.length && sql[state.index] !== "\n" && sql[state.index] !== "\r") {
128
+ state.index += 1;
129
+ }
130
+ }
131
+ function markContentAfterSemicolon(state, char, next) {
132
+ if (state.semicolons === 0 || /\s/.test(char) || char === ";")
133
+ return;
134
+ if ((char === "-" && next === "-") || (char === "/" && next === "*"))
135
+ return;
136
+ state.contentAfterSemicolon = true;
137
+ }
138
+ function consumeQuotedSql(sql, state, quote) {
139
+ // PostgreSQL's ordinary string literals and quoted identifiers escape a
140
+ // quote by doubling it. Backslashes escape only E'...' strings under the
141
+ // default standard_conforming_strings setting, so treating every backslash
142
+ // as an escape could hide a closing quote and a second statement.
143
+ const allowsBackslashEscapes = quote === "'" && state.token.toUpperCase() === "E";
144
+ flushSqlToken(state);
145
+ const next = skipQuoted(sql, state.index, quote, allowsBackslashEscapes);
146
+ if (next < 0)
147
+ return false;
148
+ // MySQL, and PostgreSQL with standard_conforming_strings off, read `\'` as
149
+ // an escaped quote: the literal would end somewhere else.
150
+ if (!allowsBackslashEscapes && sql.slice(state.index, next).includes(`\\${quote}`)) {
151
+ mark(state, "backslash-quote");
152
+ }
153
+ state.index = next;
154
+ return true;
155
+ }
156
+ function consumeDollarQuotedSql(sql, state) {
157
+ const opener = readDollarTag(sql, state.index);
158
+ if (opener === undefined)
159
+ return "not-dollar-quoted";
160
+ flushSqlToken(state);
161
+ // An opener without its own closer is invalid PostgreSQL. Refuse it at the
162
+ // first one rather than resuming at each subsequent `$tag$`; otherwise many
163
+ // distinct unterminated tags make repeated suffix scans quadratic below the
164
+ // 1 MiB input cap.
165
+ const close = sql.indexOf(opener.tag, opener.afterOpen);
166
+ if (close < 0)
167
+ return "unterminated";
168
+ state.index = close + opener.tag.length;
169
+ return "consumed";
170
+ }
171
+ /** PostgreSQL requires a delimiter after an identifier to be whitespace-separated. */
172
+ function canOpenDollarQuoted(sql, state) {
173
+ if (state.token.length > 0)
174
+ return false;
175
+ const previous = state.index === 0 ? undefined : sql[state.index - 1];
176
+ // A quoted identifier is also an identifier even though it was intentionally
177
+ // omitted from `tokens`; without this fence `"name$tag$` could hide the
178
+ // remainder from the single-statement scan.
179
+ return previous === undefined || (previous !== '"' && !isIdentifierContinuation(previous));
180
+ }
181
+ function isIdentifierContinuation(char) {
182
+ return /[A-Za-z0-9_$]/.test(char) || char.charCodeAt(0) >= 0x80;
183
+ }
184
+ function flushSqlToken(state) {
185
+ if (state.token.length === 0)
186
+ return;
187
+ const word = state.token.toUpperCase();
188
+ state.tokens.push(word);
189
+ state.statement.tokens.push(word);
190
+ state.token = "";
191
+ }
192
+ function skipQuoted(sql, start, quote, allowsBackslashEscapes) {
193
+ let index = start + 1;
194
+ while (index < sql.length) {
195
+ if (sql[index] === quote) {
196
+ if (sql[index + 1] === quote) {
197
+ index += 2;
198
+ continue;
199
+ }
200
+ return index + 1;
201
+ }
202
+ if (allowsBackslashEscapes && sql[index] === "\\") {
203
+ index += 2;
204
+ }
205
+ else {
206
+ index += 1;
207
+ }
208
+ }
209
+ return -1;
210
+ }
211
+ function readDollarTag(sql, start) {
212
+ if (sql[start] !== "$")
213
+ return undefined;
214
+ const next = sql[start + 1];
215
+ if (next === "$")
216
+ return { tag: "$$", afterOpen: start + 2 };
217
+ if (next === undefined || !/[A-Za-z_]/.test(next))
218
+ return undefined;
219
+ let end = start + 2;
220
+ while (end < sql.length && /[A-Za-z0-9_]/.test(sql[end] ?? ""))
221
+ end += 1;
222
+ if (sql[end] !== "$")
223
+ return undefined;
224
+ const tag = sql.slice(start, end + 1);
225
+ return { tag, afterOpen: end + 1 };
226
+ }
227
+ //# sourceMappingURL=sql-lexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-lexer.js","sourceRoot":"","sources":["../../src/domain/sql-lexer.ts"],"names":[],"mappings":"AAAA,uGAAuG;AA8BvG,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,OAAO,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IAC1D,CAAC;IACD,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,iBAAiB,KAAK,CAAC;QAClC,CAAC,CAAC;YACE,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;YAClD,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B;QACH,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AACpB,CAAC;AAaD,SAAS,kBAAkB;IACzB,OAAO;QACL,MAAM,EAAE,EAAE;QACV,KAAK,EAAE,CAAC;QACR,UAAU,EAAE,CAAC;QACb,qBAAqB,EAAE,KAAK;QAC5B,KAAK,EAAE,EAAE;QACT,iBAAiB,EAAE,CAAC;QACpB,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACtD,CAAC;AAED,SAAS,cAAc,CAAC,KAAmB,EAAE,GAAW;IACtD,KAAK,CAAC,SAAS,CAAC,GAAG,GAAG,GAAG,CAAC;IAC1B,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,KAAK,CAAC,SAAS,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,IAAI,CAAC,KAAmB,EAAE,KAAqB;IACtD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,KAAmB;IACxD,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QAChC,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,yBAAyB,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC1C,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IACjB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW,EAAE,KAAmB,EAAE,IAAY,EAAE,IAAY;IACrF,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjC,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IAC/C,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2DAA2D;AAC3D,SAAS,gBAAgB,CAAC,GAAW,EAAE,KAAmB;IACxD,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG;QAAE,IAAI,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IACpE,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;IAC7B,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,SAAS,iBAAiB,CAAC,GAAW,EAAE,KAAmB,EAAE,IAAY;IACvE,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5E,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvE,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxD,IAAI,YAAY,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,YAAY,KAAK,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAmB,EAAE,IAAY;IACjE,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC;QACpB,OAAO;IACT,CAAC;IACD,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;QACtB,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACxD,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;SAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtB,CAAC;SAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW,EAAE,KAAmB;IAC3D,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjC,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjC,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;QAC7B,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjB,OAAO;IACT,CAAC;IACD,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW,EAAE,KAAmB;IAC1D,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IACjB,OAAO,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1F,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAmB,EAAE,IAAY,EAAE,IAAY;IAChF,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO;IACtE,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO;IAC7E,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC;AACrC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,KAAmB,EAAE,KAAgB;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,2EAA2E;IAC3E,kEAAkE;IAClE,MAAM,sBAAsB,GAAG,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC;IAClF,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,sBAAsB,CAAC,CAAC;IACzE,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3B,2EAA2E;IAC3E,0DAA0D;IAC1D,IAAI,CAAC,sBAAsB,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC;AAID,SAAS,sBAAsB,CAAC,GAAW,EAAE,KAAmB;IAC9D,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC;IACrD,aAAa,CAAC,KAAK,CAAC,CAAC;IACrB,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,mBAAmB;IACnB,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,cAAc,CAAC;IACrC,KAAK,CAAC,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;IACxC,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,sFAAsF;AACtF,SAAS,mBAAmB,CAAC,GAAW,EAAE,KAAmB;IAC3D,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACtE,6EAA6E;IAC7E,wEAAwE;IACxE,4CAA4C;IAC5C,OAAO,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAClE,CAAC;AAED,SAAS,aAAa,CAAC,KAAmB;IACxC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CACjB,GAAW,EACX,KAAa,EACb,KAAgB,EAChB,sBAA+B;IAE/B,IAAI,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACtB,OAAO,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC;YACzB,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;gBAC7B,KAAK,IAAI,CAAC,CAAC;gBACX,SAAS;YACX,CAAC;YACD,OAAO,KAAK,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,IAAI,sBAAsB,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;YAClD,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,KAAa;IAC/C,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC5B,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC;IAC7D,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACpE,IAAI,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC;IACpB,OAAO,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAAE,GAAG,IAAI,CAAC,CAAC;IACzE,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IACtC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC;AACrC,CAAC"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@tacuchi/agent-workflow-cli",
3
- "version": "25.6.0",
3
+ "version": "25.7.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": {
7
7
  "agent-workflow": "dist/cli/main.js",
8
8
  "aw": "dist/cli/main.js"
9
9
  },
10
- "files": ["dist", "skills", "LICENSE", "README.md"],
10
+ "files": ["dist", "skills", "LICENSE", "README.md", "CHANGELOG.md"],
11
11
  "scripts": {
12
12
  "build": "node scripts/clean-dist.mjs && tsc",
13
13
  "build:watch": "node scripts/clean-dist.mjs && tsc --watch",
package/skills/w/SKILL.md CHANGED
@@ -1,14 +1,13 @@
1
1
  ---
2
2
  name: w
3
3
  description: >-
4
- Orientation skill for Workline (`w` = *workline*), the whole system — built-in
5
- default for the `overview` role. Load this to understand the model end-to-end: the 3-layer
6
- architecture (commands → loops → sessions/artifacts) plus the docs/ zone, the 3
7
- flows (SPEC / PLAN / QUICK), the `/w:` commands, the 5 loops and their chassis, the
8
- `export-*` family, the composable capability skills + `.workflow/skills.toml`
9
- binding cascade, and the 6 hard invariants. Use whenever an agent (or human) needs
10
- to know how the pieces fit, where a deliverable should land, or which command/loop/
11
- skill to reach for.
4
+ Orientation skill for Workline (`w` = *workline*), default for the `overview`
5
+ role. Load it to understand the whole model: the 3 layers (commands → loops →
6
+ sessions/artifacts) plus docs/, the 3 flows (SPEC / PLAN / QUICK), the `/w:`
7
+ commands, the 5 loops and their chassis, the `export-*` family, the capability
8
+ skills + `.workflow/skills.toml` cascade, and the 6 hard invariants. Use it to
9
+ know how the pieces fit, where a deliverable lands, or which command/loop/skill
10
+ to reach for.
12
11
  ---
13
12
 
14
13
  # w — Workline overview
@@ -111,7 +110,7 @@ The flows are **composable with host-native work, never exclusive**. The host is
111
110
  - `/w:quick` — starts `quick-loop` (shortcut, no `docs/`; escalates live to SPEC when the objective exceeds a quick).
112
111
  - `/w:export-scripts` · `/w:export-manuals` · `/w:export-diagrams` · `/w:export-reports` — promote artifacts to `docs/`.
113
112
 
114
- ### Transversal skills (no flow) — `/w:status` · `/w:doctor` · `/w:fix-git` · `/w:generate-launch` · `/w:persist` · `/w:resume`
113
+ ### Transversal skills (no flow) — `/w:status` · `/w:doctor` · `/w:fix-git` · `/w:generate-launch` · `/w:persist` · `/w:resume` · `/w:recall`
115
114
 
116
115
  **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
116
 
@@ -120,6 +119,7 @@ The flows are **composable with host-native work, never exclusive**. The host is
120
119
  - `/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`.
121
120
  - `/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`.
122
121
  - `/w:persist` — persists work **already done in this conversation** (an analysis, conclusions, a plan) into `docs/`: classifies its shape and routes it — analysis/conclusions → `docs/research/` · requirement-shaped → spec draft (`spec-new` procedure) · plan-shaped → plan adoption (`plan-new` mode 4) — with `## Origin` + attribution (host · model · date) and the anti-duplicate check. Never creates sessions; the host→`docs/` counterpart of `export-*` (which stays the only session→`docs/` path).
122
+ - `/w:recall` — reports what the other hosts' curated memory learned about Workline (backed by `aw host-memory`, which only reads), contrasts each learning against the installed CLI and doctrine, applies what still holds in the session and offers to save it in the current host's own memory, with its origin mark, only after confirmation. Never writes another host's memory.
123
123
  - `/w:resume` — read-only: composes `/w:status` for a prioritized summary of pending work (workline signals + host context) and proposes how to continue via structured-choice, routed to the target command (`spec-refine` / `plan-new` / `plan-exec` / reopen); an optional artifact argument (spec/plan/session) skips the survey and gets its exact re-entry route. Writes nothing; the actionable sibling of `/w:status`.
124
124
 
125
125
  ### The loops (Layer 2)
@@ -27,6 +27,7 @@ Every invoked directory is a usable implicit workspace. The closest ancestor wit
27
27
  | [`generate-launch`](generate-launch.md) | (Re)generates the per-source launch scripts (`.workflow/launch/<alias>/`) | single-pass (transversal) |
28
28
  | [`persist`](persist.md) | Persists in-conversation work into `docs/` (classify → `research` · spec draft · plan adoption) | single-pass (transversal) |
29
29
  | [`resume`](resume.md) | Summary (composes `/status`) + proposes how to resume pending work | single-pass (transversal) |
30
+ | [`recall`](recall.md) | What the other hosts learned about Workline: contrasted, applied, offered for saving | single-pass (transversal) |
30
31
  | [`export-scripts`](export-scripts.md) | Promotes session SQL migrations to `docs/scripts/` | single-pass, read-only |
31
32
  | [`export-manuals`](export-manuals.md) | Generates manuals in `docs/manuals/` | single-pass, read-only |
32
33
  | [`export-diagrams`](export-diagrams.md) | Generates C4/mermaid diagrams in `docs/diagrams/` | single-pass, read-only |
@@ -34,7 +35,7 @@ Every invoked directory is a usable implicit workspace. The closest ancestor wit
34
35
 
35
36
  > **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**.
36
37
  >
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*.
38
+ > **Transversal (no flow):** `status`, `doctor`, `fix-git`, `generate-launch`, `persist`, `resume` and `recall` 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*.
38
39
 
39
40
  ## Schema of each command file
40
41
 
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Use when the user asks what other hosts learned about Workline, to apply what still holds and offer to save it.
3
+ argument-hint: "(none)"
4
+ allowed-tools:
5
+ [
6
+ "Bash",
7
+ "Read",
8
+ "Write",
9
+ "Edit",
10
+ ]
11
+ ---
12
+
13
+ # recall — learnings from the other hosts
14
+
15
+ Runs only when the person invokes it, never at session start. No loop, no session, no `docs/`.
16
+
17
+ ## Run
18
+
19
+ 1. `aw host-memory --json` — reads the other hosts' curated memory and writes nothing. Only Workline learnings come back; the rest is a count.
20
+ 2. **Report every row of `hosts`**: which memories were read, and which are absent, keep none of their own, are disabled or unreadable, each with its reason. With no entries, say which case it is — no other host's memory was found (no row is `read`), or it was read and holds nothing about Workline yet — and carry on.
21
+ 3. **Leave out working state** — a run log, a plan's progress, a session's status. Keep what holds beyond one run.
22
+ 4. **Contrast each learning** into one of three states:
23
+ - **possibly stale** — it carries a `stale` signal, or `aw <command> --help` or the installed doctrine contradicts it. Do not apply it;
24
+ - **current** — it holds against them. Apply it;
25
+ - **unverified** — nothing here can check it. Check it when its situation arises.
26
+ 5. **Apply in this session** what is current and serves the work at hand: when its situation arises, act on it instead of researching again.
27
+ 6. **Present each learning with its host and its date** (`date` null → say it carries none).
28
+ 7. **Flag what two or more hosts found separately** as a possible Workline defect: say so, open no flow. Copies never count — an entry whose `provenance` is `copy` is the same finding as its original.
29
+ 8. **Offer to save only what is current and absent** (`present_in_destination: false`): show what gets saved and where, `current_host.destination.path`. Canonical [option shape](../loops/CHASSIS.md#structured-choice-design--batching) and [host binding](../harness/HARNESS.md#harness-binding-matrix). Save nothing without confirmation.
30
+ 9. **Save through the host's own channel** — the one `destination.channel` names, following that host's memory rules — with its `origin_mark` copied verbatim, so the next reading knows the copy.
31
+ 10. **With `destination` null**, give its `destination_reason`: say this host has nowhere to save and offer nothing.
32
+
33
+ > **Never write another host's memory.** Only the current host's destination is ever touched, and only after the person confirms.
34
+
35
+ Degradation is declared, never silent: with no structured-choice, list the options as labeled markdown with the `flow` control among them.
36
+
37
+ ## More context
38
+
39
+ `aw context-plan --command recall --root "${CLAUDE_PLUGIN_ROOT}/skills/w"` returns the extra documents a case needs; read exactly what it lists.
@@ -410,6 +410,10 @@
410
410
  }
411
411
  ]
412
412
  },
413
+ "recall": {
414
+ "core": ["commands/recall.md"],
415
+ "modules": [{ "path": "modules/PLAN-MODE.md", "signal": "plan-mode" }]
416
+ },
413
417
  "reset": {
414
418
  "core": ["commands/reset.md"],
415
419
  "modules": []
@@ -36,7 +36,7 @@ The capabilities the harness layer depends on, with their universal fallback (wh
36
36
  | **procedure-loading** | load a loop's/command's doctrine | the AI **reads the `.md`** of the loop and follows it (read-and-follow) |
37
37
  | **structured-choice** | ask the human ≤3 content questions **+ always** a `flow` control (`Compactar`/`Cerrar`); every option has a semantic label + one-sentence functional explanation/example | the host's own tool when the turn offers it; else the **`structured_choice`** tool of Workline's own MCP server, which renders the host's native selector by elicitation (only where the catalog declares it with dated evidence); else **labeled markdown** in chat, answered by label or by ratifying all first options with `Aceptar recomendaciones` |
38
38
  | **compaction** | shrink the context without losing the thread (+ a context-pressure **signal** for the chassis' self-regulation) | write `CHECKPOINT` and ask the user to restart the context and resume (resume keys off `CHECKPOINT`) |
39
- | **subagent-dispatch** | *(optional)* parallelize research breadth | **inline sequential** research in the same session (the default anyway) |
39
+ | **subagent-dispatch** | *(optional)* run the three stages the chassis admits — parallel research in the refine and planning loops, independent implementation units in the code loops, the code loops' final review — and the on-demand follow-up after close | the same cases **inline, in sequence** in the main thread; `plan-exec`'s review becomes a clean re-read its report declares (optional in `quick`) |
40
40
  | **persistent-context** | the `WORKSPACE` block + conventions always present | the repo's context file (standard **`AGENTS.md`**; `CLAUDE.md` on Claude Code) |
41
41
  | **host-memory** | *(optional)* recover state/pending work from the host's accessible history — a **second source** after the workline signals | recent **git** / **`docs/`** signals + (in `/resume`) **ask the user**; plus Workline's own `.workflow/CHECKPOINT` via `aw resume-summary` |
42
42
  | **web-research** | *(optional)* search/fetch external online evidence inside a consented ideation round (spec-refine § *Ideation gate*) | **offline ideation** (own knowledge + workspace + repos) — the loop **declares** the web was unavailable |
@@ -56,10 +56,14 @@ own target explicitly; environment detection is the fallback, while a shared
56
56
  - A deterministic tranche dispatches **zero** model workers, subagents and
57
57
  external processes. `aw flow advance` exhausts it locally until the first
58
58
  semantic, human, authorization, execution, blocked or final frontier.
59
- - A semantic tranche is inline by default. It may use subagents only for three
60
- or more independent partitions with no dependency and no overlapping writes;
61
- then the CLI caps them at **3** (at most **4** model workers including the
62
- coordinator). Human and authorization frontiers never fan out.
59
+ - A semantic tranche is inline by default. Subagents fit only the three stages
60
+ of the chassis rule (`../loops/CHASSIS.md`, *Subagents — admitted per stage*):
61
+ parallel research in `spec-refine`, `plan-new` and `plan-refine`; independent
62
+ implementation units in `plan-exec` and `quick`; the code loops' final review.
63
+ Research and implementation need three or more independent partitions with no
64
+ dependency and no overlapping writes, capped at **3** (at most **4** model
65
+ workers including the coordinator); the final review does not depend on that
66
+ threshold. Human and authorization frontiers never fan out.
63
67
  - An execution frontier has one external invocation at a time and returns its
64
68
  actual evidence; it is not a request to run more agents.
65
69
  - Token usage is recorded only when the host supplies a real count. Bytes,
@@ -14,28 +14,39 @@
14
14
  | `PreCompact` | `checkpoint-write` | Writes `CHECKPOINT.md` before the host compacts. **Never blocks the compaction.** |
15
15
  | `PostCompact` | `resume-summary` | Recovers **the conversation's own** loop state after a compact. |
16
16
 
17
- > **Conversation identity (spec 011).** The three lifecycle hooks act on **one**
18
- > session — the conversation's own — never on "the first active one" and never
19
- > on all of them. They resolve it with the canonical precedence: explicit
20
- > `--code` → the conversation's durable association → the sole active session.
21
- > The identity travels in the hook payload's `session_id` (read from stdin) or
22
- > in `AW_CONTEXT_ID`; two signals naming different conversations fail with
23
- > `CONTEXT_ID_CONFLICT` instead of picking one. The association lives in
24
- > `.workflow/sessions/.bindings.json` keyed by the SHA-256 of that id — the raw
25
- > value is never persisted.
17
+ > **Conversation identity (spec 011, spec 056).** The three lifecycle hooks act
18
+ > on **one** session — the conversation's own — never on "the first active one"
19
+ > and never on all of them. They resolve it as every write does: explicit
20
+ > `--code` → the conversation's durable association. A write **never** falls back
21
+ > to the sole active session: it may be another conversation's line, so with no
22
+ > identity and an active session it refuses with `SESSION_UNBOUND`, lists the
23
+ > active sessions and asks for `--code <NNN>`. Only reads keep that fallback. The identity travels in the
24
+ > hook payload's `session_id` (read from stdin) or in `AW_CONTEXT_ID`; two
25
+ > signals naming different conversations fail with `CONTEXT_ID_CONFLICT` instead
26
+ > of picking one. The association lives in `.workflow/sessions/.bindings.json`
27
+ > keyed by the SHA-256 of that id — the raw value is never persisted. Hosts that
28
+ > give the agent's commands no id associate nothing, so there the CHECKPOINT is
29
+ > always written with `aw checkpoint-write --code <NNN>`.
26
30
  >
27
31
  > **An unresolved session never holds a compaction back.** `PreCompact` always
28
32
  > exits **0**. It used to exit 2 on an ambiguity so a person could name the
29
33
  > session first, and that trapped the conversation: the remedy it printed does
30
34
  > not always bind the conversation, so the next `/compact` blocked again. Now the
31
35
  > host's compaction completes, Workline reports `continuity: "degraded"` with
32
- > `primary_session: null`, and — whenever there is a candidate that could adopt
33
- > it — parks a **refuge checkpoint** in `.workflow/sessions/.refuge/` naming the
34
- > reason, the candidates and the way out. `PostCompact` reports it as `refuge`,
35
- > and the first `checkpoint-write` that does resolve the session (typically
36
- > `--code <NNN>`) folds it into that session's `CHECKPOINT.md` and removes it.
37
- > The refuge names its conversation by the SHA-256 of the id, like the
38
- > association registry. Per-host installation and transport belong to spec 010.
36
+ > `primary_session: null`, says so on stderr (`PreCompact` and `SessionEnd`) and
37
+ > parks a **refuge checkpoint** in `.workflow/sessions/.refuge/` naming the
38
+ > reason, the **active** candidates and the way out — none at all when no
39
+ > session is active. `PostCompact` reports it as `refuge`.
40
+ >
41
+ > **Who adopts a refuge.** Its own conversation, into whichever session its next
42
+ > `checkpoint-write` or `SessionEnd` resolves. Anybody else only with `--code` on one of its candidates, and only
43
+ > when nobody else can claim it: it has no conversation, the invocation carries
44
+ > no id, or it is older than 24 hours. Adopting folds it into that session's
45
+ > `CHECKPOINT.md` and removes it. A refuge nobody can adopt any more — no active
46
+ > candidate, and no conversation or past the 24 hours — is swept on the next
47
+ > lifecycle write and listed in `refuges_swept`. The refuge names its
48
+ > conversation by the SHA-256 of the id, like the association registry.
49
+ > Per-host installation and transport belong to spec 010.
39
50
 
40
51
  > **What they enforce (host-level, blocking):** invariant **#4** (DB scripts-only) via `sql-mutation-guard` (blocks DML/DDL over MCP), and the *expected-branch* clause of **#5** via `branch-check` (blocks edits on the wrong branch). The rest of git-safe (`push`/`--amend`/`--no-verify`/`--force`) is **doctrinal** — `git-commit-advisor` only **warns**, it does not block; a host may add its own deny hook if it wants hard enforcement.
41
52
  >
@@ -1,6 +1,6 @@
1
1
  # CHASSIS — the loop engine
2
2
 
3
- This document is the **common engine** of the Workline loops: the doctrine every loop runs underneath its deltas. **It is not a skill** — it is a referenced document: every loop orders it read from its `## Inherits`, **always, before its deltas**. If you edit the engine, edit it **here** — heirs never repeat it, they only reference it.
3
+ The **common engine** of the Workline loops: every loop reads it from its `## Inherits`, **always, before its deltas**. Edit the engine **here**; heirs only reference it.
4
4
 
5
5
  > **When each step below happens is no longer this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document. They consume no model worker, subagent or external process: the CLI advances them locally to the first real frontier. What stays is what each rule is FOR — the half no engine carries. Answering the frontier it stops at is `aw flow submit`, and its envelope — which fields each kind of frontier demands, and where each digest comes from — is **read** with `aw flow --help`, never guessed.
6
6
 
@@ -20,13 +20,13 @@ The two that edit code also apply [`CODE-POLICIES.md`](CODE-POLICIES.md).
20
20
 
21
21
  A loop **is a persistent objective**: it exists to fulfill the `SESSION.Objective` declared at start, and **it is not finished until the convergence gate confirms the objective was met**. Gap-driven iteration is the *method*; the artifacts are the *record*; the objective is the *frame*.
22
22
 
23
- "Don't stop until convergence" is sustained by the loop itself — its `repeat:` plus the convergence gate — never by a host hook, which is what makes it harness-agnostic. Each heir instantiates the frame: `spec-refine` pursues the spec; the plan loops pursue the plan up to their gate; `plan-exec` up to its final validation; `quick-loop` its prompt.
23
+ "Don't stop until convergence" is sustained by the loop itself — its `repeat:` plus the convergence gate — never by a host hook, which is what makes it harness-agnostic.
24
24
 
25
- > **Inter-turn continuity.** The same `CHECKPOINT`+resume governs the **next prompt**: the objective persists **across turns**, not only within a run. The canonical rules (command = new work line · re-run = `create_or_resume` · bare prompt = continue the most recent session · reopening closed sessions · consented escalation) are the **single source** in [`../SKILL.md`](../SKILL.md) § *Operating context*; this engine executes them via *Compact / resume* (case 3).
25
+ > **Inter-turn continuity.** The same `CHECKPOINT`+resume governs the **next prompt**: the objective persists **across turns**, not only within a run. Its canonical rules have their **single source** in [`../SKILL.md`](../SKILL.md) § *Operating context*; this engine executes them via *Compact / resume* (case 3).
26
26
 
27
27
  ## Verification-first
28
28
 
29
- The persistent objective needs a **checkable done-condition** — otherwise the loop cannot know when it is done (or chases a target it invented). That condition is **seeded BEFORE executing**, never improvised at the end: it is **generalized TDD**. Together with artifact-first (next section) these are the **two seeds** of every gap/phase: *how will I know it worked* + *what am I about to do*.
29
+ The persistent objective needs a **checkable done-condition** — otherwise the loop cannot know when it is done (or chases a target it invented). That condition is **seeded BEFORE executing**, never improvised at the end: it is **generalized TDD**.
30
30
 
31
31
  **Where it lives:** in `SESSION.Success criteria` — a `[ ]` checklist of **falsifiable** criteria (that *can* fail). `CHECKPOINT.Pending/Completed` tracks the **red→green** progress. Two forms, by deliverable:
32
32
 
@@ -44,7 +44,7 @@ The persistent objective needs a **checkable done-condition** — otherwise the
44
44
 
45
45
  **Gate integrity (anti-gaming + independent verification).** The gate only counts if it is not gamed to pass. The loop does **not**: modify the check or loosen a `Success criterion` to force green; weaken, delete or skip tests/validations; use trivial or tautological asserts that always pass (the expected value comes from an independent source, never from the output itself); patch the test instead of fixing the cause (prefer fixing production code).
46
46
 
47
- Facing a real blocker it **stops and reports it** (→ `Open questions`/`BACKLOG`) instead of gaming the metric. The verdict counts **only the check's output, never the implementer's self-declaration**: when the deliverable warrants it, the final verification is an **independent** pass (subagent only when the CLI's independent-partition rule admits it, or a clean re-read) that does not assume the implementation is correct — *only command output counts*.
47
+ Facing a real blocker it **stops and reports it** (→ `Open questions`/`BACKLOG`) instead of gaming the metric. The verdict counts **only the check's output, never the implementer's self-declaration**: when the deliverable warrants it, the final verification is an **independent** pass (a clean re-read in the main thread; in the code loops, `CODE-POLICIES.md`'s review) that does not assume the implementation is correct — *only command output counts*.
48
48
 
49
49
  **Minimality (anti-over-engineering).** Passing the criteria is **necessary, not sufficient**: the gate also rejects a deliverable **heavier than its `Success criteria` require** — YAGNI at the deliverable's altitude. A spec can be coherent yet over-specified; a plan sound yet over-engineered; a diff green yet padded with reinvented stdlib, speculative abstractions or dead flexibility. At its own altitude the gate asks the laziest-that-works questions:
50
50
 
@@ -62,7 +62,7 @@ The loop works **artifact-first**: the artifact is **seeded before** executing a
62
62
  2. **EXECUTE.** Resolve the gap / run the phase / edit the code.
63
63
  3. **AFTER — bring to actual state.** `CHECKPOINT.Pending → Completed`; `DECISION` records the non-obvious **as it is decided**; `BACKLOG` **only if** something is deferred/follow-up.
64
64
 
65
- > The artifact expresses the **intent** (before) and then the **result** (after), at **every** gap/phase boundary — not only on `Compactar`/`Cerrar`. Session artifacts are the run's live log; the spec/plan is the **guiding base**.
65
+ > Session artifacts are the run's live log at **every** boundary, not only on `Compactar`/`Cerrar`; the spec/plan is the **guiding base**.
66
66
 
67
67
  > **Fixed form (hard rule):** an artifact keeps its template's `##` headings **exactly** and is updated **in place** — appending a **duplicate heading** is a contract violation. A filled section **replaces** its `<!-- … -->` guidance comment. Canonical headings per artifact: its template under [`../artifacts/`](../artifacts/) (CHECKPOINT: `Completed` · `Pending / Next`; `Open questions` only while live doubts exist).
68
68
 
@@ -72,13 +72,13 @@ The common cycle — each heir instantiates it in its `## Sequence` with its own
72
72
 
73
73
  ## Internal sessions (managed) — one session per run
74
74
 
75
- The loop creates and manages its session under `.workflow/sessions/`; **the user never creates it**. **A single session per run**: it keeps progress live (`CHECKPOINT`) and enables resume. Artifacts: `SESSION.md` · `CHECKPOINT.md` (· `BACKLOG.md` only if something is deferred; code-editing loops add `DECISION` and `SCRIPTS.sql`). Each heir declares its descriptor and `Type` in its own `## Internal sessions`.
75
+ The loop creates and manages its session under `.workflow/sessions/`; **the user never creates it**. **A single session per run**: it keeps progress live (`CHECKPOINT`) and enables resume. Artifacts: `SESSION.md` · `CHECKPOINT.md` (· `BACKLOG.md`; code-editing loops add `DECISION` and `SCRIPTS.sql`). Each heir declares its descriptor and `Type` in its own `## Internal sessions`.
76
76
 
77
77
  > The flow's input document (spec/plan) **never** goes inside a session; it lives in `docs/`.
78
78
 
79
- **CLI**: `aw session-create --type <type> --name <slug>-<flow> --objetivo "<one-line objective>"` opens it · `aw checkpoint-write` / `aw checkpoint-read` keep it resumable. **Closing it is the CLI's own move**, run at `finalize`: a loop never issues the close itself, and one issued mid-run leaves the next `advance`/`submit` standing on a closed session.
79
+ **CLI**: `aw session-create --type <type> --name <slug>-<flow> --objetivo "<one-line objective>"` opens it · `aw checkpoint-write --code <NNN>` / `aw checkpoint-read` keep it resumable. **Closing it is the CLI's own move**, run at `finalize`: a loop never runs it, and one issued mid-run leaves the next `advance`/`submit` on a closed session.
80
80
 
81
- > The caller passes **only the descriptor** via `--name` — **never** a number; the CLI owns the global `NNN`. How it is assigned, how a session is located or reopened, and how a failed history upsert is repaired, are in the `sessions` module.
81
+ > The caller passes **only the descriptor** via `--name` — **never** a number; the CLI owns the global `NNN`. Its assignment, locating or reopening a session and repairing a failed history upsert live in the `sessions` module.
82
82
 
83
83
  ## Ask-vs-research rule (the discriminator)
84
84
 
@@ -86,13 +86,18 @@ Which resolver a gap gets is the kind of thing it is, and the CLI classifies it:
86
86
 
87
87
  ## Research: autonomy, scope & failure
88
88
 
89
- Investigation is **inline**: an activity **inside the run's current session**, never a separate session. It writes its artifacts (`ANALYSIS-FILE` → `CONCLUSIONS`, + read-only `SCRIPTS.sql` if it queries DB) **into the session's own folder**.
89
+ Investigation runs **inside the run's current session**, never a separate session. It writes its artifacts (`ANALYSIS-FILE` → `CONCLUSIONS`, + read-only `SCRIPTS.sql` if it queries DB) **into the session's own folder**.
90
90
 
91
- - **Autonomous**: the AI investigates inline and reports **without asking permission**. The human learns of it at integration time and keeps control via the `flow` control.
91
+ - **Autonomous**: the AI investigates and reports **without asking permission**. The human keeps control via the `flow` control.
92
92
  - **Scope**: the current conversation (settled conclusions are reused, never re-derived) + workspace + associated repos + DB MCPs.
93
93
  - **DB rule** — the single exception to autonomy: it lives in the `db` module and is loaded **before** any query runs.
94
94
  - **Inconclusive research** (DB unavailable, insufficient evidence, unresolvable factual gap): the investigation closes **`inconclusive`** in `CONCLUSIONS` with its reason. The loop **degrades** the gap — to a human question, or failing that to the flow doc's `## Open questions` (the session's `BACKLOG` when the flow has no doc) — instead of re-firing it. Capping the attempts is the CLI's; declaring where a degraded gap GOES is doctrine's, because a gap dropped without a destination is this engine's promised convergence, faked.
95
95
 
96
+ **Subagents — admitted per stage.** Only three cases inside a run: parallel research in `spec-refine`, `plan-new` and `plan-refine`; implementing independent units in `plan-exec` and `quick`; the code loops' final review.
97
+ Research and implementation fan out only with **three or more independent** parts, at most **3** at a time. Independent means none uses another's result or writes what another writes; dependent units run in sequence.
98
+ Everything else stays in the main thread: drafting, deciding, asking, shaping phases, persisting, updating state, resuming, integrating, committing and a document loop's closing verification. Capture (`spec-new`) keeps its total ban.
99
+ This rule prevails over the host's mode and over any installed skill that orders agent orchestration; a host without subagents runs the same cases inline.
100
+
96
101
  ## Structured-choice (design & batching)
97
102
 
98
103
  **Canonical form:** *structured-choice* = **≤3 content questions + 1 `flow` control**, always. Each option is a **short semantic label + one functional sentence** (outcome/trade-off or simple example), never a positional code. The CLI builds it and refuses a question that does not hold this form. Present it with the richest current binding in [`HARNESS.md`](../harness/HARNESS.md); otherwise labeled markdown.
@@ -132,7 +137,6 @@ The engine above is what every run needs. The branches below apply only under th
132
137
 
133
138
  - `adopted` → [`../modules/ADOPTED-CONTEXT.md`](../modules/ADOPTED-CONTEXT.md) · `probe` → [`../modules/PROBE.md`](../modules/PROBE.md) · `db` → [`../modules/DB-RESEARCH-RULE.md`](../modules/DB-RESEARCH-RULE.md)
134
139
  - `compaction` → [`../modules/COMPACTION.md`](../modules/COMPACTION.md) · `sessions` → [`../modules/SESSION-NUMBERING.md`](../modules/SESSION-NUMBERING.md)
135
- - `code` → [`CODE-POLICIES.md`](CODE-POLICIES.md), which the two code-editing loops order read from their `## Inherits`
136
140
 
137
141
  ## Reference resolution (global layout rule) — and what the chassis is NOT
138
142
 
@@ -1,9 +1,8 @@
1
1
  # CODE-POLICIES — policies for code-editing loops
2
2
 
3
3
  They apply to **`plan-exec-loop`** (per effective batch) and **`quick-loop`** (the single task;
4
- **proportional** gate): each reads this doc with the chassis, and no document loop loads it. These
5
- policies own the DB scripts-only, safe Git and closing-review invariants; code loops keep only a
6
- short inline floor for advisory hosts.
4
+ **proportional** gate), read with the chassis. They own the DB scripts-only, safe Git and
5
+ closing-review invariants.
7
6
 
8
7
  ## Safe git — verified branch + proposed commits
9
8
 
@@ -17,7 +16,7 @@ its internal phases in one reviewed commit, and no batch may co-mingle with anot
17
16
 
18
17
  Concurrent flows never share a working tree: a run declares its sources and takes an **isolation
19
18
  unit** in each before writing — a worktree on its own branch
20
- (`aw worktree ensure | list | release`), where branch and commits are read. An edit outside is
19
+ (`aw worktree ensure | list | release`). An edit outside is
21
20
  blocked naming the command that gets one, and at close `aw worktree integrate` merges each into
22
21
  the source's work branch; a conflict is reported, routed to `aw fix-git --path`, never alone.
23
22
 
@@ -29,16 +28,22 @@ After validation and before commits, the whole execution-unit diff passes a **cl
29
28
  gate**: an effective batch in plan-exec, or the proportional task in quick. Early `Cerrar` uses the
30
29
  same gate before any pending commit.
31
30
 
32
- - **Independent re-read** of the diff (subagent or clean re-read — the engine's *independent verification*: it does not assume the implementation is correct; *only command output counts*).
31
+ - **Independent re-read** of the diff — the engine's *independent verification*: it does not assume the implementation is correct; *only command output counts*. In `quick` a subagent reviewer is optional; `plan-exec` requires a distinct one (its Delta 5).
33
32
  - **Apply the installed ambient conventions** relevant to the touched stack (code/stack standards, security, diff review, the workspace's own families) — the host **auto-discovers them by `description`**. Workline **names and binds no** concrete conventions skill: **it creates the moment; the installed skills fill it** (that is why review is **not a role** — see [`../roles/README.md`](../roles/README.md)). With no convention skills installed → minimal generic checklist: SOLID/early-return, clear names, DRY, no silenced errors, no secrets/PII, parametrized SQL, no dead code, + the plan's `Validations` (if any).
34
33
  - **Minimality lens** (floor — holds with **no external skill**; chassis § *Minimality*): re-read the diff for over-building. Flag `delete` (dead/speculative code), `stdlib` (reinvented standard library), `native` (a dep or code doing what the platform already does), `yagni` (one-implementation abstraction, config nobody sets, one-caller layer), `shrink` (same behavior, fewer lines). An installed ambient review skill *raises* this; it never lowers it.
35
34
  - **Test-value lens** (floor, next to minimality): every test the diff adds must demonstrate an observable behavior, protect a business rule, verify a contract, exercise a real integration or prevent a known regression. Flag `overtest` for the ones that only mirror structure — a test per class or method, mocked call chains, the same happy path re-asserted at every layer, trivial getters/setters/mappers, cases written for coverage, broad snapshots where a functional assertion is clearer. Bounded by *Gate integrity*: `overtest` prunes redundancy, **never** a check that guards behavior, a trust boundary, security or accessibility.
36
35
  - **Temporary simulation check** (only when the change carries one): stubs, fakes and in-memory adapters are **explicit and named as such** (`Stub…` / `Fake…`), they sit at the boundary the plan declares, and no configuration can select them in a production runtime. A simulation still active on the main path with no declared removal is a finding, not a detail.
37
- - **Tooling check** (`docs/tools`): did the run create **reusable auxiliary tooling** (support scripts/CLIs/generators/reusable configs — not product code, not session probes)? → the host applies the **ambient `creating-tools` skill** (auto-discovered by its `description`; Workline does not bind it) so the tool gets its home under `docs/tools/<slug>/` (README + run/output structure per that skill's contract + its index row). Host without such a skill → the loop still **never writes `docs/tools` itself**: **declare the gap** — the homeless tool goes to the plan's `Open questions` + `BACKLOG` (in quick, `BACKLOG`) — never silent.
36
+ - **Tooling check** (`docs/tools`): did the run create **reusable auxiliary tooling** (support scripts/CLIs/generators/reusable configs — not product code, not session probes)? → the host applies the **ambient `creating-tools` skill** (auto-discovered; Workline does not bind it), which homes it under `docs/tools/<slug>/` per its contract. Host without such a skill → the loop still **never writes `docs/tools` itself**: **declare the gap** — the homeless tool goes to the plan's `Open questions` + `BACKLOG` (in quick, `BACKLOG`) — never silent.
38
37
  - **Findings**: **fix** them in the working tree and **re-run validation** (the gate does not replace the tests: it re-verifies after fixing), or **defer them justified** (→ the plan's `Open questions` + `BACKLOG`; in quick, `BACKLOG`); the non-obvious → `DECISION`. Gate integrity (see [`CHASSIS.md`](CHASSIS.md) § *Verification-first*): never weaken a check or lower a convention to pass.
39
38
  - **Artifact-first + verification-first**: seed `CHECKPOINT.Next = "review <batch/task>"`; Success
40
39
  criteria require the whole diff to pass before commits.
41
40
 
41
+ **Close first, follow up on demand.** Before the commit only the validations and this review run;
42
+ nothing waits on exploration. After commit and integration the report offers a parallel follow-up
43
+ that probes what was delivered, in one line. It runs only if the user asks; its agents never modify
44
+ the delivered work nor commit. Each finding comes back as a ready `/w:quick`, without reopening the
45
+ closed document or session. A host without subagents runs it inline.
46
+
42
47
  ## Conditional modules
43
48
 
44
49
  - `db` — the DB scripts-only rule → `../modules/DB-SCRIPTS-ONLY.md`