@ludecker/aaac 1.1.5 → 1.2.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 (104) hide show
  1. package/README.md +27 -12
  2. package/package.json +9 -9
  3. package/src/cli.mjs +19 -7
  4. package/src/generators/generate-commands.mjs +25 -1
  5. package/src/generators/generate-graph.mjs +9 -1
  6. package/src/lib/install.mjs +13 -1
  7. package/src/lib/sweep-project-docs.mjs +348 -0
  8. package/src/run-engine/advance-phase.mjs +23 -0
  9. package/src/run-engine/debug-run.mjs +0 -0
  10. package/src/run-engine/gate-write.mjs +13 -0
  11. package/src/run-engine/lib.mjs +153 -5
  12. package/src/run-engine/log-dump.mjs +0 -0
  13. package/src/run-engine/log-trace.mjs +0 -0
  14. package/templates/cursor/aaac/enforcement.json +96 -5
  15. package/templates/cursor/aaac/graph.project.yaml +44 -5
  16. package/templates/cursor/aaac/lifecycle/lifecycle.json +26 -0
  17. package/templates/cursor/aaac/lifecycle/phases.json +9 -1
  18. package/templates/cursor/aaac/ontology.json +1 -0
  19. package/templates/cursor/aaac/project.config.json +36 -0
  20. package/templates/cursor/aaac/scripts/remediation/auto-check-swarm-synthesis.mjs +75 -0
  21. package/templates/cursor/aaac/scripts/remediation/auto-dispatch-queue-from-health.mjs +78 -0
  22. package/templates/cursor/aaac/scripts/remediation/bootstrap-autonomous.mjs +113 -0
  23. package/templates/cursor/aaac/scripts/remediation/capture-verify-baseline.mjs +66 -0
  24. package/templates/cursor/aaac/scripts/remediation/capture-wave-snapshot.mjs +79 -0
  25. package/templates/cursor/aaac/scripts/remediation/check-swarm-raw.template.json +26 -0
  26. package/templates/cursor/aaac/scripts/remediation/classify-fallow-issues.mjs +77 -0
  27. package/templates/cursor/aaac/scripts/remediation/classify-verify-failure.mjs +176 -0
  28. package/templates/cursor/aaac/scripts/remediation/compute-satisfaction.mjs +344 -0
  29. package/templates/cursor/aaac/scripts/remediation/debt-sweep-gate.mjs +202 -0
  30. package/templates/cursor/aaac/scripts/remediation/dispatch-rules.json +44 -0
  31. package/templates/cursor/aaac/scripts/remediation/fallow-fp-rules.json +87 -0
  32. package/templates/cursor/aaac/scripts/remediation/fallow-scan.mjs +219 -0
  33. package/templates/cursor/aaac/scripts/remediation/handle-yield.mjs +240 -0
  34. package/templates/cursor/aaac/scripts/remediation/init-campaign.mjs +211 -0
  35. package/templates/cursor/aaac/scripts/remediation/lib/autonomous-mode.mjs +63 -0
  36. package/templates/cursor/aaac/scripts/remediation/lib/campaign-focus.mjs +87 -0
  37. package/templates/cursor/aaac/scripts/remediation/lib/fallow-classifier.mjs +190 -0
  38. package/templates/cursor/aaac/scripts/remediation/lib/fallow-health-targets.mjs +56 -0
  39. package/templates/cursor/aaac/scripts/remediation/lib/fallow-metrics.mjs +119 -0
  40. package/templates/cursor/aaac/scripts/remediation/lib/invoke-cursor-agent.mjs +51 -0
  41. package/templates/cursor/aaac/scripts/remediation/lib/reconcile-run-manifest.mjs +41 -0
  42. package/templates/cursor/aaac/scripts/remediation/lib/regression-analysis.mjs +55 -0
  43. package/templates/cursor/aaac/scripts/remediation/lib/remediation-config.mjs +69 -0
  44. package/templates/cursor/aaac/scripts/remediation/lib/remediation-progress.mjs +58 -0
  45. package/templates/cursor/aaac/scripts/remediation/lib/remediation-watch-loop.mjs +168 -0
  46. package/templates/cursor/aaac/scripts/remediation/lib/runner-exec.mjs +156 -0
  47. package/templates/cursor/aaac/scripts/remediation/lib/runner-state.mjs +145 -0
  48. package/templates/cursor/aaac/scripts/remediation/lib/verify-metrics.mjs +205 -0
  49. package/templates/cursor/aaac/scripts/remediation/merge-check-swarm.mjs +257 -0
  50. package/templates/cursor/aaac/scripts/remediation/plan-waves-from-queue.mjs +85 -0
  51. package/templates/cursor/aaac/scripts/remediation/prepare-check-context.mjs +148 -0
  52. package/templates/cursor/aaac/scripts/remediation/record-fallow-fp.mjs +107 -0
  53. package/templates/cursor/aaac/scripts/remediation/record-iteration-step.mjs +56 -0
  54. package/templates/cursor/aaac/scripts/remediation/remediation-cli.mjs +157 -0
  55. package/templates/cursor/aaac/scripts/remediation/remediation-cursor-watch.sh +10 -0
  56. package/templates/cursor/aaac/scripts/remediation/remediation-runner-daemon.sh +13 -0
  57. package/templates/cursor/aaac/scripts/remediation/remediation-runner.mjs +748 -0
  58. package/templates/cursor/aaac/scripts/remediation/remediation-yield-watcher.mjs +40 -0
  59. package/templates/cursor/aaac/scripts/remediation/remediator-gate.mjs +405 -0
  60. package/templates/cursor/aaac/scripts/remediation/repair-fallow-start-baseline.mjs +118 -0
  61. package/templates/cursor/aaac/scripts/remediation/runner-health-check.mjs +164 -0
  62. package/templates/cursor/aaac/scripts/remediation/satisfaction-loop-gate.mjs +286 -0
  63. package/templates/cursor/aaac/scripts/remediation/validate-campaign-complete.mjs +191 -0
  64. package/templates/cursor/aaac/scripts/remediation/verify-remediation-iteration.mjs +112 -0
  65. package/templates/cursor/aaac/scripts/run-engine/advance-phase.mjs +23 -0
  66. package/templates/cursor/aaac/scripts/run-engine/debug-run.mjs +0 -0
  67. package/templates/cursor/aaac/scripts/run-engine/gate-write.mjs +13 -0
  68. package/templates/cursor/aaac/scripts/run-engine/lib.mjs +153 -5
  69. package/templates/cursor/aaac/scripts/run-engine/log-dump.mjs +0 -0
  70. package/templates/cursor/aaac/scripts/run-engine/log-trace.mjs +0 -0
  71. package/templates/cursor/agents/doc-conformance.md +25 -0
  72. package/templates/cursor/agents/implementation-review.md +21 -0
  73. package/templates/cursor/agents/remediation-check-app-inventory.md +32 -0
  74. package/templates/cursor/agents/remediation-check-app-ssot.md +24 -0
  75. package/templates/cursor/agents/remediation-check-app-trace.md +29 -0
  76. package/templates/cursor/agents/remediation-check-architecture-boundaries.md +21 -0
  77. package/templates/cursor/agents/remediation-check-architecture-decomposition.md +25 -0
  78. package/templates/cursor/agents/remediation-check-architecture-deps.md +23 -0
  79. package/templates/cursor/agents/remediation-check-risk.md +37 -0
  80. package/templates/cursor/agents/remediation-e2e-gate.md +30 -0
  81. package/templates/cursor/agents/remediation-remediator.md +69 -0
  82. package/templates/cursor/agents/test-author.md +27 -0
  83. package/templates/cursor/commands/remediate-app.md +212 -0
  84. package/templates/cursor/hooks/aaac-before-submit.sh +0 -0
  85. package/templates/cursor/hooks/aaac-pre-tool.sh +0 -0
  86. package/templates/cursor/hooks/aaac-stop.sh +0 -0
  87. package/templates/cursor/hooks/aaac-subagent-start.sh +0 -0
  88. package/templates/cursor/rules/aaac-enforcement.mdc +10 -3
  89. package/templates/cursor/skills/shared/execution/SKILL.md +7 -3
  90. package/templates/cursor/skills/shared/governance/implementation/SKILL.md +396 -28
  91. package/templates/cursor/skills/shared/implementation-review/SKILL.md +49 -0
  92. package/templates/cursor/skills/shared/planning/SKILL.md +5 -0
  93. package/templates/cursor/skills/shared/remediation/SKILL.md +51 -0
  94. package/templates/cursor/skills/shared/remediation/babysit/SKILL.md +223 -0
  95. package/templates/cursor/skills/shared/remediation/check-swarm/SKILL.md +114 -0
  96. package/templates/cursor/skills/shared/remediation/orchestrator/SKILL.md +275 -0
  97. package/templates/cursor/skills/shared/remediation/orchestrator/contract.yaml +116 -0
  98. package/templates/cursor/skills/shared/test-authoring/SKILL.md +58 -0
  99. package/templates/cursor/skills/shared/testing/SKILL.md +6 -0
  100. package/templates/cursor/skills/shared/verbs/create/orchestrator/SKILL.md +5 -3
  101. package/templates/cursor/skills/shared/verbs/fix/orchestrator/SKILL.md +5 -3
  102. package/templates/cursor/skills/shared/verbs/update/orchestrator/SKILL.md +5 -3
  103. package/templates/cursor/skills/shared/verification/SKILL.md +5 -3
  104. package/templates/docs/agentic_architecture.md +169 -97
@@ -123,6 +123,28 @@ export function isEditPhase(phase, enforcement) {
123
123
  return enforcement.edit_phases.includes(phase);
124
124
  }
125
125
 
126
+ /** Test/spec file paths — used for writer vs tester phase scoping. */
127
+ export function isTestPath(filePath) {
128
+ if (!filePath) return false;
129
+ const normalized = filePath.replace(/\\/g, "/");
130
+ return (
131
+ /\.(test|spec)\.(mjs|cjs|js|ts|tsx)$/.test(normalized) ||
132
+ /(?:^|\/)__tests__(?:\/|$)/.test(normalized) ||
133
+ /(?:^|\/)tests\/(?:unit|integration|e2e|fixtures)\//.test(normalized)
134
+ );
135
+ }
136
+
137
+ /** Phase-scoped edit rules from enforcement.phase_edit_scopes (v3+). */
138
+ export function isPathAllowedForPhase(filePath, phase, enforcement) {
139
+ if (!filePath) return true;
140
+ const scopes = enforcement.phase_edit_scopes?.[phase];
141
+ if (!scopes) return true;
142
+ const isTest = isTestPath(filePath);
143
+ if (scopes.deny_test_paths && isTest) return false;
144
+ if (scopes.test_paths_only && !isTest) return false;
145
+ return true;
146
+ }
147
+
126
148
  export function isArtifactPath(filePath, enforcement) {
127
149
  const normalized = filePath.replace(/\\/g, "/");
128
150
  const prefixes = [
@@ -138,11 +160,22 @@ export function phaseKind(phase, registry) {
138
160
 
139
161
  /** Swarm minimum for completed phase — check verb uses check_swarm on discover. */
140
162
  export function resolveSwarmMinimum(completedPhase, manifest, enforcement) {
141
- if (
142
- completedPhase === "verify" &&
143
- (enforcement.fix_commands?.includes(manifest.command) || manifest.verb === "fix")
144
- ) {
145
- return enforcement.swarm_min_agents?.verify_fix;
163
+ const mutating = enforcement.mutating_verbs ?? ["create", "update", "fix"];
164
+ const isMutating =
165
+ mutating.includes(manifest.verb) ||
166
+ enforcement.fix_commands?.includes(manifest.command);
167
+
168
+ if (completedPhase === "verify" && isMutating) {
169
+ return (
170
+ enforcement.swarm_min_agents?.verify ??
171
+ enforcement.swarm_min_agents?.verify_fix
172
+ );
173
+ }
174
+ if (completedPhase === "test_execute" && isMutating) {
175
+ return enforcement.swarm_min_agents?.test_execute;
176
+ }
177
+ if (completedPhase === "review_swarm" && isMutating) {
178
+ return enforcement.swarm_min_agents?.review_swarm;
146
179
  }
147
180
  if (completedPhase === "discover" && manifest.verb === "check") {
148
181
  return (
@@ -189,3 +222,118 @@ export function clearActiveRun(conversationId) {
189
222
  // already cleared
190
223
  }
191
224
  }
225
+
226
+ export function isMutatingVerb(manifest, enforcement) {
227
+ const mutating = enforcement.mutating_verbs ?? ["create", "update", "fix"];
228
+ return (
229
+ mutating.includes(manifest.verb) ||
230
+ (enforcement.fix_commands ?? []).includes(manifest.command)
231
+ );
232
+ }
233
+
234
+ /** List items under a YAML field (lines starting with `-` before next top-level key). */
235
+ export function readYamlListField(content, fieldName) {
236
+ if (!content) return [];
237
+ const lines = content.split("\n");
238
+ const start = lines.findIndex((line) => line.startsWith(`${fieldName}:`));
239
+ if (start < 0) return [];
240
+
241
+ const inline = lines[start].slice(`${fieldName}:`.length).trim();
242
+ if (inline === "[]") return [];
243
+ if (inline && !inline.startsWith("-")) return [inline];
244
+
245
+ const items = [];
246
+ for (let i = start + 1; i < lines.length; i += 1) {
247
+ const line = lines[i];
248
+ if (/^\S/.test(line) && line.trim()) break;
249
+ const itemMatch = line.match(/^\s+-\s+(.*)$/);
250
+ if (itemMatch) items.push(itemMatch[1].trim());
251
+ }
252
+ return items;
253
+ }
254
+
255
+ export function readYamlScalarField(content, fieldName) {
256
+ if (!content) return null;
257
+ const match = content.match(new RegExp(`^${fieldName}:\\s*(.+)$`, "m"));
258
+ if (!match) return null;
259
+ return match[1].trim().replace(/^["']|["']$/g, "");
260
+ }
261
+
262
+ export function hasYamlField(content, fieldName) {
263
+ if (!content) return false;
264
+ return new RegExp(`^${fieldName}:`, "m").test(content);
265
+ }
266
+
267
+ export function planRequiresTests(planContent) {
268
+ if (!planContent) return false;
269
+ if (hasYamlField(planContent, "tests_to_add")) {
270
+ return readYamlListField(planContent, "tests_to_add").length > 0;
271
+ }
272
+ return /^\s*create:[\s\S]*?^\s+-\s+path:.*\/lib\//m.test(planContent);
273
+ }
274
+
275
+ export function validatePhaseArtifactContent(runId, completedPhase, manifest, enforcement) {
276
+ if (!isMutatingVerb(manifest, enforcement)) {
277
+ return { ok: true };
278
+ }
279
+
280
+ const planPath = path.join(runDir(runId), "artifacts/plan.yaml");
281
+ const planContent = fs.existsSync(planPath)
282
+ ? fs.readFileSync(planPath, "utf8")
283
+ : "";
284
+
285
+ if (completedPhase === "plan") {
286
+ if (!hasYamlField(planContent, "tests_to_add")) {
287
+ return {
288
+ ok: false,
289
+ reason:
290
+ "plan.yaml must include tests_to_add (behaviors to cover, or tests_to_add: [] when no tests are needed)",
291
+ };
292
+ }
293
+ return { ok: true };
294
+ }
295
+
296
+ if (completedPhase === "test_execute") {
297
+ const testPlanPath = path.join(runDir(runId), "artifacts/test_plan.yaml");
298
+ const testPlanContent = fs.existsSync(testPlanPath)
299
+ ? fs.readFileSync(testPlanPath, "utf8")
300
+ : "";
301
+
302
+ const filesWritten = readYamlListField(testPlanContent, "files_written");
303
+ const skippedReason = readYamlScalarField(testPlanContent, "skipped_reason");
304
+ const testsRequired = planRequiresTests(planContent);
305
+
306
+ if (/status:\s*deferred/i.test(testPlanContent) && filesWritten.length === 0) {
307
+ return {
308
+ ok: false,
309
+ reason:
310
+ "test_plan.yaml cannot defer tests — author test files in test_execute (files_written required)",
311
+ };
312
+ }
313
+
314
+ if (testsRequired && filesWritten.length === 0) {
315
+ return {
316
+ ok: false,
317
+ reason:
318
+ "plan.yaml tests_to_add requires non-empty test_plan.files_written — launch test-author Task in test_execute",
319
+ };
320
+ }
321
+
322
+ if (
323
+ hasYamlField(planContent, "tests_to_add") &&
324
+ /tests_to_add:\s*\[\]/m.test(planContent) &&
325
+ filesWritten.length === 0 &&
326
+ !skippedReason
327
+ ) {
328
+ return {
329
+ ok: false,
330
+ reason:
331
+ "tests_to_add is empty — test_plan.yaml must include skipped_reason explaining why no tests were authored",
332
+ };
333
+ }
334
+
335
+ return { ok: true };
336
+ }
337
+
338
+ return { ok: true };
339
+ }
File without changes
File without changes
@@ -1,15 +1,43 @@
1
1
  {
2
- "version": 2,
2
+ "version": 3,
3
3
  "description": "AAAC runtime enforcement — SSOT for hooks and run engine",
4
- "edit_phases": ["execute", "sync_inventory", "persist", "write"],
5
- "artifact_write_phases": ["plan", "report", "verify"],
4
+ "edit_phases": [
5
+ "execute",
6
+ "debt_sweep",
7
+ "test_execute",
8
+ "sync_inventory",
9
+ "persist",
10
+ "write"
11
+ ],
12
+ "artifact_write_phases": [
13
+ "plan",
14
+ "report",
15
+ "campaign_init",
16
+ "scan",
17
+ "check_swarm",
18
+ "plan_waves",
19
+ "satisfaction_gate"
20
+ ],
21
+ "mutating_verbs": ["create", "update", "fix"],
22
+ "phase_edit_scopes": {
23
+ "execute": { "deny_test_paths": true },
24
+ "test_execute": { "test_paths_only": true }
25
+ },
6
26
  "verify_verbs": ["create", "update", "fix"],
7
27
  "swarm_min_agents": {
8
28
  "discover": 4,
9
29
  "check_swarm": 3,
10
30
  "investigate_swarm": 7,
11
31
  "research_swarm": 6,
12
- "verify_fix": 3
32
+ "test_execute": 1,
33
+ "verify": 3,
34
+ "verify_fix": 3,
35
+ "review_swarm": 3
36
+ },
37
+ "swarm_min_agents_by_command": {
38
+ "remediate-app": {
39
+ "check_swarm": 7
40
+ }
13
41
  },
14
42
  "phase_artifacts": {
15
43
  "investigate_swarm": ["artifacts/investigation.md"],
@@ -20,12 +48,75 @@
20
48
  "dependency_graph": ["artifacts/dependency_graph.yaml"],
21
49
  "fitness_functions": ["artifacts/fitness.yaml"],
22
50
  "rollback": ["artifacts/rollback.yaml"],
51
+ "test_execute": ["artifacts/test_plan.yaml"],
23
52
  "verify": ["artifacts/verify.yaml"],
53
+ "review_swarm": ["artifacts/review.yaml"],
24
54
  "report": ["artifacts/report.md"]
25
55
  },
26
56
  "allowed_path_prefixes": {
27
57
  "run_artifacts": [".cursor/aaac/state/runs/", "aaac/state/runs/"],
28
- "write_article": [".cursor/write-article-runs/"]
58
+ "campaign_artifacts": [".cursor/aaac/state/campaigns/", "aaac/state/campaigns/"]
59
+ },
60
+ "remediation_gate": {
61
+ "script": "verify-remediation-iteration.mjs",
62
+ "remediator_gate_script": "remediator-gate.mjs",
63
+ "debt_sweep_script": "debt-sweep-gate.mjs",
64
+ "satisfaction_loop_script": "satisfaction-loop-gate.mjs",
65
+ "repair_fallow_start_script": "repair-fallow-start-baseline.mjs",
66
+ "bootstrap_autonomous_script": "bootstrap-autonomous.mjs",
67
+ "runner_script": "remediation-runner.mjs",
68
+ "runner_daemon_script": "remediation-runner-daemon.sh",
69
+ "runner_health_script": "runner-health-check.mjs",
70
+ "plan_waves_script": "plan-waves-from-queue.mjs",
71
+ "validate_script": "validate-campaign-complete.mjs",
72
+ "baseline_script": "capture-verify-baseline.mjs",
73
+ "wave_snapshot_script": "capture-wave-snapshot.mjs",
74
+ "classify_fallow_script": "classify-fallow-issues.mjs",
75
+ "record_fallow_fp_script": "record-fallow-fp.mjs",
76
+ "fallow_fp_rules": "fallow-fp-rules.json",
77
+ "classify_script": "classify-verify-failure.mjs",
78
+ "dispatch_rules": "dispatch-rules.json",
79
+ "wave_mode": "wave",
80
+ "debt_mode": "debt",
81
+ "wave_gate_mode": "regression",
82
+ "debt_gate_mode": "strict",
83
+ "campaign_artifact": "artifacts/campaign.json",
84
+ "exit_codes": {
85
+ "promote": 0,
86
+ "block": 1,
87
+ "runtime_error": 2,
88
+ "remediate": 3
89
+ },
90
+ "invariants": {
91
+ "exit_3_is_continue": true,
92
+ "never_block_campaign_on_wave_exit_3": true,
93
+ "satisfaction_exit_3_is_continue_loop": true,
94
+ "fallow_start_baseline_immutable": true,
95
+ "validate_before_report": true
96
+ }
97
+ },
98
+ "phase_artifacts_remediate": {
99
+ "campaign_init": ["artifacts/campaign.json", "artifacts/verify_baseline.json"],
100
+ "scan": [
101
+ "artifacts/fallow_scan.json",
102
+ "artifacts/fallow_dupes.json",
103
+ "artifacts/fallow_health.json",
104
+ "artifacts/fallow_scan_bundle.json",
105
+ "artifacts/fallow_classification.json"
106
+ ],
107
+ "check_swarm": [
108
+ "artifacts/check_synthesis.md",
109
+ "artifacts/dispatch-queue.yaml",
110
+ "artifacts/check_app_validate.yaml",
111
+ "artifacts/check_architecture_fitness.yaml",
112
+ "artifacts/protected_paths.yaml",
113
+ "artifacts/check_swarm_merge.json"
114
+ ],
115
+ "plan_waves": ["artifacts/plan_waves.yaml"],
116
+ "execute": ["artifacts/execute_waves.yaml"],
117
+ "debt_sweep": ["artifacts/debt_sweep.json", "artifacts/verify_debt.json"],
118
+ "satisfaction_gate": ["artifacts/satisfaction.json", "artifacts/satisfaction_loop_gate.json"],
119
+ "report": ["artifacts/report.md"]
29
120
  },
30
121
  "fix_commands": ["fix-module", "fix-bug", "module-fix", "bug-fix"]
31
122
  }
@@ -1,5 +1,6 @@
1
- # Generic AAAC project overlay — verb orchestrators + exception commands only.
2
- # Add domain resolvers, orchestrators, and project skills in your repo after init.
1
+ # Generic AAAC project overlay — copied into consumer repos by `aaac init`.
2
+ # Add `resolvers:` and domain orchestrators when you create `.cursor/domains/<slug>/`.
3
+ # Reference implementation (Lüdecker cms/ui/database): ludecker repo `.cursor/aaac/graph.project.yaml`
3
4
 
4
5
  orchestrators:
5
6
  update-doc:
@@ -30,6 +31,12 @@ orchestrators:
30
31
  path: skills/shared/platform-release/orchestrator
31
32
  requires: [testing, verification, execution, reporting]
32
33
 
34
+ remediate-app:
35
+ path: skills/shared/remediation/orchestrator
36
+ requires: [remediation, discovery, check, execution, testing, verification, reporting]
37
+ check_swarm_skill: skills/shared/remediation/check-swarm
38
+ phases: [campaign_init, scan, check_swarm, plan_waves, execute, debt_sweep, satisfaction_gate, report]
39
+
33
40
  verb-create:
34
41
  path: skills/shared/verbs/create/orchestrator
35
42
  requires: [discovery, investigation-lite, planning, validation, impact-analysis, dependency-graph, fitness-functions, rollback, execution, testing, verification, reporting, module-authoring]
@@ -41,7 +48,7 @@ orchestrators:
41
48
  verb-fix:
42
49
  path: skills/shared/verbs/fix/orchestrator
43
50
  requires: [discovery, investigation, root-cause, planning, validation, impact-analysis, dependency-graph, fitness-functions, rollback, execution, testing, verification, reporting]
44
- phases: [load_inventory, discover, investigate_swarm, root_cause, plan, validate, impact_analysis, dependency_graph, fitness_functions, rollback, execute, verify, sync_inventory, report]
51
+ phases: [load_inventory, discover, investigate_swarm, root_cause, plan, validate, impact_analysis, dependency_graph, fitness_functions, rollback, execute, test_execute, verify, review_swarm, sync_inventory, report]
45
52
 
46
53
  verb-review:
47
54
  path: skills/shared/verbs/review/orchestrator
@@ -72,11 +79,17 @@ skills:
72
79
  execution:
73
80
  path: skills/shared/execution
74
81
  depends: [governance/implementation]
82
+ test-authoring:
83
+ path: skills/shared/test-authoring
84
+ agents: [test-author]
75
85
  testing:
76
86
  path: skills/shared/testing
77
87
  agents: [unit-test-run, fallow-check-changed, fix-repro-verify]
78
88
  verification:
79
89
  path: skills/shared/verification
90
+ implementation-review:
91
+ path: skills/shared/implementation-review
92
+ agents: [boundary-review, doc-conformance, implementation-review]
80
93
  reporting:
81
94
  path: skills/shared/reporting
82
95
  architecture:
@@ -136,6 +149,10 @@ skills:
136
149
  path: skills/shared/module-authoring
137
150
  platform-release:
138
151
  path: skills/shared/platform-release
152
+ remediation:
153
+ path: skills/shared/remediation
154
+ remediation-check-swarm:
155
+ path: skills/shared/remediation/check-swarm
139
156
  governance/implementation:
140
157
  path: skills/shared/governance/implementation
141
158
 
@@ -182,14 +199,36 @@ agents:
182
199
  path: agents/fix-repro-verify.md
183
200
  fix-hypothesis-validate:
184
201
  path: agents/fix-hypothesis-validate.md
202
+ test-author:
203
+ path: agents/test-author.md
204
+ doc-conformance:
205
+ path: agents/doc-conformance.md
206
+ implementation-review:
207
+ path: agents/implementation-review.md
185
208
  release-git:
186
209
  path: agents/release-git.md
187
210
  wave: 1
188
211
  blocking: true
212
+ remediation-check-app-inventory:
213
+ path: agents/remediation-check-app-inventory.md
214
+ remediation-check-app-ssot:
215
+ path: agents/remediation-check-app-ssot.md
216
+ remediation-check-app-trace:
217
+ path: agents/remediation-check-app-trace.md
218
+ remediation-check-architecture-boundaries:
219
+ path: agents/remediation-check-architecture-boundaries.md
220
+ remediation-check-architecture-deps:
221
+ path: agents/remediation-check-architecture-deps.md
222
+ remediation-check-architecture-decomposition:
223
+ path: agents/remediation-check-architecture-decomposition.md
224
+ remediation-check-risk:
225
+ path: agents/remediation-check-risk.md
226
+ remediation-remediator:
227
+ path: agents/remediation-remediator.md
228
+ remediation-e2e-gate:
229
+ path: agents/remediation-e2e-gate.md
189
230
 
190
231
  policies:
191
232
  - policies/master-rules.md
192
- - policies/project-context.md
193
- - policies/ui-design.md
194
233
  - policies/implementation.md
195
234
  - policies/mcp-and-deploy.md
@@ -8,7 +8,9 @@
8
8
  "investigate_lite",
9
9
  "plan",
10
10
  "execute",
11
+ "test_execute",
11
12
  "verify",
13
+ "review_swarm",
12
14
  "report"
13
15
  ],
14
16
  "gate_stack": "pre_execute"
@@ -19,7 +21,9 @@
19
21
  "investigate_lite",
20
22
  "plan",
21
23
  "execute",
24
+ "test_execute",
22
25
  "verify",
26
+ "review_swarm",
23
27
  "report"
24
28
  ],
25
29
  "gate_stack": "pre_execute"
@@ -31,7 +35,9 @@
31
35
  "root_cause",
32
36
  "plan",
33
37
  "execute",
38
+ "test_execute",
34
39
  "verify",
40
+ "review_swarm",
35
41
  "report"
36
42
  ],
37
43
  "gate_stack": "pre_execute"
@@ -58,7 +64,9 @@
58
64
  "investigate_lite",
59
65
  "plan",
60
66
  "execute",
67
+ "test_execute",
61
68
  "verify",
69
+ "review_swarm",
62
70
  "report"
63
71
  ],
64
72
  "gate_stack": "pre_execute"
@@ -96,7 +104,9 @@
96
104
  "root_cause",
97
105
  "plan",
98
106
  "execute",
107
+ "test_execute",
99
108
  "verify",
109
+ "review_swarm",
100
110
  "report"
101
111
  ],
102
112
  "gate_stack": "pre_execute"
@@ -109,10 +119,26 @@
109
119
  "root_cause",
110
120
  "plan",
111
121
  "execute",
122
+ "test_execute",
112
123
  "verify",
124
+ "review_swarm",
113
125
  "report"
114
126
  ],
115
127
  "gate_stack": "pre_execute"
128
+ },
129
+ "remediate-app": {
130
+ "description": "Long-running remediation campaign — Fallow scan, check swarm, fix waves, debt sweep, satisfaction loop",
131
+ "work_phases": [
132
+ "campaign_init",
133
+ "scan",
134
+ "check_swarm",
135
+ "plan_waves",
136
+ "execute",
137
+ "debt_sweep",
138
+ "satisfaction_gate",
139
+ "report"
140
+ ],
141
+ "gate_stack": null
116
142
  }
117
143
  }
118
144
  }
@@ -14,7 +14,15 @@
14
14
  "fitness_functions": { "skill": "fitness-functions", "gate": true },
15
15
  "rollback": { "skill": "rollback", "gate": true },
16
16
  "execute": { "skill": "execution" },
17
+ "test_execute": { "skill": "test-authoring" },
17
18
  "verify": { "skills": ["testing", "verification"] },
18
- "report": { "skill": "reporting" }
19
+ "review_swarm": { "skill": "implementation-review", "readonly": true },
20
+ "report": { "skill": "reporting" },
21
+ "campaign_init": { "skill": "remediation", "readonly": true },
22
+ "scan": { "skill": "remediation", "readonly": true },
23
+ "check_swarm": { "skill": "check", "readonly": true },
24
+ "plan_waves": { "skill": "planning", "readonly": true },
25
+ "debt_sweep": { "skill": "remediation" },
26
+ "satisfaction_gate": { "skill": "remediation", "readonly": true }
19
27
  }
20
28
  }
@@ -180,6 +180,7 @@
180
180
  "review-incident": { "orchestrator": "review-incident" },
181
181
  "test-function": { "orchestrator": "test-function" },
182
182
  "release-app": { "orchestrator": "release-app" },
183
+ "remediate-app": { "orchestrator": "remediate-app", "object": "app" },
183
184
  "module-update": { "alias": "update-module" },
184
185
  "update-doc": { "alias": "update-architecture" },
185
186
  "architecture": { "alias": "update-architecture" },
@@ -2,5 +2,41 @@
2
2
  "manual_commands": [],
3
3
  "verify": {
4
4
  "enabled": false
5
+ },
6
+ "remediation": {
7
+ "fallow_cwd": ".",
8
+ "scan_root": ".",
9
+ "verify": {
10
+ "layers": [
11
+ {
12
+ "id": "typecheck",
13
+ "command": "npm",
14
+ "args": ["run", "typecheck"],
15
+ "cwd": ".",
16
+ "optional": true
17
+ },
18
+ {
19
+ "id": "vitest",
20
+ "command": "npm",
21
+ "args": ["test"],
22
+ "cwd": ".",
23
+ "optional": true
24
+ },
25
+ {
26
+ "id": "build",
27
+ "command": "npm",
28
+ "args": ["run", "build"],
29
+ "cwd": ".",
30
+ "optional": true
31
+ }
32
+ ],
33
+ "playwright": {
34
+ "enabled": false
35
+ },
36
+ "dev_server": {
37
+ "url": "http://localhost:3000",
38
+ "launch_hint": "Start your dev server before debt sweep / Playwright gates."
39
+ }
40
+ }
5
41
  }
6
42
  }
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Synthesize check-swarm-raw.json from Fallow health targets (scriptable check_swarm).
4
+ */
5
+ import fs from "fs";
6
+ import path from "path";
7
+ import { isoNow } from "../run-engine/lib.mjs";
8
+ import { campaignDir, iterDir } from "./lib/runner-state.mjs";
9
+ import { loadCampaignContext } from "./lib/campaign-focus.mjs";
10
+ import {
11
+ fetchHealthTargets,
12
+ filterTargetsForWaves,
13
+ } from "./lib/fallow-health-targets.mjs";
14
+
15
+ const AGENT_IDS = [
16
+ "remediation-check-app-inventory",
17
+ "remediation-check-app-ssot",
18
+ "remediation-check-app-trace",
19
+ "remediation-check-architecture-boundaries",
20
+ "remediation-check-architecture-deps",
21
+ "remediation-check-architecture-decomposition",
22
+ "remediation-check-risk",
23
+ ];
24
+
25
+ function parseArgs(argv) {
26
+ const out = { campaignId: null, iteration: 0 };
27
+ for (let i = 0; i < argv.length; i++) {
28
+ if (argv[i] === "--campaign-id") out.campaignId = argv[++i];
29
+ else if (argv[i] === "--iteration") out.iteration = Number(argv[++i]);
30
+ }
31
+ return out;
32
+ }
33
+
34
+ const args = parseArgs(process.argv.slice(2));
35
+ if (!args.campaignId) {
36
+ console.error("--campaign-id required");
37
+ process.exit(2);
38
+ }
39
+
40
+ const ctx = loadCampaignContext(args.campaignId);
41
+ const { targets, score } = fetchHealthTargets({ scope: ctx.scope, limit: 15 });
42
+ const filtered = filterTargetsForWaves(targets, {
43
+ protected_paths: ctx.protected_paths,
44
+ defer_high_fan_in: ctx.focus.defer_high_fan_in,
45
+ });
46
+
47
+ const safeToFix = filtered.slice(0, 8).map((t) => ({
48
+ path: t.path,
49
+ category: "health_decompose",
50
+ evidence: t.recommendation ?? null,
51
+ }));
52
+
53
+ const baseFinding = `health ${score ?? "?"}; focus=${ctx.focus.health_functions_above_60_loc ? "functions>60LOC" : "general"}`;
54
+
55
+ const agents = AGENT_IDS.map((agent_id) => ({
56
+ agent_id,
57
+ command_mirror: agent_id.includes("risk") ? "check-risk" : agent_id.includes("architecture") ? "check-architecture" : "check-app",
58
+ answer: "partial",
59
+ confidence: "high",
60
+ false_positives: [],
61
+ protected_paths: ctx.protected_paths,
62
+ do_not_delete: ctx.protected_paths.map((p) => ({ path: p, reason: "protected" })),
63
+ safe_to_fix: safeToFix,
64
+ findings: [baseFinding, `auto-synthesis iter ${args.iteration}`],
65
+ gaps: [],
66
+ }));
67
+
68
+ const outPath = path.join(iterDir(args.campaignId, args.iteration), "check-swarm-raw.json");
69
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
70
+ fs.writeFileSync(
71
+ outPath,
72
+ JSON.stringify({ merged_at: isoNow(), iteration: args.iteration, focus: ctx.focus, agents }, null, 2),
73
+ );
74
+
75
+ console.log(JSON.stringify({ ok: true, path: outPath, agents: agents.length, safe_to_fix: safeToFix.length }));