@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.
- package/.codex-plugin/plugin.json +43 -0
- package/agents/eval/codex-rubric-output.schema.json +22 -0
- package/agents/eval/grade-codex-rubric.sh +39 -0
- package/agents/eval/promptfooconfig.codex.yaml +56 -0
- package/agents/eval/run-codex-agent-eval.sh +47 -0
- package/agents/test/architect-codex-eval-contract.bats +29 -0
- package/bin/install.mjs +5 -4
- package/lib/install-utils.mjs +99 -23
- package/package.json +2 -1
- package/skills/create-adr/test/create-adr-codex-eval-contract.bats +30 -0
- package/skills/review-design/SKILL.md +15 -4
- package/skills/review-design/test/review-design-codex-contract.bats +22 -0
|
@@ -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
|
}
|
package/lib/install-utils.mjs
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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
|
|
72
|
+
### 5. Delegate to the architect agent
|
|
73
73
|
|
|
74
|
-
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|