@windyroad/architect 0.17.3-preview.755 → 0.17.3-preview.766

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.
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "wr-architect",
3
+ "version": "0.17.3",
4
+ "description": "Architecture decision enforcement for AI coding agents",
5
+ "author": {
6
+ "name": "Windy Road Technology",
7
+ "url": "https://windyroad.com.au"
8
+ },
9
+ "homepage": "https://github.com/windyroad/agent-plugins/tree/main/packages/architect",
10
+ "repository": "https://github.com/windyroad/agent-plugins",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "architecture",
14
+ "adr",
15
+ "decisions",
16
+ "governance",
17
+ "codex",
18
+ "claude-code"
19
+ ],
20
+ "skills": "./skills/",
21
+ "interface": {
22
+ "displayName": "Windy Road Architect",
23
+ "shortDescription": "Review changes against architecture decisions",
24
+ "longDescription": "Architecture decision enforcement for AI coding agents. Create ADRs, review recorded decisions, and check proposed changes against docs/decisions/.",
25
+ "developerName": "Windy Road Technology",
26
+ "category": "Developer Tools",
27
+ "capabilities": [
28
+ "Interactive",
29
+ "Read",
30
+ "Write"
31
+ ],
32
+ "websiteURL": "https://windyroad.com.au",
33
+ "privacyPolicyURL": "https://windyroad.com.au/privacy",
34
+ "termsOfServiceURL": "https://windyroad.com.au/terms",
35
+ "defaultPrompt": [
36
+ "Review this change against the architecture decisions",
37
+ "Create an ADR for this design decision",
38
+ "Review decisions that lack human oversight"
39
+ ],
40
+ "brandColor": "#0F766E",
41
+ "screenshots": []
42
+ }
43
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "type": "object",
3
+ "additionalProperties": false,
4
+ "required": [
5
+ "pass",
6
+ "score",
7
+ "reason"
8
+ ],
9
+ "properties": {
10
+ "pass": {
11
+ "type": "boolean"
12
+ },
13
+ "score": {
14
+ "type": "number",
15
+ "minimum": 0,
16
+ "maximum": 1
17
+ },
18
+ "reason": {
19
+ "type": "string"
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)"
6
+ SCHEMA="${SCRIPT_DIR}/codex-rubric-output.schema.json"
7
+ PROMPT="${*:-}"
8
+
9
+ if [[ -z "$PROMPT" ]]; then
10
+ echo "grade-codex-rubric.sh: rubric prompt argument is required" >&2
11
+ exit 2
12
+ fi
13
+
14
+ raw="$(
15
+ codex exec \
16
+ --ephemeral \
17
+ --cd "$REPO_ROOT" \
18
+ -c 'approval_policy="never"' \
19
+ --sandbox read-only \
20
+ --output-schema "$SCHEMA" \
21
+ "You are a strict grading assistant. Respond only with JSON matching the provided schema. Grade this promptfoo rubric literally.
22
+
23
+ ${PROMPT}"
24
+ )"
25
+
26
+ printf '%s' "$raw" | awk '
27
+ BEGIN { depth = 0; started = 0 }
28
+ {
29
+ line = $0
30
+ for (i = 1; i <= length(line); i++) {
31
+ c = substr(line, i, 1)
32
+ if (c == "{") { depth++; started = 1 }
33
+ if (started) { buf = buf c }
34
+ if (c == "}") { depth--; if (depth == 0 && started) { print buf; exit } }
35
+ }
36
+ if (started) { buf = buf "\n" }
37
+ }
38
+ END { if (started && depth != 0) print buf }
39
+ ' || printf '%s' "$raw"
@@ -0,0 +1,56 @@
1
+ description: |
2
+ Codex wr-architect agent verdict eval. Exercises the generated
3
+ .codex/agents/wr-architect.toml path and the Codex plugin install surface.
4
+
5
+ providers:
6
+ - id: 'exec:bash ./run-codex-agent-eval.sh'
7
+
8
+ defaultTest:
9
+ options:
10
+ provider:
11
+ id: 'exec:bash ./grade-codex-rubric.sh'
12
+
13
+ prompts:
14
+ - '{{prompt}}'
15
+
16
+ tests:
17
+ - description: PASS for aligned pre-edit proposal
18
+ vars:
19
+ prompt: |
20
+ PRE-EDIT review: proposed change updates comments only. No
21
+ architecture-bearing files, dependencies, hooks, workflows, or ADRs
22
+ change. Return the architect verdict.
23
+ assert:
24
+ - type: regex
25
+ value: 'Architecture Review:\s*PASS|PASS'
26
+
27
+ - description: ISSUES FOUND for undocumented dependency
28
+ vars:
29
+ prompt: |
30
+ PRE-EDIT review: proposed change adds a new npm dependency named
31
+ fast-queue to package.json for core task scheduling. No existing ADR
32
+ covers this dependency choice. Return the architect verdict.
33
+ assert:
34
+ - type: regex
35
+ value: 'ISSUES FOUND|Undocumented Decision|new decision'
36
+
37
+ - description: NEEDS DIRECTION when viable options are unpinned
38
+ vars:
39
+ prompt: |
40
+ PRE-EDIT review: proposed change must choose whether plugin
41
+ distribution uses a remote marketplace only or also a repo-local
42
+ marketplace, and the prompt does not pin a direction. Return the
43
+ architect verdict.
44
+ assert:
45
+ - type: regex
46
+ value: 'NEEDS DIRECTION'
47
+
48
+ - description: Unratified Dependency flags unconfirmed ADR dependency
49
+ vars:
50
+ prompt: |
51
+ PRE-EDIT review: proposed change explicitly implements ADR-074, but
52
+ the ADR frontmatter lacks human-oversight: confirmed. Return the
53
+ architect verdict and action.
54
+ assert:
55
+ - type: regex
56
+ value: 'Unratified Dependency|ratify|review-decisions'
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+ # Codex promptfoo exec-provider driver for the generated wr-architect agent.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)"
7
+ MARKETPLACE_DIR="$REPO_ROOT"
8
+ PROMPT="${*:-}"
9
+
10
+ if [[ -z "$PROMPT" ]]; then
11
+ echo "run-codex-agent-eval.sh: prompt argument is required" >&2
12
+ exit 2
13
+ fi
14
+
15
+ SOURCE_CODEX_HOME="${CODEX_HOME:-${HOME}/.codex}"
16
+ TMP_CODEX_HOME=""
17
+
18
+ if [[ -n "${WR_CODEX_EVAL_CODEX_HOME:-}" ]]; then
19
+ export CODEX_HOME="$WR_CODEX_EVAL_CODEX_HOME"
20
+ mkdir -p "$CODEX_HOME"
21
+ else
22
+ TMP_CODEX_HOME="$(mktemp -d)"
23
+ chmod 700 "$TMP_CODEX_HOME"
24
+ export CODEX_HOME="$TMP_CODEX_HOME"
25
+ if [[ -f "${SOURCE_CODEX_HOME}/auth.json" ]]; then
26
+ cp "${SOURCE_CODEX_HOME}/auth.json" "$CODEX_HOME/auth.json"
27
+ chmod 600 "$CODEX_HOME/auth.json"
28
+ fi
29
+ if [[ "${WR_CODEX_EVAL_COPY_CONFIG:-0}" == "1" && -f "${SOURCE_CODEX_HOME}/config.toml" ]]; then
30
+ cp "${SOURCE_CODEX_HOME}/config.toml" "$CODEX_HOME/config.toml"
31
+ chmod 600 "$CODEX_HOME/config.toml"
32
+ fi
33
+ trap 'rm -rf "$TMP_CODEX_HOME"' EXIT
34
+ fi
35
+
36
+ codex plugin marketplace add "$MARKETPLACE_DIR" >/dev/null
37
+ codex plugin add wr-architect@windyroad-local >/dev/null
38
+
39
+ exec codex exec \
40
+ --ephemeral \
41
+ --cd "$REPO_ROOT" \
42
+ -c 'approval_policy="never"' \
43
+ --sandbox read-only \
44
+ --dangerously-bypass-hook-trust \
45
+ "Spawn the custom collaborator agent named wr-architect:agent (auto-discovered by Codex from the installed wr-architect plugin's agents/agent.md). If this non-interactive harness cannot spawn the custom agent directly, read .codex/agents/wr-architect.toml and perform the same review inline.
46
+
47
+ ${PROMPT}"
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bats
2
+
3
+ setup() {
4
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
5
+ EVAL_DIR="$REPO_ROOT/packages/architect/agents/eval"
6
+ }
7
+
8
+ @test "architect Codex agent eval covers required verdict classes" {
9
+ [ -f "$EVAL_DIR/promptfooconfig.codex.yaml" ]
10
+ run grep -n "PASS" "$EVAL_DIR/promptfooconfig.codex.yaml"
11
+ [ "$status" -eq 0 ]
12
+ run grep -n "ISSUES FOUND" "$EVAL_DIR/promptfooconfig.codex.yaml"
13
+ [ "$status" -eq 0 ]
14
+ run grep -n "NEEDS DIRECTION" "$EVAL_DIR/promptfooconfig.codex.yaml"
15
+ [ "$status" -eq 0 ]
16
+ run grep -n "Unratified Dependency" "$EVAL_DIR/promptfooconfig.codex.yaml"
17
+ [ "$status" -eq 0 ]
18
+ }
19
+
20
+ @test "architect Codex agent eval runner uses codex exec and local plugin install" {
21
+ run grep -n "codex plugin marketplace add" "$EVAL_DIR/run-codex-agent-eval.sh"
22
+ [ "$status" -eq 0 ]
23
+ run grep -n "codex plugin add wr-architect@windyroad-local" "$EVAL_DIR/run-codex-agent-eval.sh"
24
+ [ "$status" -eq 0 ]
25
+ run grep -n "codex exec" "$EVAL_DIR/run-codex-agent-eval.sh"
26
+ [ "$status" -eq 0 ]
27
+ run grep -n ".codex/agents/wr-architect.toml" "$EVAL_DIR/run-codex-agent-eval.sh"
28
+ [ "$status" -eq 0 ]
29
+ }
package/bin/install.mjs CHANGED
@@ -21,6 +21,7 @@ Options:
21
21
  --update Update this plugin and its skills
22
22
  --uninstall Remove this plugin
23
23
  --scope Installation scope: project (default) or user
24
+ --runtime Runtime to install for: claude (default), codex, or both
24
25
  --dry-run Show what would be done without executing
25
26
  --help, -h Show this help
26
27
  `);
@@ -32,12 +33,12 @@ if (flags.dryRun) {
32
33
  console.log("[dry-run mode — no commands will be executed]\n");
33
34
  }
34
35
 
35
- utils.checkPrerequisites();
36
+ utils.checkPrerequisites({ runtime: flags.runtime });
36
37
 
37
38
  if (flags.uninstall) {
38
- utils.uninstallPackage(PLUGIN);
39
+ utils.uninstallPackage(PLUGIN, { runtime: flags.runtime });
39
40
  } else if (flags.update) {
40
- utils.updatePackage(PLUGIN, { scope: flags.scope });
41
+ utils.updatePackage(PLUGIN, { scope: flags.scope, runtime: flags.runtime });
41
42
  } else {
42
- utils.installPackage(PLUGIN, { deps: DEPS, scope: flags.scope });
43
+ utils.installPackage(PLUGIN, { deps: DEPS, scope: flags.scope, runtime: flags.runtime });
43
44
  }
@@ -7,10 +7,12 @@ import { execSync } from "node:child_process";
7
7
 
8
8
  const MARKETPLACE_REPO = "windyroad/agent-plugins";
9
9
  const MARKETPLACE_NAME = "windyroad";
10
+ const CODEX_MARKETPLACE_PATH = ".";
11
+ const CODEX_MARKETPLACE_NAME = "windyroad-local";
10
12
 
11
13
  let _dryRun = false;
12
14
 
13
- export { MARKETPLACE_REPO, MARKETPLACE_NAME };
15
+ export { MARKETPLACE_REPO, MARKETPLACE_NAME, CODEX_MARKETPLACE_PATH, CODEX_MARKETPLACE_NAME };
14
16
 
15
17
  export function setDryRun(value) {
16
18
  _dryRun = value;
@@ -35,16 +37,34 @@ export function run(cmd, label) {
35
37
  }
36
38
  }
37
39
 
38
- export function checkPrerequisites() {
40
+ function runtimesFor(runtime = "claude") {
41
+ if (runtime === "both") return ["claude", "codex"];
42
+ return [runtime];
43
+ }
44
+
45
+ export function checkPrerequisites({ runtime = "claude" } = {}) {
39
46
  if (_dryRun) return;
40
47
 
41
- try {
42
- execSync("claude --version", { stdio: "pipe" });
43
- } catch {
44
- console.error(
45
- "Error: 'claude' CLI not found. Install Claude Code first:\n https://docs.anthropic.com/en/docs/claude-code\n"
46
- );
47
- process.exit(1);
48
+ for (const currentRuntime of runtimesFor(runtime)) {
49
+ if (currentRuntime === "claude") {
50
+ try {
51
+ execSync("claude --version", { stdio: "pipe" });
52
+ } catch {
53
+ console.error(
54
+ "Error: 'claude' CLI not found. Install Claude Code first:\n https://docs.anthropic.com/en/docs/claude-code\n"
55
+ );
56
+ process.exit(1);
57
+ }
58
+ } else if (currentRuntime === "codex") {
59
+ try {
60
+ execSync("codex --version", { stdio: "pipe" });
61
+ } catch {
62
+ console.error(
63
+ "Error: 'codex' CLI not found. Install Codex CLI first:\n https://developers.openai.com/codex\n"
64
+ );
65
+ process.exit(1);
66
+ }
67
+ }
48
68
  }
49
69
  }
50
70
 
@@ -55,6 +75,13 @@ export function addMarketplace() {
55
75
  );
56
76
  }
57
77
 
78
+ export function addCodexMarketplace() {
79
+ return run(
80
+ `codex plugin marketplace add ${CODEX_MARKETPLACE_PATH}`,
81
+ `Codex marketplace: ${CODEX_MARKETPLACE_NAME}`
82
+ );
83
+ }
84
+
58
85
  export function installPlugin(pluginName, { scope = "project" } = {}) {
59
86
  return run(
60
87
  `claude plugin install ${pluginName}@${MARKETPLACE_NAME} --scope ${scope}`,
@@ -62,6 +89,13 @@ export function installPlugin(pluginName, { scope = "project" } = {}) {
62
89
  );
63
90
  }
64
91
 
92
+ export function installCodexPlugin(pluginName) {
93
+ return run(
94
+ `codex plugin add ${pluginName}@${CODEX_MARKETPLACE_NAME}`,
95
+ pluginName
96
+ );
97
+ }
98
+
65
99
  export function updatePlugin(pluginName, { scope = "project" } = {}) {
66
100
  return run(
67
101
  `claude plugin update "${pluginName}@${MARKETPLACE_NAME}" --scope ${scope}`,
@@ -69,18 +103,36 @@ export function updatePlugin(pluginName, { scope = "project" } = {}) {
69
103
  );
70
104
  }
71
105
 
106
+ export function updateCodexMarketplace() {
107
+ return run(
108
+ `codex plugin marketplace add ${CODEX_MARKETPLACE_PATH}`,
109
+ `Codex marketplace: ${CODEX_MARKETPLACE_NAME}`
110
+ );
111
+ }
112
+
72
113
  export function uninstallPlugin(pluginName) {
73
114
  return run(`claude plugin uninstall ${pluginName}`, `Removing ${pluginName}`);
74
115
  }
75
116
 
117
+ export function uninstallCodexPlugin(pluginName) {
118
+ return run(`codex plugin remove ${pluginName}`, `Removing ${pluginName}`);
119
+ }
120
+
76
121
  /**
77
122
  * Install a single package: marketplace add + plugin install.
78
123
  */
79
- export function installPackage(pluginName, { deps = [], scope = "project" } = {}) {
124
+ export function installPackage(pluginName, { deps = [], scope = "project", runtime = "claude" } = {}) {
80
125
  console.log(`\nInstalling @windyroad/${pluginName.replace("wr-", "")} (${scope} scope)...\n`);
81
126
 
82
- addMarketplace();
83
- installPlugin(pluginName, { scope });
127
+ if (runtime === "claude" || runtime === "both") {
128
+ addMarketplace();
129
+ installPlugin(pluginName, { scope });
130
+ }
131
+
132
+ if (runtime === "codex" || runtime === "both") {
133
+ addCodexMarketplace();
134
+ installCodexPlugin(pluginName);
135
+ }
84
136
 
85
137
  if (deps.length > 0) {
86
138
  console.log(`\nNote: This plugin works best with:`);
@@ -90,34 +142,47 @@ export function installPackage(pluginName, { deps = [], scope = "project" } = {}
90
142
  }
91
143
 
92
144
  console.log(
93
- `\nDone! Restart Claude Code to activate.\n`
145
+ `\nDone! Restart ${runtime === "codex" ? "Codex" : runtime === "both" ? "Claude Code and Codex" : "Claude Code"} to activate.\n`
94
146
  );
95
147
  }
96
148
 
97
149
  /**
98
150
  * Update a single package.
99
151
  */
100
- export function updatePackage(pluginName, { scope = "project" } = {}) {
152
+ export function updatePackage(pluginName, { scope = "project", runtime = "claude" } = {}) {
101
153
  console.log(`\nUpdating @windyroad/${pluginName.replace("wr-", "")}...\n`);
102
154
 
103
- run(
104
- `claude plugin marketplace update ${MARKETPLACE_NAME}`,
105
- "Updating marketplace"
106
- );
107
- updatePlugin(pluginName, { scope });
155
+ if (runtime === "claude" || runtime === "both") {
156
+ run(
157
+ `claude plugin marketplace update ${MARKETPLACE_NAME}`,
158
+ "Updating marketplace"
159
+ );
160
+ updatePlugin(pluginName, { scope });
161
+ }
108
162
 
109
- console.log("\nDone! Restart Claude Code to apply updates.\n");
163
+ if (runtime === "codex" || runtime === "both") {
164
+ updateCodexMarketplace();
165
+ installCodexPlugin(pluginName);
166
+ }
167
+
168
+ console.log(`\nDone! Restart ${runtime === "codex" ? "Codex" : runtime === "both" ? "Claude Code and Codex" : "Claude Code"} to apply updates.\n`);
110
169
  }
111
170
 
112
171
  /**
113
172
  * Uninstall a single package.
114
173
  */
115
- export function uninstallPackage(pluginName) {
174
+ export function uninstallPackage(pluginName, { runtime = "claude" } = {}) {
116
175
  console.log(`\nUninstalling @windyroad/${pluginName.replace("wr-", "")}...\n`);
117
176
 
118
- uninstallPlugin(pluginName);
177
+ if (runtime === "claude" || runtime === "both") {
178
+ uninstallPlugin(pluginName);
179
+ }
180
+
181
+ if (runtime === "codex" || runtime === "both") {
182
+ uninstallCodexPlugin(pluginName);
183
+ }
119
184
 
120
- console.log("\nDone. Restart Claude Code to apply changes.\n");
185
+ console.log(`\nDone. Restart ${runtime === "codex" ? "Codex" : runtime === "both" ? "Claude Code and Codex" : "Claude Code"} to apply changes.\n`);
121
186
  }
122
187
 
123
188
  /**
@@ -131,6 +196,7 @@ export function parseStandardArgs(argv) {
131
196
  update: args.includes("--update"),
132
197
  dryRun: args.includes("--dry-run"),
133
198
  scope: "project",
199
+ runtime: "claude",
134
200
  };
135
201
  const scopeIdx = args.indexOf("--scope");
136
202
  if (scopeIdx !== -1 && args[scopeIdx + 1]) {
@@ -142,5 +208,15 @@ export function parseStandardArgs(argv) {
142
208
  process.exit(1);
143
209
  }
144
210
  }
211
+ const runtimeIdx = args.indexOf("--runtime");
212
+ if (runtimeIdx !== -1 && args[runtimeIdx + 1]) {
213
+ const val = args[runtimeIdx + 1];
214
+ if (["claude", "codex", "both"].includes(val)) {
215
+ flags.runtime = val;
216
+ } else {
217
+ console.error("--runtime requires: claude, codex, or both");
218
+ process.exit(1);
219
+ }
220
+ }
145
221
  return flags;
146
222
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/architect",
3
- "version": "0.17.3-preview.755",
3
+ "version": "0.17.3-preview.766",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "bin": {
6
6
  "windyroad-architect": "./bin/install.mjs"
@@ -25,6 +25,7 @@
25
25
  "skills/",
26
26
  "scripts/",
27
27
  ".claude-plugin/",
28
+ ".codex-plugin/",
28
29
  "lib/",
29
30
  "!skills/*/eval/"
30
31
  ]
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bats
2
+
3
+ setup() {
4
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
5
+ EVAL_DIR="$REPO_ROOT/packages/architect/skills/create-adr/eval"
6
+ }
7
+
8
+ @test "create-adr Codex promptfoo config sits beside Claude config" {
9
+ [ -f "$EVAL_DIR/promptfooconfig.yaml" ]
10
+ [ -f "$EVAL_DIR/promptfooconfig.codex.yaml" ]
11
+ run grep -n "run-codex-skill-eval.sh" "$EVAL_DIR/promptfooconfig.codex.yaml"
12
+ [ "$status" -eq 0 ]
13
+ run grep -n "grade-codex-rubric.sh" "$EVAL_DIR/promptfooconfig.codex.yaml"
14
+ [ "$status" -eq 0 ]
15
+ }
16
+
17
+ @test "create-adr Codex eval runner uses codex exec and plugin marketplace" {
18
+ run grep -n "codex plugin marketplace add" "$EVAL_DIR/run-codex-skill-eval.sh"
19
+ [ "$status" -eq 0 ]
20
+ run grep -n "codex plugin add wr-architect@windyroad-local" "$EVAL_DIR/run-codex-skill-eval.sh"
21
+ [ "$status" -eq 0 ]
22
+ run grep -n "codex exec" "$EVAL_DIR/run-codex-skill-eval.sh"
23
+ [ "$status" -eq 0 ]
24
+ run grep -n -- "--ephemeral" "$EVAL_DIR/run-codex-skill-eval.sh"
25
+ [ "$status" -eq 0 ]
26
+ run grep -n -- 'approval_policy="never"' "$EVAL_DIR/run-codex-skill-eval.sh"
27
+ [ "$status" -eq 0 ]
28
+ run grep -n -- "--sandbox read-only" "$EVAL_DIR/run-codex-skill-eval.sh"
29
+ [ "$status" -eq 0 ]
30
+ }
@@ -69,16 +69,27 @@ Build a self-contained prompt for the architect subagent that includes:
69
69
 
70
70
  The architect's verdict taxonomy includes **[Unratified Dependency]** (ADR-074 surface 3): if the plan/change explicitly cites or implements an ADR that lacks `human-oversight: confirmed` (unratified, non-superseded), the architect flags ISSUES FOUND with a "ratify via /wr-architect:review-decisions first" action. This applies to plan review exactly as to edit review — a plan built on an unratified decision should not proceed until that decision's substance is ratified. No extra prompt wiring is needed (the agent owns the check); this note records that the surface-3 check is in-scope for plan review.
71
71
 
72
- ### 5. Delegate to wr-architect:agent
72
+ ### 5. Delegate to the architect agent
73
73
 
74
- Invoke the architect subagent via the `Skill` tool:
74
+ Use the runtime-native architect agent path with the constructed prompt.
75
+
76
+ Claude Code invocation:
75
77
 
76
78
  ```
77
79
  subagent_type: wr-architect:agent
78
80
  prompt: <constructed review prompt from step 4>
79
81
  ```
80
82
 
81
- Wait for the subagent to complete.
83
+ Codex invocation:
84
+
85
+ ```
86
+ agent: wr-architect:agent
87
+ prompt: <constructed review prompt from step 4>
88
+ ```
89
+
90
+ Codex auto-discovers the agent from the installed plugin's `agents/agent.md` and registers it as `wr-architect:agent` (plugin name + agent frontmatter name). Adopter projects do not need to ship any `.codex/agents/*.toml` themselves — `codex plugin add wr-architect@windyroad` is enough. The repo-local `.codex/agents/wr-architect.toml`, kept in sync from `packages/architect/agents/agent.md` by `scripts/sync-codex-agents.mjs`, only supports in-repo dogfooding before the plugin is installed into `CODEX_HOME`; it registers a short-name alias `wr-architect` for source-repo developers. If a non-interactive `codex exec` validation harness cannot spawn the custom agent directly, perform the review inline using the same generated agent instructions and name that fallback in the output.
91
+
92
+ Wait for the agent to complete.
82
93
 
83
94
  ### 6. Present results
84
95
 
@@ -87,7 +98,7 @@ Present the full compliance report to the user. The architect subagent will repo
87
98
  - FLAGGED: specific violations or compliance questions with ADR references
88
99
  - NEW ADR NEEDED: decisions that should be recorded before proceeding
89
100
 
90
- If violations are flagged, use `AskUserQuestion` to ask how the user wants to proceed:
101
+ If violations are flagged, use the runtime's structured question mechanism to ask how the user wants to proceed:
91
102
  - (a) Address the violations before continuing
92
103
  - (b) Proceed with a documented exception
93
104
  - (c) Draft a new or amended ADR to legitimise the approach
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bats
2
+
3
+ setup() {
4
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
5
+ SKILL="$REPO_ROOT/packages/architect/skills/review-design/SKILL.md"
6
+ }
7
+
8
+ @test "review-design documents Claude and Codex architect invocation paths" {
9
+ run grep -n "Claude Code invocation" "$SKILL"
10
+ [ "$status" -eq 0 ]
11
+ run grep -n "subagent_type: wr-architect:agent" "$SKILL"
12
+ [ "$status" -eq 0 ]
13
+ run grep -n "Codex invocation" "$SKILL"
14
+ [ "$status" -eq 0 ]
15
+ run grep -nE "^agent: wr-architect:agent$" "$SKILL"
16
+ [ "$status" -eq 0 ]
17
+ }
18
+
19
+ @test "review-design names generated Codex agent config" {
20
+ run grep -n ".codex/agents/wr-architect.toml" "$SKILL"
21
+ [ "$status" -eq 0 ]
22
+ }