@williambeto/ai-workflow 2.9.2 โ†’ 2.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  ## [unreleased]
2
2
 
3
+ ## [2.9.4] - 2026-07-16
4
+
5
+ ### ๐Ÿ›ก๏ธ Hardening
6
+
7
+ - Add an opt-in repository-local pre-push hook that rejects direct updates to
8
+ `main` and `master` without changing the published consumer payload
9
+ - Refresh development-only lockfile dependencies to remove known production,
10
+ moderate, high, and critical audit findings
11
+
12
+ ### ๐Ÿงช Testing
13
+
14
+ - Add stable contract coverage for documentation integrity, protected-branch
15
+ pushes, finalizer change detection, and validation-result precedence
16
+ - Verify that the public tarball excludes contributor hooks, internal
17
+ validators, tests, and generated evidence
18
+
19
+ ### ๐Ÿ“š Documentation
20
+
21
+ - Align the README with the canonical AI Workflow Kit product promise,
22
+ installed paths, agent roles, and the actual CLI enforcement boundary
23
+
24
+ ## [2.9.3] - 2026-07-16
25
+
26
+ ### ๐Ÿ› Bug Fixes
27
+
28
+ - Restore scoped specialist delegation for every core AIWK agent without
29
+ reintroducing `bash` or `edit` approval prompts
30
+ - Allow Atlas to reach both workflow agents and all registered specialists
31
+ while preventing specialists from delegating recursively
32
+ - Set OpenCode's bounded subagent depth to two so workflow agents delegated by
33
+ Atlas can still consult one specialist
34
+ - Detect stale or incomplete specialist routing through `ai-workflow doctor`
35
+
36
+ ### ๐Ÿงช Testing
37
+
38
+ - Cover the complete six-caller by twenty-specialist routing matrix
39
+ - Verify upgrades from permission-free `2.9.2` configurations and reject
40
+ recursive specialist delegation
41
+ - Exercise Atlas to workflow-agent to specialist routing in a real OpenCode
42
+ runtime smoke test
43
+
3
44
  ## [2.9.2] - 2026-07-16
4
45
 
5
46
  ### ๐Ÿ› Bug Fixes
package/README.md CHANGED
@@ -15,20 +15,22 @@
15
15
 
16
16
  ## What is AI Workflow Kit?
17
17
 
18
- AI Workflow Kit (AIWK) is an **npm CLI** you install in your project that makes AI-assisted software delivery **safe, structured, and verifiable**.
18
+ AI Workflow is an npm CLI that installs agents, commands, skills, policies and templates into your repository. It guides coding agents from request to implementation, validation and evidence.
19
19
 
20
- It works with [OpenCode](https://opencode.ai) to turn a natural language request into a full delivery โ€” with branch protection, specialist agent delegation, automated validation, and a persisted evidence log.
20
+ AI Workflow Kit preserves workflow integrity so coding agents cannot skip from request to code to success without an explicit implementation path, proportional validation, and final evidence.
21
+
22
+ It works with [OpenCode](https://opencode.ai) to turn a natural language request into a proportionate delivery โ€” with branch isolation, optional specialist analysis, observed validation, and evidence appropriate to the task risk.
21
23
 
22
24
  **Without AIWK**, a coding agent receives a request, writes code, and reports success. There is no proof, no branch isolation, and no guarantee that tests passed.
23
25
 
24
26
  **With AIWK**, the same request travels through a mandatory workflow:
25
27
 
26
28
  ```
27
- Your request โ†’ Classification โ†’ Branch Gate โ†’ Specialist Agent
28
- โ†’ Automated Validation โ†’ Evidence โ†’ Handoff
29
+ Your request โ†’ Classification โ†’ Branch Gate โ†’ Workflow Owner
30
+ โ†’ Observed Validation โ†’ Evidence โ†’ Handoff
29
31
  ```
30
32
 
31
- No step can be skipped. No claim of success is made without proof.
33
+ Within the `ai-workflow execute` control plane, every stage is evaluated and a successful final state requires observed validation. Direct model chat remains subject to runtime capabilities; see the [runtime compatibility matrix](dist-assets/docs/compatibility/runtime-matrix.md).
32
34
 
33
35
  ---
34
36
 
@@ -47,7 +49,7 @@ AI Workflow Kit enforces a contract: **the agent must earn the right to deliver.
47
49
 
48
50
  ## How it works
49
51
 
50
- AIWK installs a structured team of 6 specialist agents into your repository. Each agent has a defined role, a permission boundary, and cannot claim work that belongs to another.
52
+ AIWK installs a structured team of 6 core workflow agents into your repository. Each agent has a defined role and ownership boundary. Any core agent may request bounded analysis from a registered specialist when that improves the result, while retaining ownership of its workflow stage.
51
53
 
52
54
  When you run `npx aw execute "your task"`, Atlas (the coordinator) takes over:
53
55
 
@@ -59,7 +61,7 @@ When you run `npx aw execute "your task"`, Atlas (the coordinator) takes over:
59
61
  | **4. Implement** | Astra | Implements the change on the feature branch |
60
62
  | **5. Validate** | Sage | Runs tests, accessibility checks, visual regression โ€” writes evidence |
61
63
  | **6. Remediate** | Phoenix | If validation fails, Phoenix heals within a bounded attempt limit |
62
- | **7. Evidence** | Atlas | Saves `EVIDENCE.json` + `HANDOFF-<task>.md` to `.ai-workflow/` |
64
+ | **7. Evidence** | Atlas | Saves the handoff and ledger; persists `EVIDENCE.json` when the evidence policy requires it |
63
65
 
64
66
  > **Proportional by design.** A typo fix in a README gets 1 remediation attempt and no spec. A payment integration gets 3 attempts, a required SDD, and mandatory persisted evidence. The kit calibrates automatically.
65
67
 
@@ -100,7 +102,7 @@ This creates the `.ai-workflow/` directory and installs 6 agents, 25 skills, and
100
102
  npx aw execute "Add a health check endpoint returning HTTP 200"
101
103
  ```
102
104
 
103
- Atlas classifies the request, creates a branch, delegates to Astra, validates with Sage, and writes evidence โ€” all automatically.
105
+ Atlas classifies the request, the branch gate establishes a safe branch, Astra owns requested changes, and validation and evidence run proportionally.
104
106
 
105
107
  ### 4. Check the evidence
106
108
 
@@ -134,7 +136,7 @@ Each agent has a fixed role and cannot exceed its operational boundary.
134
136
  | ๐Ÿงช **Sage** | Validator | Audits changes, runs quality gates, writes verifiable evidence |
135
137
  | ๐Ÿ”ง **Phoenix** | Recovery | Heals broken states within a bounded remediation limit |
136
138
 
137
- Agents are installed as prompts in your `.ai-workflow/agents/` directory. You can read, audit, or customise them.
139
+ Agents are installed as prompts in your `.ai-workflow/opencode/agents/` directory. You can read, audit, or customise them.
138
140
 
139
141
  ---
140
142
 
@@ -170,15 +172,22 @@ You don't configure this. The kit reads your request and calibrates automaticall
170
172
 
171
173
  Running `npx aw init` writes the following into your repository:
172
174
 
175
+ The canonical OpenCode runtime paths are `.ai-workflow/opencode/agents/`, `.ai-workflow/opencode/commands/`, `.ai-workflow/opencode/skills/`, and `.ai-workflow/opencode/docs/`.
176
+
173
177
  ```
174
178
  .ai-workflow/
175
- โ”œโ”€โ”€ agents/ # Atlas, Nexus, Orion, Astra, Sage, Phoenix prompts
176
- โ”œโ”€โ”€ commands/ # Slash commands for your AI IDE
177
- โ”œโ”€โ”€ skills/ # 25 domain skills (architecture, security, database, ...)
179
+ โ”œโ”€โ”€ opencode/
180
+ โ”‚ โ”œโ”€โ”€ agents/ # Atlas, Nexus, Orion, Astra, Sage, Phoenix prompts
181
+ โ”‚ โ”œโ”€โ”€ commands/ # Slash commands for OpenCode
182
+ โ”‚ โ”œโ”€โ”€ skills/ # Domain skills (architecture, security, database, ...)
183
+ โ”‚ โ””โ”€โ”€ docs/ # Runtime policies, profiles, references, and guides
184
+ โ”œโ”€โ”€ harness/ # Workflow and handoff harness
185
+ โ”œโ”€โ”€ schemas/ # Evidence and workflow schemas
178
186
  โ”œโ”€โ”€ templates/ # Specification and handoff templates
179
- โ”œโ”€โ”€ policies/ # Branch gate, quality gate, merge gate policies
180
- โ”œโ”€โ”€ history/ # Ledger of every workflow execution
181
- โ””โ”€โ”€ handoffs/ # HANDOFF-<task>.md for every completed delivery
187
+ โ”œโ”€โ”€ history/ # Runtime-generated workflow ledgers
188
+ โ””โ”€โ”€ handoffs/ # Runtime-generated delivery handoffs
189
+ AGENTS.md # Project-local contributor contract
190
+ QUICKSTART.md # Installed quickstart
182
191
  opencode.jsonc # OpenCode runtime configuration
183
192
  ```
184
193
 
@@ -188,8 +197,8 @@ Everything is plain text โ€” readable, auditable, and version-controlled.
188
197
 
189
198
  ## Safety Guarantees
190
199
 
191
- - **Branch protection**: execution is always blocked on `main`/`master`. A feature branch is created automatically.
192
- - **Read-only confinement**: tasks classified as read-only are cryptographically verified โ€” any file mutation blocks the execution.
200
+ - **Branch gate**: write-mode execution is blocked on `main`/`master`. A feature branch is created automatically when the worktree is clean.
201
+ - **Read-only confinement**: tasks classified as read-only compare SHA-256 workspace snapshots before and after execution; any observed mutation blocks completion.
193
202
  - **Bounded remediation**: Phoenix is limited to N attempts. The kit never loops indefinitely.
194
203
  - **Mandatory handoff**: every write-mode execution produces a `HANDOFF-<task>.md` with evidence, diff, and status โ€” regardless of risk level.
195
204
  - **Schema-validated evidence**: `EVIDENCE.json` is validated against a strict Ajv schema. Path traversal and shell injection are blocked.
@@ -231,12 +240,12 @@ Beyond the 6 core agents, AIWK ships 25 domain skills that agents activate as co
231
240
 
232
241
  ## Contributing
233
242
 
234
- AIWK uses itself to manage its own development. To contribute:
243
+ This development repository follows the AIWK contributor contract directly without installing consumer runtime assets into itself. To contribute:
235
244
 
236
245
  ```
237
246
  src/ TypeScript source (CLI + Core)
238
247
  dist-assets/ Templates, agents, skills, schemas installed into consumer repos
239
- tests/ Unit (296 tests) and E2E (19 tests) suites
248
+ tests/ Unit, contract, linting, and E2E suites
240
249
  internal/ Validation pipelines and release scripts
241
250
  docs/ Guides, ADRs, specs, and release notes
242
251
  ```
@@ -249,6 +258,14 @@ npm run validate
249
258
 
250
259
  All 23 quality gates must pass.
251
260
 
261
+ Contributors without server-side branch protection can enable the repository's local push safeguard explicitly:
262
+
263
+ ```bash
264
+ npm run setup:hooks
265
+ ```
266
+
267
+ The hook blocks pushes targeting `main` or `master` and allows maintenance or feature branches. It prevents accidents but is not a server-side security boundary and can be bypassed with Git's `--no-verify` option.
268
+
252
269
  ---
253
270
 
254
271
  ## License
@@ -761,6 +761,58 @@ var SUBAGENTS = {
761
761
  "Technical-Leader": { description: "Capability only: analyze technical decisions, architecture, and trade-offs", skill: "technical-leadership" },
762
762
  "UI-UX-Engineer": { description: "Capability only: review usability and interface clarity", skill: "ui-ux-design" }
763
763
  };
764
+ var CORE_AGENT_NAMES = Object.freeze(Object.keys(AGENTS));
765
+ var SPECIALIST_AGENT_NAMES = Object.freeze(Object.keys(SUBAGENTS));
766
+ var MIN_SUBAGENT_DEPTH = 2;
767
+ function inspectSpecialistRoutingConfig(opencodeConfig) {
768
+ const errors = [];
769
+ const warnings = [];
770
+ const agents = opencodeConfig?.agent ?? {};
771
+ if (typeof opencodeConfig?.subagent_depth !== "number" || opencodeConfig.subagent_depth < MIN_SUBAGENT_DEPTH) {
772
+ errors.push(`OpenCode subagent_depth must be at least ${MIN_SUBAGENT_DEPTH} for workflow-agent to specialist routing`);
773
+ }
774
+ for (const specialist of SPECIALIST_AGENT_NAMES) {
775
+ if (agents[specialist]?.mode !== "subagent") {
776
+ errors.push(`specialist missing or not configured as subagent: ${specialist}`);
777
+ }
778
+ if (agents[specialist]?.permission?.task !== void 0) {
779
+ errors.push(`specialist must not delegate recursively: ${specialist}`);
780
+ }
781
+ }
782
+ for (const caller of CORE_AGENT_NAMES) {
783
+ const taskPermissions = agents[caller]?.permission?.task;
784
+ if (!taskPermissions || typeof taskPermissions !== "object" || Array.isArray(taskPermissions)) {
785
+ errors.push(`core agent lacks explicit specialist task routing: ${caller}`);
786
+ continue;
787
+ }
788
+ if (taskPermissions["*"] !== "deny") {
789
+ errors.push(`core agent task routing must deny unspecified targets: ${caller}`);
790
+ }
791
+ if (Object.values(taskPermissions).includes("ask")) {
792
+ errors.push(`core agent task routing must not request approval: ${caller}`);
793
+ }
794
+ const blockedSpecialists = SPECIALIST_AGENT_NAMES.filter((specialist) => taskPermissions[specialist] !== "allow");
795
+ if (blockedSpecialists.length > 0) {
796
+ errors.push(`core agent cannot reach all specialists: ${caller} (${blockedSpecialists.join(", ")})`);
797
+ }
798
+ const otherCoreAgents = CORE_AGENT_NAMES.filter((name) => name !== caller);
799
+ if (caller === "Atlas") {
800
+ const blockedCoreAgents = otherCoreAgents.filter((name) => taskPermissions[name] !== "allow");
801
+ if (blockedCoreAgents.length > 0) {
802
+ errors.push(`Atlas cannot reach all workflow agents: ${blockedCoreAgents.join(", ")}`);
803
+ }
804
+ } else {
805
+ const recursiveCoreAgents = otherCoreAgents.filter((name) => taskPermissions[name] === "allow");
806
+ if (recursiveCoreAgents.length > 0) {
807
+ errors.push(`non-Atlas core agent can recursively delegate workflow ownership: ${caller} (${recursiveCoreAgents.join(", ")})`);
808
+ }
809
+ }
810
+ }
811
+ if (opencodeConfig?.permission?.task !== void 0) {
812
+ warnings.push("consumer-level permission.task may override AIWK specialist routing or enable recursive delegation");
813
+ }
814
+ return { valid: errors.length === 0, errors, warnings };
815
+ }
764
816
  var COMMANDS = {
765
817
  atlas: { description: "Decide safest next step and delegate to the appropriate workflow or agent", agent: "Atlas" },
766
818
  run: { description: "Execute the master orchestration pipeline (Gates, SDD, Implementation, Validation, Healing)", agent: "Atlas" },
@@ -779,11 +831,23 @@ var COMMANDS = {
779
831
  };
780
832
  function buildManagedConfig() {
781
833
  const agent = {};
834
+ const specialistTaskPermissions = Object.fromEntries([
835
+ ["*", "deny"],
836
+ ...SPECIALIST_AGENT_NAMES.map((name) => [name, "allow"])
837
+ ]);
838
+ const atlasTaskPermissions = Object.fromEntries([
839
+ ["*", "deny"],
840
+ ...CORE_AGENT_NAMES.filter((name) => name !== "Atlas").map((name) => [name, "allow"]),
841
+ ...SPECIALIST_AGENT_NAMES.map((name) => [name, "allow"])
842
+ ]);
782
843
  for (const [name, def] of Object.entries(AGENTS)) {
783
844
  agent[name] = {
784
845
  mode: def.mode,
785
846
  description: def.description,
786
- prompt: `{file:./.ai-workflow/opencode/agents/${name.toLowerCase()}.md}`
847
+ prompt: `{file:./.ai-workflow/opencode/agents/${name.toLowerCase()}.md}`,
848
+ permission: {
849
+ task: name === "Atlas" ? atlasTaskPermissions : specialistTaskPermissions
850
+ }
787
851
  };
788
852
  }
789
853
  for (const [name, def] of Object.entries(SUBAGENTS)) {
@@ -804,6 +868,7 @@ function buildManagedConfig() {
804
868
  return {
805
869
  $schema: "https://opencode.ai/config.json",
806
870
  default_agent: "Atlas",
871
+ subagent_depth: MIN_SUBAGENT_DEPTH,
807
872
  agent,
808
873
  skills: {
809
874
  paths: ["./.ai-workflow/opencode/skills"]
@@ -839,6 +904,7 @@ async function mergeOpencodeConfig(cwd, { force = false, backupRoot = ".ai-workf
839
904
  const next = {
840
905
  ...currentWithoutLegacy,
841
906
  $schema: current.$schema ?? managed.$schema,
907
+ subagent_depth: typeof current.subagent_depth === "number" ? Math.max(current.subagent_depth, managed.subagent_depth) : managed.subagent_depth,
842
908
  ...managed.mcp ? {
843
909
  mcp: {
844
910
  ...current.mcp ?? {},
@@ -1988,6 +2054,18 @@ async function checkOpencodeJson(cwd, state) {
1988
2054
  console.log(`FAIL opencode agent entries missing: ${missingAgents.join(", ")}`);
1989
2055
  }
1990
2056
  }
2057
+ const specialistRouting = inspectSpecialistRoutingConfig(opencodeConfig);
2058
+ if (specialistRouting.valid) {
2059
+ console.log(`PASS OpenCode specialist routing available (${CORE_AGENT_NAMES.length} callers, ${SPECIALIST_AGENT_NAMES.length} specialists)`);
2060
+ } else {
2061
+ state.hasWarning = true;
2062
+ for (const error of specialistRouting.errors) console.log(`WARN ${error}`);
2063
+ console.log("WARN specialist routing is stale or incomplete; rerun `ai-workflow init --yes --no-install`");
2064
+ }
2065
+ for (const warning of specialistRouting.warnings) {
2066
+ state.hasWarning = true;
2067
+ console.log(`WARN ${warning}`);
2068
+ }
1991
2069
  } catch {
1992
2070
  state.hasFailure = true;
1993
2071
  console.log("FAIL opencode.jsonc is not valid JSONC");