vigiles 2.5.0 → 3.0.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.
- package/.claude-plugin/plugin.json +9 -0
- package/README.md +73 -434
- package/action.yml +143 -7
- package/dist/action-gate.d.ts +1 -1
- package/dist/action-gate.js +1 -1
- package/dist/adapter-conformance.d.ts +30 -0
- package/dist/adapter-conformance.js +153 -0
- package/dist/adapter-registry.d.ts +42 -0
- package/dist/adapter-registry.js +55 -0
- package/dist/adapter.d.ts +26 -0
- package/dist/adapter.js +16 -0
- package/dist/adapters/claude-code/adapter.d.ts +3 -0
- package/dist/adapters/claude-code/adapter.js +46 -0
- package/dist/{agent-result.d.ts → adapters/claude-code/agent-result.d.ts} +1 -1
- package/dist/adapters/claude-code/dialect.d.ts +13 -0
- package/dist/adapters/claude-code/dialect.js +51 -0
- package/dist/adapters/claude-code/egress-entry.d.ts +2 -0
- package/dist/adapters/claude-code/egress-entry.js +115 -0
- package/dist/adapters/claude-code/egress-proxy.d.ts +2 -0
- package/dist/adapters/claude-code/egress-proxy.js +60 -0
- package/dist/adapters/claude-code/egress.d.ts +114 -0
- package/dist/adapters/claude-code/egress.js +276 -0
- package/dist/adapters/claude-code/eval-baseline.d.ts +68 -0
- package/dist/adapters/claude-code/eval-baseline.js +173 -0
- package/dist/{eval-cache.d.ts → adapters/claude-code/eval-cache.d.ts} +1 -1
- package/dist/{eval-cache.js → adapters/claude-code/eval-cache.js} +1 -1
- package/dist/{eval.d.ts → adapters/claude-code/eval.d.ts} +28 -4
- package/dist/{eval.js → adapters/claude-code/eval.js} +61 -25
- package/dist/{harness-test.d.ts → adapters/claude-code/harness-test.d.ts} +33 -37
- package/dist/{harness-test.js → adapters/claude-code/harness-test.js} +124 -43
- package/dist/adapters/claude-code/hook-protocol.d.ts +10 -0
- package/dist/adapters/claude-code/hook-protocol.js +10 -0
- package/dist/adapters/claude-code/layout.d.ts +8 -0
- package/dist/adapters/claude-code/layout.js +18 -0
- package/dist/{mock-model.d.ts → adapters/claude-code/mock-model.d.ts} +2 -24
- package/dist/adapters/claude-code/model-mock.d.ts +11 -0
- package/dist/adapters/claude-code/model-mock.js +10 -0
- package/dist/adapters/claude-code/plugin-loader.d.ts +25 -0
- package/dist/adapters/claude-code/plugin-loader.js +19 -0
- package/dist/adapters/claude-code/run-hook.d.ts +204 -0
- package/dist/adapters/claude-code/run-hook.js +418 -0
- package/dist/adapters/claude-code/run-scripts.d.ts +52 -0
- package/dist/adapters/claude-code/run-scripts.js +150 -0
- package/dist/adapters/claude-code/runtime.d.ts +16 -0
- package/dist/adapters/claude-code/runtime.js +39 -0
- package/dist/{sandbox.d.ts → adapters/claude-code/sandbox.d.ts} +45 -4
- package/dist/{sandbox.js → adapters/claude-code/sandbox.js} +76 -8
- package/dist/{skill-driver.d.ts → adapters/claude-code/skill-driver.d.ts} +1 -1
- package/dist/adapters/codex/adapter.d.ts +3 -0
- package/dist/adapters/codex/adapter.js +49 -0
- package/dist/adapters/codex/dialect.d.ts +10 -0
- package/dist/adapters/codex/dialect.js +30 -0
- package/dist/adapters/codex/driver.d.ts +20 -0
- package/dist/adapters/codex/driver.js +89 -0
- package/dist/adapters/codex/hook-protocol.d.ts +10 -0
- package/dist/adapters/codex/hook-protocol.js +18 -0
- package/dist/adapters/codex/layout.d.ts +16 -0
- package/dist/adapters/codex/layout.js +18 -0
- package/dist/adapters/codex/mock-model.d.ts +52 -0
- package/dist/adapters/codex/mock-model.js +210 -0
- package/dist/adapters/codex/model-mock.d.ts +11 -0
- package/dist/adapters/codex/model-mock.js +10 -0
- package/dist/adapters/codex/runtime.d.ts +38 -0
- package/dist/adapters/codex/runtime.js +62 -0
- package/dist/adapters/opencode/adapter.d.ts +3 -0
- package/dist/adapters/opencode/adapter.js +48 -0
- package/dist/adapters/opencode/dialect.d.ts +10 -0
- package/dist/adapters/opencode/dialect.js +36 -0
- package/dist/adapters/opencode/layout.d.ts +9 -0
- package/dist/adapters/opencode/layout.js +25 -0
- package/dist/adapters/opencode/model-mock.d.ts +10 -0
- package/dist/adapters/opencode/model-mock.js +10 -0
- package/dist/adapters/opencode/runtime.d.ts +9 -0
- package/dist/adapters/opencode/runtime.js +21 -0
- package/dist/claude-code.d.ts +16 -0
- package/dist/claude-code.js +32 -0
- package/dist/cli-flags.d.ts +22 -0
- package/dist/cli-flags.js +38 -0
- package/dist/cli.js +406 -206
- package/dist/codex.d.ts +20 -0
- package/dist/codex.js +36 -0
- package/dist/community-skills.d.ts +1 -1
- package/dist/community-skills.js +2 -2
- package/dist/core/adapter.d.ts +88 -0
- package/dist/core/adapter.js +3 -0
- package/dist/{compile.d.ts → core/compile.d.ts} +11 -2
- package/dist/{compile.js → core/compile.js} +68 -53
- package/dist/core/compose.d.ts +79 -0
- package/dist/core/compose.js +145 -0
- package/dist/core/dialect.d.ts +51 -0
- package/dist/core/dialect.js +3 -0
- package/dist/core/harness-driver.d.ts +134 -0
- package/dist/core/harness-driver.js +3 -0
- package/dist/core/hook-protocol.d.ts +28 -0
- package/dist/core/hook-protocol.js +3 -0
- package/dist/core/layout.d.ts +43 -0
- package/dist/core/layout.js +3 -0
- package/dist/core/model-mock.d.ts +27 -0
- package/dist/core/model-mock.js +3 -0
- package/dist/core/refs.d.ts +62 -0
- package/dist/{refs.js → core/refs.js} +49 -23
- package/dist/core/runtime.d.ts +38 -0
- package/dist/core/runtime.js +3 -0
- package/dist/{types.d.ts → core/types.d.ts} +29 -0
- package/dist/{validate.d.ts → core/validate.d.ts} +1 -1
- package/dist/{validate.js → core/validate.js} +41 -4
- package/dist/e2e.d.ts +19 -0
- package/dist/e2e.js +39 -0
- package/dist/harness-assert.d.ts +60 -11
- package/dist/harness-assert.js +111 -9
- package/dist/integration.d.ts +16 -0
- package/dist/integration.js +32 -0
- package/dist/leaderboard.d.ts +33 -0
- package/dist/leaderboard.js +107 -0
- package/dist/linting.d.ts +9 -0
- package/dist/linting.js +25 -0
- package/dist/plugin-loader.d.ts +6 -3
- package/dist/plugin-loader.js +101 -49
- package/dist/scan.d.ts +49 -0
- package/dist/scan.js +177 -0
- package/dist/setup-plan.d.ts +51 -0
- package/dist/setup-plan.js +85 -0
- package/dist/skill-test.d.ts +1 -1
- package/dist/skill-test.js +1 -1
- package/dist/test-coverage.d.ts +71 -0
- package/dist/test-coverage.js +228 -0
- package/dist/testing.d.ts +12 -0
- package/dist/testing.js +28 -0
- package/dist/unit.d.ts +17 -0
- package/dist/unit.js +36 -0
- package/hooks/refs-nudge.sh +24 -0
- package/package.json +35 -16
- package/skills/audit-feedback-loop/SKILL.md +76 -0
- package/skills/edit-spec/SKILL.md +131 -0
- package/skills/enforce-rules-format/SKILL.md +71 -0
- package/skills/generate-logo/SKILL.md +103 -0
- package/skills/generate-rule/SKILL.md +64 -0
- package/skills/linter-docs/clippy.md +241 -0
- package/skills/linter-docs/eslint.md +384 -0
- package/skills/linter-docs/pylint.md +288 -0
- package/skills/linter-docs/rubocop.md +277 -0
- package/skills/linter-docs/ruff.md +187 -0
- package/skills/linter-docs/stylelint.md +247 -0
- package/skills/migrate-to-spec/SKILL.md +126 -0
- package/skills/pr-to-lint-rule/SKILL.md +97 -0
- package/skills/strengthen/SKILL.md +168 -0
- package/skills/test-harness/SKILL.md +157 -0
- package/dist/action.d.ts +0 -7
- package/dist/action.js +0 -180
- package/dist/refs.d.ts +0 -44
- package/dist/run-hook.d.ts +0 -77
- package/dist/run-hook.js +0 -80
- package/dist/run-scripts.d.ts +0 -20
- package/dist/run-scripts.js +0 -70
- /package/dist/{agent-result.js → adapters/claude-code/agent-result.js} +0 -0
- /package/dist/{agent-runtime.d.ts → adapters/claude-code/agent-runtime.d.ts} +0 -0
- /package/dist/{agent-runtime.js → adapters/claude-code/agent-runtime.js} +0 -0
- /package/dist/{judge.d.ts → adapters/claude-code/judge.d.ts} +0 -0
- /package/dist/{judge.js → adapters/claude-code/judge.js} +0 -0
- /package/dist/{mock-entry.d.ts → adapters/claude-code/mock-entry.d.ts} +0 -0
- /package/dist/{mock-entry.js → adapters/claude-code/mock-entry.js} +0 -0
- /package/dist/{mock-model.js → adapters/claude-code/mock-model.js} +0 -0
- /package/dist/{skill-driver.js → adapters/claude-code/skill-driver.js} +0 -0
- /package/dist/{skill-runtime.d.ts → adapters/claude-code/skill-runtime.d.ts} +0 -0
- /package/dist/{skill-runtime.js → adapters/claude-code/skill-runtime.js} +0 -0
- /package/dist/{stats.d.ts → adapters/claude-code/stats.d.ts} +0 -0
- /package/dist/{stats.js → adapters/claude-code/stats.js} +0 -0
- /package/dist/{compile-generator.d.ts → core/compile-generator.d.ts} +0 -0
- /package/dist/{compile-generator.js → core/compile-generator.js} +0 -0
- /package/dist/{coverage.d.ts → core/coverage.d.ts} +0 -0
- /package/dist/{coverage.js → core/coverage.js} +0 -0
- /package/dist/{doc-refs.d.ts → core/doc-refs.d.ts} +0 -0
- /package/dist/{doc-refs.js → core/doc-refs.js} +0 -0
- /package/dist/{evolve.d.ts → core/evolve.d.ts} +0 -0
- /package/dist/{evolve.js → core/evolve.js} +0 -0
- /package/dist/{frontmatter.d.ts → core/frontmatter.d.ts} +0 -0
- /package/dist/{frontmatter.js → core/frontmatter.js} +0 -0
- /package/dist/{generate-schema.d.ts → core/generate-schema.d.ts} +0 -0
- /package/dist/{generate-schema.js → core/generate-schema.js} +0 -0
- /package/dist/{generate-types.d.ts → core/generate-types.d.ts} +0 -0
- /package/dist/{generate-types.js → core/generate-types.js} +0 -0
- /package/dist/{hash.d.ts → core/hash.d.ts} +0 -0
- /package/dist/{hash.js → core/hash.js} +0 -0
- /package/dist/{inline.d.ts → core/inline.d.ts} +0 -0
- /package/dist/{inline.js → core/inline.js} +0 -0
- /package/dist/{integrity.d.ts → core/integrity.d.ts} +0 -0
- /package/dist/{integrity.js → core/integrity.js} +0 -0
- /package/dist/{linters.d.ts → core/linters.d.ts} +0 -0
- /package/dist/{linters.js → core/linters.js} +0 -0
- /package/dist/{mcp.d.ts → core/mcp.d.ts} +0 -0
- /package/dist/{mcp.js → core/mcp.js} +0 -0
- /package/dist/{orphans.d.ts → core/orphans.d.ts} +0 -0
- /package/dist/{orphans.js → core/orphans.js} +0 -0
- /package/dist/{proofs.d.ts → core/proofs.d.ts} +0 -0
- /package/dist/{proofs.js → core/proofs.js} +0 -0
- /package/dist/{session.d.ts → core/session.d.ts} +0 -0
- /package/dist/{session.js → core/session.js} +0 -0
- /package/dist/{sidecar.d.ts → core/sidecar.d.ts} +0 -0
- /package/dist/{sidecar.js → core/sidecar.js} +0 -0
- /package/dist/{spec.d.ts → core/spec.d.ts} +0 -0
- /package/dist/{spec.js → core/spec.js} +0 -0
- /package/dist/{symbols.d.ts → core/symbols.d.ts} +0 -0
- /package/dist/{symbols.js → core/symbols.js} +0 -0
- /package/dist/{test-utils.d.ts → core/test-utils.d.ts} +0 -0
- /package/dist/{test-utils.js → core/test-utils.js} +0 -0
- /package/dist/{types.js → core/types.js} +0 -0
- /package/{.claude-plugin/hooks → hooks}/post-edit.sh +0 -0
- /package/{.claude-plugin/hooks → hooks}/pre-edit.sh +0 -0
- /package/{.claude-plugin/hooks → hooks}/session-start.sh +0 -0
package/action.yml
CHANGED
|
@@ -1,25 +1,161 @@
|
|
|
1
1
|
name: "vigiles"
|
|
2
|
-
description: "
|
|
2
|
+
description: "Verify the references in your agent instruction files (CLAUDE.md/AGENTS.md) and compile typed specs — in CI."
|
|
3
|
+
author: "zernie"
|
|
3
4
|
branding:
|
|
4
5
|
icon: "check-circle"
|
|
5
6
|
color: "orange"
|
|
6
7
|
|
|
7
8
|
inputs:
|
|
8
9
|
command:
|
|
9
|
-
description: "
|
|
10
|
+
description: "Which vigiles command to run: 'audit' (verify references + integrity + coverage) or 'compile' (specs → markdown)."
|
|
10
11
|
required: false
|
|
11
12
|
default: "audit"
|
|
12
13
|
paths:
|
|
13
|
-
description: "Comma-separated paths to .
|
|
14
|
+
description: "Comma- or space-separated paths to operate on (.md files for audit, .spec.ts files for compile). Auto-discovers when empty."
|
|
14
15
|
required: false
|
|
16
|
+
default: ""
|
|
17
|
+
version:
|
|
18
|
+
description: "Version of the vigiles npm package to run (e.g. '1', '1.2.3', 'latest'). Use 'local' to run the action's own checkout — for dogfooding via `uses: ./` in this repo's CI."
|
|
19
|
+
required: false
|
|
20
|
+
default: "latest"
|
|
15
21
|
max-rules:
|
|
16
|
-
description: "Maximum number of rules per spec file"
|
|
22
|
+
description: "Maximum number of rules per spec file (maps to the CLI's --max-rules)."
|
|
17
23
|
required: false
|
|
24
|
+
default: ""
|
|
18
25
|
catalog-only:
|
|
19
|
-
description: "Only check that linter rules exist
|
|
26
|
+
description: "Only check that linter rules exist; skip config-enabled checks (maps to the CLI's --catalog-only). 'true' or 'false'."
|
|
20
27
|
required: false
|
|
21
28
|
default: "false"
|
|
29
|
+
working-directory:
|
|
30
|
+
description: "Directory to run vigiles in."
|
|
31
|
+
required: false
|
|
32
|
+
default: "."
|
|
33
|
+
comment:
|
|
34
|
+
description: "On pull_request events, post/update a sticky PR comment with the result ('true' or 'false'). Requires `pull-requests: write`."
|
|
35
|
+
required: false
|
|
36
|
+
default: "true"
|
|
37
|
+
github-token:
|
|
38
|
+
description: "Token used to post the PR comment. Defaults to the workflow token."
|
|
39
|
+
required: false
|
|
40
|
+
default: ${{ github.token }}
|
|
41
|
+
|
|
42
|
+
outputs:
|
|
43
|
+
valid:
|
|
44
|
+
description: "'true' if vigiles passed (exit 0), 'false' otherwise."
|
|
45
|
+
value: ${{ steps.vigiles.outputs.valid }}
|
|
22
46
|
|
|
23
47
|
runs:
|
|
24
|
-
using: "
|
|
25
|
-
|
|
48
|
+
using: "composite"
|
|
49
|
+
steps:
|
|
50
|
+
- id: vigiles
|
|
51
|
+
shell: bash
|
|
52
|
+
working-directory: ${{ inputs.working-directory }}
|
|
53
|
+
env:
|
|
54
|
+
# Inputs are passed through the environment (never interpolated into
|
|
55
|
+
# the script body) so a value can't break out of the command line.
|
|
56
|
+
VIGILES_COMMAND: ${{ inputs.command }}
|
|
57
|
+
VIGILES_PATHS: ${{ inputs.paths }}
|
|
58
|
+
VIGILES_VERSION: ${{ inputs.version }}
|
|
59
|
+
VIGILES_MAX_RULES: ${{ inputs.max-rules }}
|
|
60
|
+
VIGILES_CATALOG_ONLY: ${{ inputs.catalog-only }}
|
|
61
|
+
VIGILES_ACTION_PATH: ${{ github.action_path }}
|
|
62
|
+
VIGILES_COMMENT: ${{ inputs.comment }}
|
|
63
|
+
GH_TOKEN: ${{ inputs.github-token }}
|
|
64
|
+
run: |
|
|
65
|
+
set -euo pipefail
|
|
66
|
+
|
|
67
|
+
cmd="${VIGILES_COMMAND:-audit}"
|
|
68
|
+
args=("$cmd")
|
|
69
|
+
|
|
70
|
+
# paths: split on commas and whitespace into positional args.
|
|
71
|
+
paths="${VIGILES_PATHS:-}"
|
|
72
|
+
if [[ -n "${paths// /}" ]]; then
|
|
73
|
+
IFS=', ' read -r -a _paths <<< "$paths"
|
|
74
|
+
args+=("${_paths[@]}")
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
max_rules="${VIGILES_MAX_RULES:-}"
|
|
78
|
+
if [[ -n "${max_rules// /}" ]]; then
|
|
79
|
+
args+=("--max-rules=${max_rules}")
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if [[ "${VIGILES_CATALOG_ONLY:-false}" == "true" ]]; then
|
|
83
|
+
args+=("--catalog-only")
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Resolve the runner. 'local' runs the action's own build (CI
|
|
87
|
+
# dogfood via `uses: ./`); any other value runs the published npm
|
|
88
|
+
# package at that version, so the Action reuses the same tested
|
|
89
|
+
# artifact users get from `npx vigiles`.
|
|
90
|
+
version="${VIGILES_VERSION:-latest}"
|
|
91
|
+
if [[ "$version" == "local" ]]; then
|
|
92
|
+
runner=(node "${VIGILES_ACTION_PATH}/dist/cli.js")
|
|
93
|
+
else
|
|
94
|
+
runner=(npx --yes "vigiles@${version}")
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
echo "vigiles: ${runner[*]} ${args[*]}"
|
|
98
|
+
|
|
99
|
+
# Run, streaming to the log AND capturing for the summary/comment.
|
|
100
|
+
out="$(mktemp)"
|
|
101
|
+
set +e
|
|
102
|
+
GITHUB_ACTIONS=true "${runner[@]}" "${args[@]}" 2>&1 | tee "$out"
|
|
103
|
+
status="${PIPESTATUS[0]}"
|
|
104
|
+
set -e
|
|
105
|
+
|
|
106
|
+
if [[ "$status" -eq 0 ]]; then
|
|
107
|
+
echo "valid=true" >> "$GITHUB_OUTPUT"
|
|
108
|
+
headline="✅ \`vigiles ${cmd}\` passed"
|
|
109
|
+
else
|
|
110
|
+
echo "valid=false" >> "$GITHUB_OUTPUT"
|
|
111
|
+
headline="❌ \`vigiles ${cmd}\` failed (exit ${status})"
|
|
112
|
+
echo "::error::vigiles ${cmd} failed (exit ${status})"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Build a markdown report (cap the log tail so a huge run stays sane).
|
|
116
|
+
report="$(mktemp)"
|
|
117
|
+
{
|
|
118
|
+
echo "## vigiles"
|
|
119
|
+
echo
|
|
120
|
+
echo "$headline"
|
|
121
|
+
echo
|
|
122
|
+
echo '<details><summary>Output</summary>'
|
|
123
|
+
echo
|
|
124
|
+
echo '```'
|
|
125
|
+
tail -c 60000 "$out"
|
|
126
|
+
echo '```'
|
|
127
|
+
echo
|
|
128
|
+
echo '</details>'
|
|
129
|
+
} > "$report"
|
|
130
|
+
|
|
131
|
+
# Job summary (always, when available) — the modern run-page output.
|
|
132
|
+
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
|
|
133
|
+
cat "$report" >> "$GITHUB_STEP_SUMMARY"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# Sticky PR comment (pull_request events only, best-effort): find the
|
|
137
|
+
# prior vigiles comment by marker and update it in place, else create.
|
|
138
|
+
marker="<!-- vigiles-action -->"
|
|
139
|
+
if [[ "${VIGILES_COMMENT:-true}" == "true" \
|
|
140
|
+
&& "${GITHUB_EVENT_NAME:-}" == "pull_request" \
|
|
141
|
+
&& -n "${GH_TOKEN:-}" ]] && command -v gh >/dev/null 2>&1; then
|
|
142
|
+
pr="$(jq -r '.pull_request.number // empty' "${GITHUB_EVENT_PATH:-/dev/null}")"
|
|
143
|
+
if [[ -n "$pr" ]]; then
|
|
144
|
+
body="$(printf '%s\n%s\n' "$marker" "$(cat "$report")")"
|
|
145
|
+
repo="${GITHUB_REPOSITORY}"
|
|
146
|
+
cid="$(gh api "repos/${repo}/issues/${pr}/comments" --paginate \
|
|
147
|
+
--jq "map(select(.body | startswith(\"${marker}\"))) | .[0].id // empty" \
|
|
148
|
+
2>/dev/null || true)"
|
|
149
|
+
if [[ -n "$cid" ]]; then
|
|
150
|
+
gh api -X PATCH "repos/${repo}/issues/comments/${cid}" -f body="$body" >/dev/null \
|
|
151
|
+
&& echo "Updated PR comment #${cid}" \
|
|
152
|
+
|| echo "::warning::could not update PR comment (need pull-requests: write?)"
|
|
153
|
+
else
|
|
154
|
+
gh api -X POST "repos/${repo}/issues/${pr}/comments" -f body="$body" >/dev/null \
|
|
155
|
+
&& echo "Posted PR comment" \
|
|
156
|
+
|| echo "::warning::could not post PR comment (need pull-requests: write?)"
|
|
157
|
+
fi
|
|
158
|
+
fi
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
exit "$status"
|
package/dist/action-gate.d.ts
CHANGED
package/dist/action-gate.js
CHANGED
|
@@ -21,7 +21,7 @@ exports.loadActionGates = loadActionGates;
|
|
|
21
21
|
*/
|
|
22
22
|
const node_fs_1 = require("node:fs");
|
|
23
23
|
const node_path_1 = require("node:path");
|
|
24
|
-
const skill_runtime_js_1 = require("./skill-runtime.js");
|
|
24
|
+
const skill_runtime_js_1 = require("./adapters/claude-code/skill-runtime.js");
|
|
25
25
|
/** The file path an action touched, for `{file}` substitution. */
|
|
26
26
|
function fileOf(event) {
|
|
27
27
|
const i = event.input ?? {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { HarnessAdapter } from "./core/adapter.js";
|
|
2
|
+
export interface ConformanceResult {
|
|
3
|
+
readonly ok: boolean;
|
|
4
|
+
readonly failures: readonly string[];
|
|
5
|
+
}
|
|
6
|
+
/** Check an adapter against the port contracts; returns the (possibly empty) failure list. */
|
|
7
|
+
export declare function checkAdapterConformance(adapter: HarnessAdapter): ConformanceResult;
|
|
8
|
+
/** Throw if the adapter fails conformance — drop this in an adapter's test suite. */
|
|
9
|
+
export declare function assertAdapterConformance(adapter: HarnessAdapter): void;
|
|
10
|
+
/**
|
|
11
|
+
* Guard for the pillar-2 entry points (runHarnessTest/runEval): a pillar-1-only
|
|
12
|
+
* adapter (Cursor, Devin, Amp, Amazon Q) has no mockable transport, so driving
|
|
13
|
+
* the deterministic/eval tiers against it would hang or spawn nothing. Calling
|
|
14
|
+
* this up front turns that into a clear, immediate error. Returns the narrowed
|
|
15
|
+
* runtime+modelMock so the caller can use them without re-checking for undefined.
|
|
16
|
+
*/
|
|
17
|
+
export declare function assertHarnessTestable(adapter: HarnessAdapter): {
|
|
18
|
+
runtime: NonNullable<HarnessAdapter["runtime"]>;
|
|
19
|
+
modelMock: NonNullable<HarnessAdapter["modelMock"]>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Behavioural conformance the pure checks can't reach: write a minimal settings
|
|
23
|
+
* file in the adapter's declared `settingsFormat` (with a hook), load it through
|
|
24
|
+
* the adapter's `layout`, and assert the hooks actually came back. This is what
|
|
25
|
+
* catches a layout that points at the right file but in the wrong format (the
|
|
26
|
+
* JSON-vs-TOML trap) — the pure checker would pass it, the agent would silently
|
|
27
|
+
* run with zero hooks. Does filesystem IO, so it's a separate opt-in assert.
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertAdapterLoadsHooks(adapter: HarnessAdapter): void;
|
|
30
|
+
//# sourceMappingURL=adapter-conformance.d.ts.map
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkAdapterConformance = checkAdapterConformance;
|
|
4
|
+
exports.assertAdapterConformance = assertAdapterConformance;
|
|
5
|
+
exports.assertHarnessTestable = assertHarnessTestable;
|
|
6
|
+
exports.assertAdapterLoadsHooks = assertAdapterLoadsHooks;
|
|
7
|
+
/**
|
|
8
|
+
* Adapter conformance kit — the reusable check every `HarnessAdapter` runs, so
|
|
9
|
+
* authoring one is guided and safe rather than "hope it's wired right". It
|
|
10
|
+
* verifies each port is populated AND a behavioural invariant: the adapter's
|
|
11
|
+
* dialect actually drives tool-contract verification (its own built-in tool is
|
|
12
|
+
* accepted). A third-party adapter author runs `assertAdapterConformance(myAdapter)`
|
|
13
|
+
* in their test suite. See `docs/authoring-an-adapter.md`.
|
|
14
|
+
*/
|
|
15
|
+
const node_fs_1 = require("node:fs");
|
|
16
|
+
const node_os_1 = require("node:os");
|
|
17
|
+
const node_path_1 = require("node:path");
|
|
18
|
+
const compile_js_1 = require("./core/compile.js");
|
|
19
|
+
const spec_js_1 = require("./core/spec.js");
|
|
20
|
+
const plugin_loader_js_1 = require("./plugin-loader.js");
|
|
21
|
+
/** Check an adapter against the port contracts; returns the (possibly empty) failure list. */
|
|
22
|
+
function checkAdapterConformance(adapter) {
|
|
23
|
+
const failures = [];
|
|
24
|
+
const need = (cond, msg) => {
|
|
25
|
+
if (!cond)
|
|
26
|
+
failures.push(msg);
|
|
27
|
+
};
|
|
28
|
+
const caps = adapter.capabilities;
|
|
29
|
+
// Widen to boolean so a malformed (non-TS) adapter that set this false is still
|
|
30
|
+
// caught at runtime — the literal `true` type would make a direct check redundant.
|
|
31
|
+
const refVerification = caps.referenceVerification;
|
|
32
|
+
need(adapter.name.length > 0, "name is empty");
|
|
33
|
+
need(refVerification, "capabilities.referenceVerification must be true (every adapter does pillar 1)");
|
|
34
|
+
// --- Pillar 1 (always required): dialect + layout ---
|
|
35
|
+
need(adapter.dialect.builtinAgentTools.length > 0, "dialect has no builtinAgentTools");
|
|
36
|
+
need(adapter.dialect.instructionTargets.length > 0, "dialect has no instructionTargets");
|
|
37
|
+
need(adapter.layout.instructionFile.length > 0, "layout.instructionFile is empty");
|
|
38
|
+
need(adapter.layout.manifestPath.length > 0, "layout.manifestPath is empty");
|
|
39
|
+
need(adapter.layout.surfaceDirs.length > 0, "layout has no surfaceDirs");
|
|
40
|
+
need(typeof adapter.detect === "function", "detect is not a function");
|
|
41
|
+
// --- Pillar 2 transport ports: required ONLY for the capabilities the
|
|
42
|
+
// adapter declares. A pillar-1-only adapter (harnessTesting:false) may omit
|
|
43
|
+
// runtime/modelMock; a code-module-hook adapter (shellHooks:false) may omit
|
|
44
|
+
// hookProtocol — and conformance must NOT demand a fake one. The flip side:
|
|
45
|
+
// if it CLAIMS the capability, the port must be there and populated.
|
|
46
|
+
const portNames = [
|
|
47
|
+
["dialect", adapter.dialect.name],
|
|
48
|
+
["layout", adapter.layout.name],
|
|
49
|
+
];
|
|
50
|
+
if (caps.harnessTesting) {
|
|
51
|
+
need(adapter.runtime !== undefined, "capabilities.harnessTesting is true but runtime is missing");
|
|
52
|
+
need(adapter.modelMock !== undefined, "capabilities.harnessTesting is true but modelMock is missing");
|
|
53
|
+
if (adapter.runtime) {
|
|
54
|
+
need(adapter.runtime.agentBinary.length > 0, "runtime.agentBinary is empty");
|
|
55
|
+
need(adapter.runtime.modelBaseUrlEnv.length > 0, "runtime.modelBaseUrlEnv is empty");
|
|
56
|
+
portNames.push(["runtime", adapter.runtime.name]);
|
|
57
|
+
}
|
|
58
|
+
if (adapter.modelMock) {
|
|
59
|
+
need(adapter.modelMock.modelEndpoint.length > 0, "modelMock.modelEndpoint is empty");
|
|
60
|
+
portNames.push(["modelMock", adapter.modelMock.name]);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
need(adapter.runtime === undefined && adapter.modelMock === undefined, "capabilities.harnessTesting is false — omit runtime/modelMock (a pillar-1-only adapter must not ship a half-wired transport)");
|
|
65
|
+
}
|
|
66
|
+
if (caps.shellHooks) {
|
|
67
|
+
need(adapter.hookProtocol !== undefined, "capabilities.shellHooks is true but hookProtocol is missing");
|
|
68
|
+
if (adapter.hookProtocol) {
|
|
69
|
+
need(Number.isInteger(adapter.hookProtocol.blockExitCode), "hookProtocol.blockExitCode is not an integer");
|
|
70
|
+
portNames.push(["hookProtocol", adapter.hookProtocol.name]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
need(adapter.hookProtocol === undefined, "capabilities.shellHooks is false — omit hookProtocol (hooks are code modules, not shell processes)");
|
|
75
|
+
}
|
|
76
|
+
// Cross-port invariants — the kind of mismatch a copy-paste authoring slip
|
|
77
|
+
// produces, that no single-port check would catch. Only the present ports.
|
|
78
|
+
for (const [port, name] of portNames) {
|
|
79
|
+
need(name === adapter.name, `${port}.name "${name}" != adapter.name "${adapter.name}"`);
|
|
80
|
+
}
|
|
81
|
+
need(adapter.layout.pluginRootToken === adapter.dialect.pluginRootToken, "layout.pluginRootToken and dialect.pluginRootToken disagree");
|
|
82
|
+
need(adapter.dialect.instructionTargets.includes(adapter.layout.instructionFile), `layout.instructionFile "${adapter.layout.instructionFile}" is not one of dialect.instructionTargets`);
|
|
83
|
+
need(adapter.layout.settingsFormat === "json" ||
|
|
84
|
+
adapter.layout.settingsFormat === "toml", `layout.settingsFormat "${adapter.layout.settingsFormat}" is not "json" | "toml"`);
|
|
85
|
+
// Behavioural: the dialect drives the compiler — its own built-in tool must
|
|
86
|
+
// pass the subagent tool-contract check under this dialect.
|
|
87
|
+
const tool = adapter.dialect.builtinAgentTools[0];
|
|
88
|
+
if (tool) {
|
|
89
|
+
const spec = (0, spec_js_1.agent)({
|
|
90
|
+
name: "conformance",
|
|
91
|
+
description: "conformance probe",
|
|
92
|
+
tools: [tool],
|
|
93
|
+
body: "probe",
|
|
94
|
+
});
|
|
95
|
+
const r = (0, compile_js_1.compileAgent)(spec, {
|
|
96
|
+
specFile: "conformance.md.spec.ts",
|
|
97
|
+
dialect: adapter.dialect,
|
|
98
|
+
});
|
|
99
|
+
need(!r.errors.some((e) => e.type === "unknown-tool"), `dialect rejects its own built-in tool "${tool}"`);
|
|
100
|
+
}
|
|
101
|
+
return { ok: failures.length === 0, failures };
|
|
102
|
+
}
|
|
103
|
+
/** Throw if the adapter fails conformance — drop this in an adapter's test suite. */
|
|
104
|
+
function assertAdapterConformance(adapter) {
|
|
105
|
+
const r = checkAdapterConformance(adapter);
|
|
106
|
+
if (!r.ok) {
|
|
107
|
+
throw new Error(`Adapter "${adapter.name}" failed conformance:\n - ${r.failures.join("\n - ")}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Guard for the pillar-2 entry points (runHarnessTest/runEval): a pillar-1-only
|
|
112
|
+
* adapter (Cursor, Devin, Amp, Amazon Q) has no mockable transport, so driving
|
|
113
|
+
* the deterministic/eval tiers against it would hang or spawn nothing. Calling
|
|
114
|
+
* this up front turns that into a clear, immediate error. Returns the narrowed
|
|
115
|
+
* runtime+modelMock so the caller can use them without re-checking for undefined.
|
|
116
|
+
*/
|
|
117
|
+
function assertHarnessTestable(adapter) {
|
|
118
|
+
if (!adapter.capabilities.harnessTesting ||
|
|
119
|
+
!adapter.runtime ||
|
|
120
|
+
!adapter.modelMock) {
|
|
121
|
+
throw new Error(`Adapter "${adapter.name}" does not support harness testing (pillar 2): it is reference-verification-only (no mockable runtime). Use it for compile/scan/audit, not runHarnessTest/runEval.`);
|
|
122
|
+
}
|
|
123
|
+
return { runtime: adapter.runtime, modelMock: adapter.modelMock };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Behavioural conformance the pure checks can't reach: write a minimal settings
|
|
127
|
+
* file in the adapter's declared `settingsFormat` (with a hook), load it through
|
|
128
|
+
* the adapter's `layout`, and assert the hooks actually came back. This is what
|
|
129
|
+
* catches a layout that points at the right file but in the wrong format (the
|
|
130
|
+
* JSON-vs-TOML trap) — the pure checker would pass it, the agent would silently
|
|
131
|
+
* run with zero hooks. Does filesystem IO, so it's a separate opt-in assert.
|
|
132
|
+
*/
|
|
133
|
+
function assertAdapterLoadsHooks(adapter) {
|
|
134
|
+
const dir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "vigiles-conformance-"));
|
|
135
|
+
try {
|
|
136
|
+
const settingsAbs = (0, node_path_1.join)(dir, adapter.layout.settingsPath);
|
|
137
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(settingsAbs), { recursive: true });
|
|
138
|
+
const content = adapter.layout.settingsFormat === "toml"
|
|
139
|
+
? '[[hooks.PreToolUse]]\ncommand = "echo conformance"\n'
|
|
140
|
+
: JSON.stringify({
|
|
141
|
+
hooks: { PreToolUse: [{ command: "echo conformance" }] },
|
|
142
|
+
});
|
|
143
|
+
(0, node_fs_1.writeFileSync)(settingsAbs, content);
|
|
144
|
+
const loaded = (0, plugin_loader_js_1.loadPlugin)(dir, adapter.layout);
|
|
145
|
+
if (!loaded.settings.hooks) {
|
|
146
|
+
throw new Error(`Adapter "${adapter.name}": loadPlugin read no hooks from a ${adapter.layout.settingsFormat} settings file at ${adapter.layout.settingsPath} — the settings-format wiring is broken.`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
(0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=adapter-conformance.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter registry — the composition-root list the CLI uses to auto-detect which
|
|
3
|
+
* harness a repo targets. The library API selects an adapter by import
|
|
4
|
+
* (`vigiles/claude-code`); the CLI can't, so it walks this registry. Claude Code
|
|
5
|
+
* is the default, so detection is backwards-compatible: an undetected repo (or a
|
|
6
|
+
* repo with no adapter markers) resolves to Claude Code exactly as before.
|
|
7
|
+
*
|
|
8
|
+
* Adding a harness = add its `HarnessAdapter` to `ADAPTERS` (and a
|
|
9
|
+
* `vigiles/<harness>` export). Order matters only if two adapters could both
|
|
10
|
+
* match a repo; `detect()` returns a specificity score so the strongest signal
|
|
11
|
+
* wins regardless of order.
|
|
12
|
+
*/
|
|
13
|
+
import type { HarnessAdapter } from "./core/adapter.js";
|
|
14
|
+
/** The default adapter when detection finds no harness markers. */
|
|
15
|
+
export declare const defaultAdapter: HarnessAdapter;
|
|
16
|
+
/** All registered adapters. detect() specificity (not order) breaks ties. */
|
|
17
|
+
export declare const ADAPTERS: readonly HarnessAdapter[];
|
|
18
|
+
/** The result of auto-detecting a harness from a repo's layout. */
|
|
19
|
+
export interface DetectResult {
|
|
20
|
+
readonly adapter: HarnessAdapter;
|
|
21
|
+
/** True when detection found no harness markers and fell back to the default. */
|
|
22
|
+
readonly fallback: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Other adapters that matched at the same top specificity — a non-empty list
|
|
25
|
+
* means the repo looks like more than one harness (e.g. a CLAUDE.md + an
|
|
26
|
+
* AGENTS.md), so the pick is ambiguous; resolve with `--harness`.
|
|
27
|
+
*/
|
|
28
|
+
readonly ambiguousWith: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
/** Auto-detect the harness for a repo at `root` by highest detect() specificity. */
|
|
31
|
+
export declare function detectAdapterResult(root: string): DetectResult;
|
|
32
|
+
/** The detected adapter (highest specificity), else the default (Claude Code). */
|
|
33
|
+
export declare function detectAdapter(root: string): HarnessAdapter;
|
|
34
|
+
/** Look up a registered adapter by `name` (e.g. for a `--harness` override). */
|
|
35
|
+
export declare function getAdapter(name: string): HarnessAdapter | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the adapter for a command: an explicit `--harness <name>` wins (throws
|
|
38
|
+
* if unknown); otherwise auto-detect from `root`. The single entry point the CLI
|
|
39
|
+
* uses so detection + override live in one place.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveAdapter(root: string, harness?: string): HarnessAdapter;
|
|
42
|
+
//# sourceMappingURL=adapter-registry.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ADAPTERS = exports.defaultAdapter = void 0;
|
|
4
|
+
exports.detectAdapterResult = detectAdapterResult;
|
|
5
|
+
exports.detectAdapter = detectAdapter;
|
|
6
|
+
exports.getAdapter = getAdapter;
|
|
7
|
+
exports.resolveAdapter = resolveAdapter;
|
|
8
|
+
const adapter_js_1 = require("./adapters/claude-code/adapter.js");
|
|
9
|
+
const adapter_js_2 = require("./adapters/codex/adapter.js");
|
|
10
|
+
/** The default adapter when detection finds no harness markers. */
|
|
11
|
+
exports.defaultAdapter = adapter_js_1.claudeCodeAdapter;
|
|
12
|
+
/** All registered adapters. detect() specificity (not order) breaks ties. */
|
|
13
|
+
exports.ADAPTERS = [
|
|
14
|
+
adapter_js_1.claudeCodeAdapter,
|
|
15
|
+
adapter_js_2.codexAdapter,
|
|
16
|
+
];
|
|
17
|
+
/** Auto-detect the harness for a repo at `root` by highest detect() specificity. */
|
|
18
|
+
function detectAdapterResult(root) {
|
|
19
|
+
const scored = exports.ADAPTERS.map((a) => ({ a, score: a.detect(root) })).filter((s) => s.score > 0);
|
|
20
|
+
if (scored.length === 0) {
|
|
21
|
+
return { adapter: exports.defaultAdapter, fallback: true, ambiguousWith: [] };
|
|
22
|
+
}
|
|
23
|
+
const top = Math.max(...scored.map((s) => s.score));
|
|
24
|
+
const winners = scored.filter((s) => s.score === top).map((s) => s.a);
|
|
25
|
+
return {
|
|
26
|
+
adapter: winners[0],
|
|
27
|
+
fallback: false,
|
|
28
|
+
ambiguousWith: winners.slice(1).map((a) => a.name),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** The detected adapter (highest specificity), else the default (Claude Code). */
|
|
32
|
+
function detectAdapter(root) {
|
|
33
|
+
return detectAdapterResult(root).adapter;
|
|
34
|
+
}
|
|
35
|
+
/** Look up a registered adapter by `name` (e.g. for a `--harness` override). */
|
|
36
|
+
function getAdapter(name) {
|
|
37
|
+
return exports.ADAPTERS.find((a) => a.name === name);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the adapter for a command: an explicit `--harness <name>` wins (throws
|
|
41
|
+
* if unknown); otherwise auto-detect from `root`. The single entry point the CLI
|
|
42
|
+
* uses so detection + override live in one place.
|
|
43
|
+
*/
|
|
44
|
+
function resolveAdapter(root, harness) {
|
|
45
|
+
if (harness !== undefined) {
|
|
46
|
+
const a = getAdapter(harness);
|
|
47
|
+
if (!a) {
|
|
48
|
+
const known = exports.ADAPTERS.map((x) => x.name).join(", ");
|
|
49
|
+
throw new Error(`Unknown harness "${harness}". Known: ${known}.`);
|
|
50
|
+
}
|
|
51
|
+
return a;
|
|
52
|
+
}
|
|
53
|
+
return detectAdapter(root);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=adapter-registry.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vigiles/adapter` — the harness-adapter authoring kit.
|
|
3
|
+
*
|
|
4
|
+
* Everything you need to teach vigiles a new harness, in one import: the five
|
|
5
|
+
* port interfaces to implement, the `HarnessAdapter` bundle that groups them,
|
|
6
|
+
* the conformance kit to validate yours, and the registry the CLI detects
|
|
7
|
+
* through. vigiles ships a Claude Code adapter; building your own is welcome and
|
|
8
|
+
* supported — see `docs/authoring-an-adapter.md`.
|
|
9
|
+
*
|
|
10
|
+
* import {
|
|
11
|
+
* type HarnessAdapter, type HarnessDialect, type PluginLayout,
|
|
12
|
+
* type HarnessRuntime, type HookProtocol, type ModelMock,
|
|
13
|
+
* assertAdapterConformance,
|
|
14
|
+
* } from "vigiles/adapter";
|
|
15
|
+
*
|
|
16
|
+
* export const myHarnessAdapter: HarnessAdapter = { name: "my-harness", … };
|
|
17
|
+
*/
|
|
18
|
+
export type { HarnessAdapter, AdapterCapabilities } from "./core/adapter.js";
|
|
19
|
+
export type { HarnessDialect } from "./core/dialect.js";
|
|
20
|
+
export type { PluginLayout } from "./core/layout.js";
|
|
21
|
+
export type { HarnessRuntime } from "./core/runtime.js";
|
|
22
|
+
export type { HookProtocol } from "./core/hook-protocol.js";
|
|
23
|
+
export type { ModelMock } from "./core/model-mock.js";
|
|
24
|
+
export { checkAdapterConformance, assertAdapterConformance, assertAdapterLoadsHooks, assertHarnessTestable, type ConformanceResult, } from "./adapter-conformance.js";
|
|
25
|
+
export { ADAPTERS, defaultAdapter, detectAdapter, detectAdapterResult, resolveAdapter, getAdapter, type DetectResult, } from "./adapter-registry.js";
|
|
26
|
+
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAdapter = exports.resolveAdapter = exports.detectAdapterResult = exports.detectAdapter = exports.defaultAdapter = exports.ADAPTERS = exports.assertHarnessTestable = exports.assertAdapterLoadsHooks = exports.assertAdapterConformance = exports.checkAdapterConformance = void 0;
|
|
4
|
+
var adapter_conformance_js_1 = require("./adapter-conformance.js");
|
|
5
|
+
Object.defineProperty(exports, "checkAdapterConformance", { enumerable: true, get: function () { return adapter_conformance_js_1.checkAdapterConformance; } });
|
|
6
|
+
Object.defineProperty(exports, "assertAdapterConformance", { enumerable: true, get: function () { return adapter_conformance_js_1.assertAdapterConformance; } });
|
|
7
|
+
Object.defineProperty(exports, "assertAdapterLoadsHooks", { enumerable: true, get: function () { return adapter_conformance_js_1.assertAdapterLoadsHooks; } });
|
|
8
|
+
Object.defineProperty(exports, "assertHarnessTestable", { enumerable: true, get: function () { return adapter_conformance_js_1.assertHarnessTestable; } });
|
|
9
|
+
var adapter_registry_js_1 = require("./adapter-registry.js");
|
|
10
|
+
Object.defineProperty(exports, "ADAPTERS", { enumerable: true, get: function () { return adapter_registry_js_1.ADAPTERS; } });
|
|
11
|
+
Object.defineProperty(exports, "defaultAdapter", { enumerable: true, get: function () { return adapter_registry_js_1.defaultAdapter; } });
|
|
12
|
+
Object.defineProperty(exports, "detectAdapter", { enumerable: true, get: function () { return adapter_registry_js_1.detectAdapter; } });
|
|
13
|
+
Object.defineProperty(exports, "detectAdapterResult", { enumerable: true, get: function () { return adapter_registry_js_1.detectAdapterResult; } });
|
|
14
|
+
Object.defineProperty(exports, "resolveAdapter", { enumerable: true, get: function () { return adapter_registry_js_1.resolveAdapter; } });
|
|
15
|
+
Object.defineProperty(exports, "getAdapter", { enumerable: true, get: function () { return adapter_registry_js_1.getAdapter; } });
|
|
16
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.claudeCodeAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* claudeCodeAdapter — the Claude Code `HarnessAdapter`: the five port
|
|
6
|
+
* implementations bundled, plus a `detect` that recognizes a Claude Code repo
|
|
7
|
+
* (a `.claude-plugin/` manifest, a `.claude/settings.json`, or a `CLAUDE.md`).
|
|
8
|
+
* This is the reference adapter a second harness (Codex, Gemini, …) mirrors.
|
|
9
|
+
*/
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const dialect_js_1 = require("./dialect.js");
|
|
13
|
+
const layout_js_1 = require("./layout.js");
|
|
14
|
+
const runtime_js_1 = require("./runtime.js");
|
|
15
|
+
const hook_protocol_js_1 = require("./hook-protocol.js");
|
|
16
|
+
const model_mock_js_1 = require("./model-mock.js");
|
|
17
|
+
const harness_test_js_1 = require("./harness-test.js");
|
|
18
|
+
exports.claudeCodeAdapter = {
|
|
19
|
+
name: "claude-code",
|
|
20
|
+
// The reference harness: every tier. Mockable transport (Anthropic SSE) and
|
|
21
|
+
// shell hooks (exit 2 / decision JSON) — both pillars, all tiers.
|
|
22
|
+
capabilities: {
|
|
23
|
+
referenceVerification: true,
|
|
24
|
+
harnessTesting: true,
|
|
25
|
+
shellHooks: true,
|
|
26
|
+
},
|
|
27
|
+
dialect: dialect_js_1.claudeCodeDialect,
|
|
28
|
+
layout: layout_js_1.claudeCodeLayout,
|
|
29
|
+
runtime: runtime_js_1.claudeCodeRuntime,
|
|
30
|
+
hookProtocol: hook_protocol_js_1.claudeCodeHookProtocol,
|
|
31
|
+
modelMock: model_mock_js_1.claudeCodeModelMock,
|
|
32
|
+
harnessTestDriver: harness_test_js_1.claudeCodeDriver,
|
|
33
|
+
detect(root) {
|
|
34
|
+
// Most specific signal wins: a plugin manifest (3) > repo settings (2) >
|
|
35
|
+
// a bare CLAUDE.md (1, weak — many tools also read it / AGENTS.md).
|
|
36
|
+
const has = (rel) => (0, node_fs_1.existsSync)((0, node_path_1.join)(root, rel));
|
|
37
|
+
if (has(layout_js_1.claudeCodeLayout.manifestPath))
|
|
38
|
+
return 3;
|
|
39
|
+
if (has(layout_js_1.claudeCodeLayout.settingsPath))
|
|
40
|
+
return 2;
|
|
41
|
+
if (has(layout_js_1.claudeCodeLayout.instructionFile))
|
|
42
|
+
return 1;
|
|
43
|
+
return 0;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* third `malformed` track for a worker that didn't honor its contract (no block,
|
|
18
18
|
* bad JSON, or a shape that doesn't match the declared schema).
|
|
19
19
|
*/
|
|
20
|
-
import type { OutputContract } from "
|
|
20
|
+
import type { OutputContract } from "../../core/spec.js";
|
|
21
21
|
/** The outcome of parsing a worker's result block. */
|
|
22
22
|
export type ParsedAgentResult<S = Record<string, unknown>, E = Record<string, unknown>> = {
|
|
23
23
|
readonly kind: "ok";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* claudeCodeDialect — the Claude Code adapter's `HarnessDialect` (format axis).
|
|
3
|
+
* The concrete dialect is DEFINED here, in the adapter, symmetric with the other
|
|
4
|
+
* four ports (`claudeCodeLayout`/`Runtime`/`HookProtocol`/`ModelMock`): the core
|
|
5
|
+
* holds only the `HarnessDialect` interface and never a harness's vocabulary. The
|
|
6
|
+
* compiler/validator receive this by injection (`compileAgent(spec, { dialect })`,
|
|
7
|
+
* the CLI/composition root supplies it). A second harness defines its own dialect
|
|
8
|
+
* in its adapter (e.g. `src/adapters/codex/dialect.ts` exporting `codexDialect`).
|
|
9
|
+
*/
|
|
10
|
+
import type { HarnessDialect } from "../../core/dialect.js";
|
|
11
|
+
export declare const claudeCodeDialect: HarnessDialect;
|
|
12
|
+
export type { HarnessDialect } from "../../core/dialect.js";
|
|
13
|
+
//# sourceMappingURL=dialect.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.claudeCodeDialect = void 0;
|
|
4
|
+
exports.claudeCodeDialect = {
|
|
5
|
+
name: "claude-code",
|
|
6
|
+
// The tool contract a subagent may declare — the rails it runs on. Anything
|
|
7
|
+
// else must be an MCP tool, else it's a typo / nonexistent tool.
|
|
8
|
+
builtinAgentTools: [
|
|
9
|
+
"Read",
|
|
10
|
+
"Write",
|
|
11
|
+
"Edit",
|
|
12
|
+
"Bash",
|
|
13
|
+
"Grep",
|
|
14
|
+
"Glob",
|
|
15
|
+
"WebSearch",
|
|
16
|
+
"WebFetch",
|
|
17
|
+
"NotebookEdit",
|
|
18
|
+
"TodoWrite",
|
|
19
|
+
"Task",
|
|
20
|
+
"Skill",
|
|
21
|
+
],
|
|
22
|
+
// Tools the platform never exposes to a subagent, whatever the list says — so
|
|
23
|
+
// a subagent listing one is a guaranteed-dead reference only a compiler catches.
|
|
24
|
+
neverAvailableTools: [
|
|
25
|
+
"Agent",
|
|
26
|
+
"AskUserQuestion",
|
|
27
|
+
"EnterPlanMode",
|
|
28
|
+
"ExitPlanMode",
|
|
29
|
+
"ScheduleWakeup",
|
|
30
|
+
"WaitForMcpServers",
|
|
31
|
+
],
|
|
32
|
+
mcpToolPattern: /^mcp__[a-z0-9_-]+__[a-z0-9_-]+$/i,
|
|
33
|
+
hookEvents: [
|
|
34
|
+
"PreToolUse",
|
|
35
|
+
"PostToolUse",
|
|
36
|
+
"PreSession",
|
|
37
|
+
"PostSession",
|
|
38
|
+
"Notification",
|
|
39
|
+
],
|
|
40
|
+
// Claude Code natively reads CLAUDE.md only — it does NOT auto-load AGENTS.md
|
|
41
|
+
// (anthropics/claude-code#34235 is open; AGENTS.md works solely via an
|
|
42
|
+
// `@AGENTS.md` import inside CLAUDE.md or a symlink). AGENTS.md is the
|
|
43
|
+
// cross-tool standard (Codex's native target), not a CC dialect fact; vigiles's
|
|
44
|
+
// tool-agnostic recognition of it lives in validate.ts's INSTRUCTION_FILES.
|
|
45
|
+
instructionTargets: ["CLAUDE.md"],
|
|
46
|
+
pluginRootToken: "${CLAUDE_PLUGIN_ROOT}",
|
|
47
|
+
// Claude Code reads the full SKILL.md frontmatter set (description,
|
|
48
|
+
// disable-model-invocation, argument-hint, …).
|
|
49
|
+
skillFrontmatter: "claude-code",
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=dialect.js.map
|