coding-agent-skills 0.2.14 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +31 -1
- package/ROADMAP.md +7 -2
- package/bin/coding-agent-skills +340 -2
- package/docs/adapters/README.md +21 -0
- package/docs/adapters/project-installation.md +14 -0
- package/docs/adapters/real-project-adoption.md +2 -2
- package/docs/architecture/README.md +3 -2
- package/docs/release/README.md +13 -10
- package/docs/release/npm-package.md +27 -2
- package/docs/safety/README.md +6 -1
- package/docs/testing/README.md +16 -0
- package/docs/usage/README.md +59 -5
- package/examples/command-policies/deployment-preflight.json +70 -0
- package/examples/evidence-packs/deployment-preflight.json +60 -0
- package/examples/manifests/deployment-preflight.json +14 -0
- package/examples/workflows/deployment-preflight.md +8 -0
- package/package.json +2 -1
- package/runs/skill-runs.md +36 -0
- package/schemas/project-adapter-installation.schema.json +2 -0
- package/schemas/project-adapter.schema.json +2 -0
- package/scripts/lib/deployment-preflight.mjs +655 -0
- package/scripts/lib/pack-rules.mjs +11 -2
- package/scripts/render-deployment-preflight.mjs +9 -0
- package/scripts/test-pack.mjs +151 -1
- package/scripts/validate-pack.mjs +5 -2
- package/skills/deployment-preflight/SKILL.md +89 -0
- package/skills/deployment-preflight/adapter-interface.md +17 -0
- package/skills/deployment-preflight/agents/openai.yaml +3 -0
- package/skills/deployment-preflight/checklist.md +7 -0
- package/skills/deployment-preflight/evidence-template.md +19 -0
- package/skills/deployment-preflight/examples.md +11 -0
- package/skills/deployment-preflight/failure-modes.md +11 -0
- package/tests/fixtures/deployment-preflight/adapter-project/.coding-agent/adapters/deployment-preflight-fixture/adapter.json +56 -0
- package/tests/fixtures/deployment-preflight/adapter-project/.coding-agent/skills.json +23 -0
- package/tests/fixtures/deployment-preflight/adapter-project/README.md +3 -0
- package/tests/fixtures/deployment-preflight/adapter-project/deploy/netlify.toml +3 -0
- package/tests/fixtures/deployment-preflight/adapter-project/ignored/render.yaml +3 -0
- package/tests/fixtures/deployment-preflight/adapter-project/package.json +5 -0
- package/tests/fixtures/deployment-preflight/static-project/Dockerfile +2 -0
- package/tests/fixtures/deployment-preflight/static-project/README.md +3 -0
- package/tests/fixtures/deployment-preflight/static-project/docs/deployment.md +4 -0
- package/tests/fixtures/deployment-preflight/static-project/package.json +6 -0
- package/tests/fixtures/deployment-preflight/static-project/src/index.js +1 -0
- package/tests/fixtures/deployment-preflight/static-project/wrangler.toml +3 -0
- package/tests/fixtures/triggers/cases.json +13 -1
- package/tests/trigger/README.md +2 -0
- package/work-ledger.md +33 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes follow [Semantic Versioning](docs/versioning/README.md).
|
|
4
4
|
|
|
5
|
+
## [0.2.16] - 2026-07-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Optional `--json` output for every public `coding-agent-skills` CLI command.
|
|
10
|
+
- OpenClaw-compatible structured result fields for command identity, skill id, package
|
|
11
|
+
version, status, findings, warnings, skipped checks, refused behavior, safety summary,
|
|
12
|
+
`recommendedNextAction`, and exit-code meaning.
|
|
13
|
+
- Release tests that validate the JSON contract across the public CLI surface and confirm
|
|
14
|
+
redaction of local home paths and secret-like values.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- The public wrapper now preserves default human-readable output while offering sanitized
|
|
19
|
+
machine-readable results for orchestrator callers.
|
|
20
|
+
- Usage, release, testing, roadmap, ledger, and run-log docs now describe the exit-code
|
|
21
|
+
contract and OpenClaw integration boundary.
|
|
22
|
+
- Stale v0.2.15 ledger and run-log entries now reflect that the deployment-preflight
|
|
23
|
+
release was published, smoke-tested, and released.
|
|
24
|
+
|
|
25
|
+
## [0.2.15] - 2026-07-03
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `deployment-preflight` audit-only skill for static deployment readiness evidence
|
|
30
|
+
mapping before separately approved deployment work.
|
|
31
|
+
- `coding-agent-skills deployment-preflight <project-root>` CLI command.
|
|
32
|
+
- Dependency-free deployment preflight renderer for deployment config files, deployment
|
|
33
|
+
docs, package script keys without command values, platform indicators, static risk
|
|
34
|
+
indicators, adapter-limited scope, skipped paths, not-verified provider/runtime areas,
|
|
35
|
+
and safety refusals.
|
|
36
|
+
- Synthetic deployment-preflight fixtures and release tests for generic static scans,
|
|
37
|
+
adapter-scoped scans, package script key detection, platform indicators, and
|
|
38
|
+
repo-map-only adapter skips.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Adapter schemas and validators now recognize `deployment-preflight` as an audit-only
|
|
43
|
+
skill while preserving the existing `0.2.3` adapter contract compatibility baseline.
|
|
44
|
+
- Usage, release, safety, architecture, adapter, roadmap, ledger, and run-log docs now
|
|
45
|
+
describe the new static read-only deployment preflight command.
|
|
46
|
+
|
|
5
47
|
## [0.2.14] - 2026-07-03
|
|
6
48
|
|
|
7
49
|
### Added
|
package/README.md
CHANGED
|
@@ -12,12 +12,13 @@ The pilot pack contains:
|
|
|
12
12
|
- `api-contract-audit`: audit-only static API contract surface mapping.
|
|
13
13
|
- `migration-review`: audit-only static migration and schema evidence review.
|
|
14
14
|
- `github-handoff`: audit-only local Git handoff evidence before separately approved GitHub work.
|
|
15
|
+
- `deployment-preflight`: audit-only static deployment readiness evidence mapping.
|
|
15
16
|
- `build-verify`: controlled local validation using existing project commands.
|
|
16
17
|
- `git-preflight`: audit-only Git readiness inspection.
|
|
17
18
|
- `runtime-truth`: audit-only runtime evidence collection.
|
|
18
19
|
- `llm-drift-control`: audit-only claim reconciliation.
|
|
19
20
|
|
|
20
|
-
It does not contain deployment, package installation, Git publication, runtime mutation, migration, privileged API, platform-specific, or project-specific skills.
|
|
21
|
+
It does not contain deployment execution, package installation, Git publication, runtime mutation, migration application, privileged API, platform-specific deployment automation, or project-specific skills.
|
|
21
22
|
|
|
22
23
|
Project-specific adapters will live in their owning repositories and may narrow, but never weaken, shared safety rules.
|
|
23
24
|
|
|
@@ -50,6 +51,10 @@ Every skill emits the evidence-pack contract. A command being attempted is never
|
|
|
50
51
|
- Map static API contract surfaces with `coding-agent-skills api-contract-audit <project-root>`.
|
|
51
52
|
- Review static migration and schema evidence with `coding-agent-skills migration-review <project-root>`.
|
|
52
53
|
- Prepare local Git handoff evidence with `coding-agent-skills github-handoff <project-root>`.
|
|
54
|
+
- Map static deployment readiness evidence with `coding-agent-skills deployment-preflight <project-root>`.
|
|
55
|
+
- Add `--json` to any public CLI command when an OpenClaw-style orchestrator
|
|
56
|
+
needs a sanitized machine-readable result with `success`, `status`,
|
|
57
|
+
`recommendedNextAction`, safety flags, and exit-code meaning.
|
|
53
58
|
- Validate project adapters against [the formal adapter schema](schemas/project-adapter.schema.json).
|
|
54
59
|
- Review [external adapter discovery](docs/adapters/discovery.md).
|
|
55
60
|
- Run `node scripts/validate-adapters.mjs <adapter-root>` for a disposable external root.
|
|
@@ -67,6 +72,8 @@ Every skill emits the evidence-pack contract. A command being attempted is never
|
|
|
67
72
|
`node scripts/render-migration-review.mjs <project-root>`.
|
|
68
73
|
- Render a local GitHub handoff report with
|
|
69
74
|
`node scripts/render-github-handoff.mjs <project-root>`.
|
|
75
|
+
- Render a static deployment preflight report with
|
|
76
|
+
`node scripts/render-deployment-preflight.mjs <project-root>`.
|
|
70
77
|
- Review [adapter upgrade checks](docs/adapters/upgrades.md).
|
|
71
78
|
- Run `node scripts/check-adapter-upgrade.mjs <before-project-root> <after-project-root>`
|
|
72
79
|
for disposable project revisions.
|
|
@@ -88,6 +95,29 @@ Every skill emits the evidence-pack contract. A command being attempted is never
|
|
|
88
95
|
Governance lives in [CONTRIBUTING.md](CONTRIBUTING.md), [ROADMAP.md](ROADMAP.md), and the [release policy](docs/release/README.md).
|
|
89
96
|
The [harness guide](docs/testing/README.md) explains trigger, command, mutation, privacy, adapter, and completion checks.
|
|
90
97
|
|
|
98
|
+
## Orchestrator Output
|
|
99
|
+
|
|
100
|
+
The default CLI output remains human-readable. OpenClaw-style callers can request a
|
|
101
|
+
structured result with `--json`:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
coding-agent-skills repo-map /path/to/project --json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
JSON output is read-only and sanitized. It includes command identity, package version,
|
|
108
|
+
skill id, status, findings, warnings, skipped checks, refused behavior, safety flags,
|
|
109
|
+
and `recommendedNextAction`. Exit codes follow the public contract:
|
|
110
|
+
|
|
111
|
+
- `0`: handled execution path, including complete, partial, blocked, or controlled audit results
|
|
112
|
+
- `2`: usage error
|
|
113
|
+
- `3`: safety refusal
|
|
114
|
+
- `4`: missing required input or file
|
|
115
|
+
- `5`: unexpected internal or runtime failure
|
|
116
|
+
|
|
117
|
+
OpenClaw should remain the owner of memory, routing, permissions, scheduling, user
|
|
118
|
+
interaction, and workflow state. `coding-agent-skills` is a safe callable evidence
|
|
119
|
+
producer, not an orchestrator.
|
|
120
|
+
|
|
91
121
|
## Autonomous Maintainer Loop
|
|
92
122
|
|
|
93
123
|
The local maintainer loop reads Git tags, `ROADMAP.md`, `CHANGELOG.md`, and
|
package/ROADMAP.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
-
The public package now contains
|
|
3
|
+
The public package now contains twelve approved shared skills. Builder-mode approval is
|
|
4
4
|
active for the remaining read-only skill wave in this repository; real-world project
|
|
5
5
|
execution constraints remain unchanged.
|
|
6
6
|
|
|
@@ -40,6 +40,10 @@ execution constraints remain unchanged.
|
|
|
40
40
|
and schema evidence review.
|
|
41
41
|
- `v0.2.14`: audit-only `github-handoff` skill and CLI renderer for local Git handoff
|
|
42
42
|
evidence before separately approved GitHub work.
|
|
43
|
+
- `v0.2.15`: audit-only `deployment-preflight` skill and CLI renderer for static
|
|
44
|
+
deployment readiness evidence before separately approved deployment work.
|
|
45
|
+
- `v0.2.16`: OpenClaw-compatible optional `--json` output and documented exit-code
|
|
46
|
+
semantics for every public CLI command.
|
|
43
47
|
|
|
44
48
|
The next milestone is recorded in [work-ledger.md](work-ledger.md). The
|
|
45
49
|
[maintainer loop](RUNBOOK.md) may select and evidence that milestone, but it must stop
|
|
@@ -86,7 +90,8 @@ Next safe milestone options:
|
|
|
86
90
|
| `api-contract-audit-skill` | General | Audit-only | Implemented in `v0.2.12` |
|
|
87
91
|
| `migration-review-skill` | General with platform adapters | Audit-only | Implemented in `v0.2.13` |
|
|
88
92
|
| `github-handoff-skill` | General | Audit-only | Implemented in `v0.2.14` |
|
|
89
|
-
| `deployment-preflight-skill` | General | Audit-only |
|
|
93
|
+
| `deployment-preflight-skill` | General | Audit-only | Implemented in `v0.2.15` |
|
|
94
|
+
| `orchestrator-json-output-contract` | General tooling | Read-only CLI contract | Implemented in `v0.2.16` |
|
|
90
95
|
| `cloudflare-preflight-skill` | Platform-specific | Audit-only | Builder-mode approved; later in wave |
|
|
91
96
|
| `cloudflare-deploy-skill` | Platform-specific | Action-capable | Blocked on approval model |
|
|
92
97
|
| `supabase-rls-audit-skill` | Platform-specific | Audit-only | Builder-mode approved; later in wave |
|
package/bin/coding-agent-skills
CHANGED
|
@@ -1,9 +1,125 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
|
|
7
|
+
import { externalAdapterCliResult } from "../scripts/lib/adapter-discovery.mjs";
|
|
8
|
+
import { adapterRepoMapCliResult } from "../scripts/lib/adapter-repo-map.mjs";
|
|
9
|
+
import { apiContractAuditCliResult } from "../scripts/lib/api-contract-audit.mjs";
|
|
10
|
+
import { deploymentPreflightCliResult } from "../scripts/lib/deployment-preflight.mjs";
|
|
11
|
+
import { envAuditCliResult } from "../scripts/lib/env-audit.mjs";
|
|
12
|
+
import { githubHandoffCliResult } from "../scripts/lib/github-handoff.mjs";
|
|
13
|
+
import { migrationReviewCliResult } from "../scripts/lib/migration-review.mjs";
|
|
14
|
+
import { redactSensitiveText } from "../scripts/lib/pack-rules.mjs";
|
|
15
|
+
import { projectAdapterCliResult } from "../scripts/lib/project-adapter-installation.mjs";
|
|
16
|
+
import { routeTraceCliResult } from "../scripts/lib/route-trace.mjs";
|
|
17
|
+
import { secretAuditCliResult } from "../scripts/lib/secret-audit.mjs";
|
|
18
|
+
|
|
6
19
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(repoRoot, "package.json"), "utf8"));
|
|
21
|
+
|
|
22
|
+
const commandMetadata = {
|
|
23
|
+
"validate-pack": {
|
|
24
|
+
skillId: "pack-validation",
|
|
25
|
+
mode: "validation",
|
|
26
|
+
next: {
|
|
27
|
+
label: "Select a read-only audit command",
|
|
28
|
+
reason: "The package is structurally valid; choose the narrowest command for the target task.",
|
|
29
|
+
requiresApproval: false,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
"validate-project": {
|
|
33
|
+
skillId: "project-adapter-validation",
|
|
34
|
+
mode: "validation",
|
|
35
|
+
next: {
|
|
36
|
+
label: "Run an adapter-aware read-only report",
|
|
37
|
+
reason: "The project adapter declaration is valid; use a scoped report command next.",
|
|
38
|
+
requiresApproval: false,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
"repo-map": {
|
|
42
|
+
skillId: "repo-map",
|
|
43
|
+
mode: "audit-only",
|
|
44
|
+
next: {
|
|
45
|
+
label: "Review adapter-declared repo boundaries",
|
|
46
|
+
reason: "Use the reported docs, safe paths, ignored paths, and evidence requirements before choosing another action.",
|
|
47
|
+
requiresApproval: false,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"route-trace": {
|
|
51
|
+
skillId: "route-trace",
|
|
52
|
+
mode: "audit-only",
|
|
53
|
+
next: {
|
|
54
|
+
label: "Review static route findings",
|
|
55
|
+
reason: "Inspect verified and inferred route surfaces before approving code or runtime work.",
|
|
56
|
+
requiresApproval: false,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
"env-audit": {
|
|
60
|
+
skillId: "env-audit",
|
|
61
|
+
mode: "audit-only",
|
|
62
|
+
next: {
|
|
63
|
+
label: "Review variable-name inventory",
|
|
64
|
+
reason: "Use value-free environment names to plan documentation or configuration review without reading secrets.",
|
|
65
|
+
requiresApproval: false,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
"secret-audit": {
|
|
69
|
+
skillId: "secret-audit",
|
|
70
|
+
mode: "audit-only",
|
|
71
|
+
next: {
|
|
72
|
+
label: "Review redacted secret-risk findings",
|
|
73
|
+
reason: "Any remediation, credential rotation, or repository mutation needs separate approval.",
|
|
74
|
+
requiresApproval: true,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
"api-contract-audit": {
|
|
78
|
+
skillId: "api-contract-audit",
|
|
79
|
+
mode: "audit-only",
|
|
80
|
+
next: {
|
|
81
|
+
label: "Review static API contract surfaces",
|
|
82
|
+
reason: "Use contract, endpoint, client, and schema evidence before editing API code.",
|
|
83
|
+
requiresApproval: false,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
"migration-review": {
|
|
87
|
+
skillId: "migration-review",
|
|
88
|
+
mode: "audit-only",
|
|
89
|
+
next: {
|
|
90
|
+
label: "Review migration evidence",
|
|
91
|
+
reason: "Database access, migration edits, generation, or execution require separate approval.",
|
|
92
|
+
requiresApproval: true,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
"github-handoff": {
|
|
96
|
+
skillId: "github-handoff",
|
|
97
|
+
mode: "audit-only",
|
|
98
|
+
next: {
|
|
99
|
+
label: "Request explicit GitHub handoff approval",
|
|
100
|
+
reason: "Commit, push, tag, pull request, or API mutation work is outside this read-only report.",
|
|
101
|
+
requiresApproval: true,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
"deployment-preflight": {
|
|
105
|
+
skillId: "deployment-preflight",
|
|
106
|
+
mode: "audit-only",
|
|
107
|
+
next: {
|
|
108
|
+
label: "Request explicit deployment approval",
|
|
109
|
+
reason: "Deployment, provider API, provider CLI, build, runtime, or migration work is outside this read-only report.",
|
|
110
|
+
requiresApproval: true,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
"validate-adapters": {
|
|
114
|
+
skillId: "external-adapter-validation",
|
|
115
|
+
mode: "validation",
|
|
116
|
+
next: {
|
|
117
|
+
label: "Use accepted adapters only as narrowing metadata",
|
|
118
|
+
reason: "Adapters may narrow safe context but must not grant new powers or weaken shared restrictions.",
|
|
119
|
+
requiresApproval: false,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
7
123
|
|
|
8
124
|
const commands = {
|
|
9
125
|
"validate-pack": {
|
|
@@ -59,6 +175,12 @@ const commands = {
|
|
|
59
175
|
usage: "coding-agent-skills github-handoff <project-root>",
|
|
60
176
|
requiredArgs: 1,
|
|
61
177
|
},
|
|
178
|
+
"deployment-preflight": {
|
|
179
|
+
script: "scripts/render-deployment-preflight.mjs",
|
|
180
|
+
args: ([projectRoot]) => [projectRoot],
|
|
181
|
+
usage: "coding-agent-skills deployment-preflight <project-root>",
|
|
182
|
+
requiredArgs: 1,
|
|
183
|
+
},
|
|
62
184
|
"validate-adapters": {
|
|
63
185
|
script: "scripts/validate-adapters.mjs",
|
|
64
186
|
args: ([adapterRoot]) => [adapterRoot],
|
|
@@ -67,6 +189,29 @@ const commands = {
|
|
|
67
189
|
},
|
|
68
190
|
};
|
|
69
191
|
|
|
192
|
+
const jsonHandlers = {
|
|
193
|
+
"validate-project": ([projectRoot]) => projectAdapterCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
194
|
+
"repo-map": ([projectRoot]) => adapterRepoMapCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
195
|
+
"route-trace": ([projectRoot]) => routeTraceCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
196
|
+
"env-audit": ([projectRoot]) => envAuditCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
197
|
+
"secret-audit": ([projectRoot]) => secretAuditCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
198
|
+
"api-contract-audit": ([projectRoot]) => apiContractAuditCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
199
|
+
"migration-review": ([projectRoot]) => migrationReviewCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
200
|
+
"github-handoff": ([projectRoot]) => githubHandoffCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
201
|
+
"deployment-preflight": ([projectRoot]) => deploymentPreflightCliResult(projectRoot, { coreRoot: repoRoot }),
|
|
202
|
+
"validate-adapters": ([adapterRoot]) => externalAdapterCliResult(adapterRoot, { coreRoot: repoRoot }),
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
function stripJsonFlag(args) {
|
|
206
|
+
let json = false;
|
|
207
|
+
const rest = [];
|
|
208
|
+
for (const arg of args) {
|
|
209
|
+
if (arg === "--json") json = true;
|
|
210
|
+
else rest.push(arg);
|
|
211
|
+
}
|
|
212
|
+
return { json, args: rest };
|
|
213
|
+
}
|
|
214
|
+
|
|
70
215
|
function usage(exitCode = 0) {
|
|
71
216
|
const lines = [
|
|
72
217
|
"usage: coding-agent-skills <command> [args]",
|
|
@@ -81,6 +226,7 @@ function usage(exitCode = 0) {
|
|
|
81
226
|
" api-contract-audit <project-root>",
|
|
82
227
|
" migration-review <project-root>",
|
|
83
228
|
" github-handoff <project-root>",
|
|
229
|
+
" deployment-preflight <project-root>",
|
|
84
230
|
" validate-adapters <adapter-root>",
|
|
85
231
|
"",
|
|
86
232
|
"local wrapper for the published coding-agent-skills package",
|
|
@@ -90,7 +236,192 @@ function usage(exitCode = 0) {
|
|
|
90
236
|
process.exitCode = exitCode;
|
|
91
237
|
}
|
|
92
238
|
|
|
93
|
-
|
|
239
|
+
function sanitizedLines(text) {
|
|
240
|
+
return redactSensitiveText(text)
|
|
241
|
+
.split(/\r?\n/)
|
|
242
|
+
.map((line) => line.trimEnd())
|
|
243
|
+
.filter((line) => line.length > 0);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function sectionLines(lines, heading) {
|
|
247
|
+
const result = [];
|
|
248
|
+
let active = false;
|
|
249
|
+
for (const line of lines) {
|
|
250
|
+
if (line === `## ${heading}`) {
|
|
251
|
+
active = true;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (active && line.startsWith("## ")) break;
|
|
255
|
+
if (active && line.trim()) result.push(line.replace(/^- /, ""));
|
|
256
|
+
}
|
|
257
|
+
return result.filter((line) => line !== "none" && line !== "none found");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function detectedStatus(lines, exitCode) {
|
|
261
|
+
for (const line of lines) {
|
|
262
|
+
const match = /^Status:\s*([a-z-]+)/i.exec(line);
|
|
263
|
+
if (match) return match[1].toLowerCase();
|
|
264
|
+
}
|
|
265
|
+
if (exitCode === 0) return "complete";
|
|
266
|
+
if (exitCode === 2) return "failed";
|
|
267
|
+
return "failed";
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function exitCodeMeaning(exitCode) {
|
|
271
|
+
if (exitCode === 0) return "handled";
|
|
272
|
+
if (exitCode === 2) return "usage-error";
|
|
273
|
+
if (exitCode === 3) return "safety-refusal";
|
|
274
|
+
if (exitCode === 4) return "missing-required-input";
|
|
275
|
+
return "unexpected-internal-or-runtime-failure";
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function adapterSummary(lines) {
|
|
279
|
+
const adapter = {};
|
|
280
|
+
const adapterLines = [
|
|
281
|
+
...sectionLines(lines, "Adapter Scope"),
|
|
282
|
+
...sectionLines(lines, "Adapter Bounds"),
|
|
283
|
+
];
|
|
284
|
+
for (const line of adapterLines) {
|
|
285
|
+
const match = /^([^:]+):\s*(.*)$/.exec(line);
|
|
286
|
+
if (!match) continue;
|
|
287
|
+
const key = match[1]
|
|
288
|
+
.trim()
|
|
289
|
+
.replace(/[^a-zA-Z0-9]+([a-zA-Z0-9])/g, (_, char) => char.toUpperCase())
|
|
290
|
+
.replace(/^[A-Z]/, (char) => char.toLowerCase());
|
|
291
|
+
adapter[key] = match[2].trim();
|
|
292
|
+
}
|
|
293
|
+
return adapter;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function summaryLines(lines) {
|
|
297
|
+
return lines
|
|
298
|
+
.filter((line) => line.trim().length > 0)
|
|
299
|
+
.filter((line) => !line.startsWith("#"))
|
|
300
|
+
.filter((line) => !line.startsWith("## "))
|
|
301
|
+
.filter((line) => !line.startsWith("- "))
|
|
302
|
+
.slice(0, 12);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function findingLines(lines) {
|
|
306
|
+
const ignoredSections = new Set([
|
|
307
|
+
"Git State",
|
|
308
|
+
"Adapter Scope",
|
|
309
|
+
"Adapter Bounds",
|
|
310
|
+
"Scope Paths",
|
|
311
|
+
"Ignored Paths",
|
|
312
|
+
"Summary",
|
|
313
|
+
"Skipped",
|
|
314
|
+
"Not Verified",
|
|
315
|
+
"Warnings",
|
|
316
|
+
"Refused Behavior",
|
|
317
|
+
]);
|
|
318
|
+
const findings = [];
|
|
319
|
+
let current = null;
|
|
320
|
+
for (const line of lines) {
|
|
321
|
+
if (line.startsWith("## ")) {
|
|
322
|
+
current = line.replace(/^## /, "");
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (!current || ignoredSections.has(current)) continue;
|
|
326
|
+
if (line.startsWith("- ") && !line.includes("none found")) findings.push(line.slice(2));
|
|
327
|
+
}
|
|
328
|
+
return findings.slice(0, 100);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function normalizeOutcome(outcome) {
|
|
332
|
+
if (Array.isArray(outcome.lines)) {
|
|
333
|
+
return {
|
|
334
|
+
exitCode: outcome.exitCode ?? 5,
|
|
335
|
+
lines: outcome.lines
|
|
336
|
+
.map((line) => redactSensitiveText(line))
|
|
337
|
+
.filter((line) => line.trim().length > 0),
|
|
338
|
+
report: outcome.report ?? outcome.result ?? null,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
exitCode: outcome.status ?? 5,
|
|
344
|
+
lines: [
|
|
345
|
+
...sanitizedLines(outcome.stdout ?? ""),
|
|
346
|
+
...sanitizedLines(outcome.stderr ?? ""),
|
|
347
|
+
],
|
|
348
|
+
report: null,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function buildJsonResult(commandName, args, outcome) {
|
|
353
|
+
const normalized = normalizeOutcome(outcome);
|
|
354
|
+
const lines = normalized.lines;
|
|
355
|
+
const metadata = commandMetadata[commandName] ?? {
|
|
356
|
+
skillId: commandName,
|
|
357
|
+
mode: "unknown",
|
|
358
|
+
next: null,
|
|
359
|
+
};
|
|
360
|
+
const status = normalized.report?.status ?? detectedStatus(lines, normalized.exitCode);
|
|
361
|
+
const summary = summaryLines(lines);
|
|
362
|
+
const warnings = [
|
|
363
|
+
...(Array.isArray(normalized.report?.warnings)
|
|
364
|
+
? normalized.report.warnings.map((line) => redactSensitiveText(line))
|
|
365
|
+
: []),
|
|
366
|
+
...sectionLines(lines, "Warnings"),
|
|
367
|
+
...lines.filter((line) => /\bwarning\b/i.test(line) && !line.startsWith("## ")),
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
return {
|
|
371
|
+
success: normalized.exitCode === 0,
|
|
372
|
+
status,
|
|
373
|
+
tool: "coding-agent-skills",
|
|
374
|
+
command: commandName,
|
|
375
|
+
skillId: metadata.skillId,
|
|
376
|
+
packageVersion: packageJson.version,
|
|
377
|
+
mode: metadata.mode,
|
|
378
|
+
changedState: false,
|
|
379
|
+
summary: summary.length > 0
|
|
380
|
+
? summary
|
|
381
|
+
: [
|
|
382
|
+
normalized.exitCode === 0
|
|
383
|
+
? `${commandName} completed successfully`
|
|
384
|
+
: `${commandName} did not complete successfully`,
|
|
385
|
+
],
|
|
386
|
+
findings: Array.isArray(normalized.report?.findings)
|
|
387
|
+
? normalized.report.findings.map((finding) => redactSensitiveText(JSON.stringify(finding)))
|
|
388
|
+
: findingLines(lines),
|
|
389
|
+
warnings: [...new Set(warnings)],
|
|
390
|
+
risks: Array.isArray(normalized.report?.riskIndicators)
|
|
391
|
+
? normalized.report.riskIndicators.map((risk) => redactSensitiveText(JSON.stringify(risk)))
|
|
392
|
+
: sectionLines(lines, "Risk Indicators"),
|
|
393
|
+
skipped: Array.isArray(normalized.report?.skipped)
|
|
394
|
+
? normalized.report.skipped.map((item) => redactSensitiveText(JSON.stringify(item)))
|
|
395
|
+
: sectionLines(lines, "Skipped"),
|
|
396
|
+
notVerified: Array.isArray(normalized.report?.notVerified)
|
|
397
|
+
? normalized.report.notVerified.map((item) => redactSensitiveText(String(item)))
|
|
398
|
+
: sectionLines(lines, "Not Verified"),
|
|
399
|
+
refusedBehavior: Array.isArray(normalized.report?.refusedBehavior)
|
|
400
|
+
? normalized.report.refusedBehavior.map((item) => redactSensitiveText(String(item)))
|
|
401
|
+
: sectionLines(lines, "Refused Behavior"),
|
|
402
|
+
adapter: adapterSummary(lines),
|
|
403
|
+
recommendedNextAction: metadata.next,
|
|
404
|
+
safety: {
|
|
405
|
+
readOnly: true,
|
|
406
|
+
secretsRead: false,
|
|
407
|
+
targetCommandsRun: false,
|
|
408
|
+
mutationsPerformed: false,
|
|
409
|
+
},
|
|
410
|
+
exitCode: normalized.exitCode,
|
|
411
|
+
exitCodeMeaning: exitCodeMeaning(normalized.exitCode),
|
|
412
|
+
invocation: {
|
|
413
|
+
args: args.map((arg) => redactSensitiveText(arg)),
|
|
414
|
+
outputFormat: "json",
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function printJson(value) {
|
|
420
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const { json, args: rawArgs } = stripJsonFlag(process.argv.slice(2));
|
|
424
|
+
const [commandName, ...args] = rawArgs;
|
|
94
425
|
if (!commandName || commandName === "help" || commandName === "--help" || commandName === "-h") {
|
|
95
426
|
usage(commandName ? 0 : 2);
|
|
96
427
|
} else if (!Object.hasOwn(commands, commandName)) {
|
|
@@ -101,6 +432,10 @@ if (!commandName || commandName === "help" || commandName === "--help" || comman
|
|
|
101
432
|
if ((command.requiredArgs ?? 0) !== args.length) {
|
|
102
433
|
process.stderr.write(`usage: ${command.usage}\n`);
|
|
103
434
|
process.exitCode = 2;
|
|
435
|
+
} else if (json && jsonHandlers[commandName]) {
|
|
436
|
+
const outcome = jsonHandlers[commandName](args);
|
|
437
|
+
printJson(buildJsonResult(commandName, args, outcome));
|
|
438
|
+
process.exitCode = outcome.exitCode ?? 5;
|
|
104
439
|
} else {
|
|
105
440
|
const result = spawnSync(
|
|
106
441
|
process.execPath,
|
|
@@ -108,10 +443,13 @@ if (!commandName || commandName === "help" || commandName === "--help" || comman
|
|
|
108
443
|
{
|
|
109
444
|
cwd: repoRoot,
|
|
110
445
|
encoding: "utf8",
|
|
111
|
-
stdio: "inherit",
|
|
446
|
+
stdio: json ? "pipe" : "inherit",
|
|
112
447
|
shell: false,
|
|
113
448
|
},
|
|
114
449
|
);
|
|
450
|
+
if (json) {
|
|
451
|
+
printJson(buildJsonResult(commandName, args, result));
|
|
452
|
+
}
|
|
115
453
|
process.exitCode = result.status ?? 1;
|
|
116
454
|
}
|
|
117
455
|
}
|
package/docs/adapters/README.md
CHANGED
|
@@ -138,6 +138,24 @@ tags at HEAD, remote names, and changed-file summaries. It never prints remote U
|
|
|
138
138
|
reads tokens, creates pull requests, commits, pushes, tags, calls GitHub APIs, or mutates
|
|
139
139
|
project files.
|
|
140
140
|
|
|
141
|
+
## Adapter-Aware Deployment Preflight Consumption
|
|
142
|
+
|
|
143
|
+
The shared pack can consume a validated project-owned adapter as bounded context for
|
|
144
|
+
`deployment-preflight`:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
node scripts/render-deployment-preflight.mjs <project-root>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The renderer validates the project declaration when present. If an adapter is present but
|
|
151
|
+
does not enable `deployment-preflight`, it reports an adapter-limited skip instead of
|
|
152
|
+
broadening scope. When enabled, it reads only adapter-declared safe paths, excludes `.env`,
|
|
153
|
+
secret-bearing files, generated output, dependency paths, build output, runtime output,
|
|
154
|
+
and oversized files, then reports deployment config files, deployment docs, package
|
|
155
|
+
script keys, platform indicators, risk indicators, skipped paths, and not-verified
|
|
156
|
+
provider/runtime behavior. It never deploys, calls provider APIs, installs packages,
|
|
157
|
+
builds, tests, runs services, migrates, or mutates project files.
|
|
158
|
+
|
|
141
159
|
## What Adapters May Do
|
|
142
160
|
|
|
143
161
|
- Add bounded relative read paths and ignored paths.
|
|
@@ -153,6 +171,9 @@ project files.
|
|
|
153
171
|
files while relying on the shared reviewer to exclude secret-bearing paths.
|
|
154
172
|
- Add github-handoff required evidence labels and ignored path labels while relying on the
|
|
155
173
|
shared renderer to avoid remote URLs, tokens, and GitHub mutation.
|
|
174
|
+
- Add deployment-preflight safe read paths for static deployment config, docs, and package
|
|
175
|
+
metadata while relying on the shared preflight renderer to exclude secret-bearing paths
|
|
176
|
+
and avoid deployment behavior.
|
|
156
177
|
- Add command aliases that already satisfy the shared command policy.
|
|
157
178
|
- Add status-only runtime commands and manager hints.
|
|
158
179
|
- Require additional evidence or named approval for exceptional reads.
|
|
@@ -182,6 +182,20 @@ When enabled, it reports local Git metadata and changed-file summaries without p
|
|
|
182
182
|
remote URLs, reading tokens, creating pull requests, committing, pushing, tagging, calling
|
|
183
183
|
GitHub APIs, or changing project files.
|
|
184
184
|
|
|
185
|
+
A project-owned adapter can also enable read-only `deployment-preflight` context:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
node scripts/render-deployment-preflight.mjs <project-root>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The deployment preflight renderer validates the project declaration when present. If the
|
|
192
|
+
adapter is present but does not enable `deployment-preflight`, it reports an
|
|
193
|
+
adapter-limited skip. When enabled, it reads only adapter-declared safe paths and reports
|
|
194
|
+
static deployment config files, deployment docs, package script keys, platform indicators,
|
|
195
|
+
risk indicators, and not-verified provider/runtime behavior without deploying, calling
|
|
196
|
+
provider APIs, installing packages, building, testing, running services, or reading
|
|
197
|
+
secrets.
|
|
198
|
+
|
|
185
199
|
## Safety Boundary
|
|
186
200
|
|
|
187
201
|
Project adapters are extension-only. They cannot remove denied operations, change an
|
|
@@ -22,8 +22,8 @@ project repository is touched:
|
|
|
22
22
|
`coding-agent.skills.json`.
|
|
23
23
|
- The adapter need is bounded to existing pilot skills: `repo-map`, `route-trace`,
|
|
24
24
|
`env-audit`, `secret-audit`, `api-contract-audit`, `migration-review`,
|
|
25
|
-
`github-handoff`, `build-verify`, `git-preflight`,
|
|
26
|
-
`llm-drift-control`.
|
|
25
|
+
`github-handoff`, `deployment-preflight`, `build-verify`, `git-preflight`,
|
|
26
|
+
`runtime-truth`, or `llm-drift-control`.
|
|
27
27
|
- The adapter can narrow context with relative paths, documentation precedence, safe
|
|
28
28
|
aliases, status-only hints, or extra evidence requirements.
|
|
29
29
|
- The adapter does not require deployment, migration, package installation, Git
|
|
@@ -18,6 +18,7 @@ Audit-only:
|
|
|
18
18
|
- `api-contract-audit`
|
|
19
19
|
- `migration-review`
|
|
20
20
|
- `github-handoff`
|
|
21
|
+
- `deployment-preflight`
|
|
21
22
|
- `git-preflight`
|
|
22
23
|
- `runtime-truth`
|
|
23
24
|
- `llm-drift-control`
|
|
@@ -26,6 +27,6 @@ Controlled local validation:
|
|
|
26
27
|
|
|
27
28
|
- `build-verify`
|
|
28
29
|
|
|
29
|
-
The evidence pack is a shared output contract, not an executable skill.
|
|
30
|
-
|
|
30
|
+
The evidence pack is a shared output contract, not an executable skill. Provider
|
|
31
|
+
operations, deployment execution, and additional project adapters remain separate future
|
|
31
32
|
work.
|
package/docs/release/README.md
CHANGED
|
@@ -19,20 +19,23 @@
|
|
|
19
19
|
13. Inspect tarball contents for local-only files, credentials, `.env` files, dependency
|
|
20
20
|
folders, generated output, and unrelated repositories.
|
|
21
21
|
14. Install the tarball into a temporary npm prefix and smoke-test the installed CLI.
|
|
22
|
-
15. Smoke-test
|
|
22
|
+
15. Smoke-test human-readable and `--json` output for public commands touched by the
|
|
23
|
+
release. JSON output must include safety flags, `recommendedNextAction`, and
|
|
24
|
+
`exitCodeMeaning` without secrets or `.env` contents.
|
|
25
|
+
16. Smoke-test any new CLI command such as `coding-agent-skills route-trace`,
|
|
23
26
|
`coding-agent-skills env-audit`, `coding-agent-skills secret-audit`,
|
|
24
27
|
`coding-agent-skills api-contract-audit`, `coding-agent-skills migration-review`,
|
|
25
|
-
|
|
28
|
+
`coding-agent-skills github-handoff`, or `coding-agent-skills deployment-preflight`
|
|
26
29
|
against synthetic fixtures only unless a real project read-only smoke is explicitly
|
|
27
30
|
approved.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
17. Review changelog, ledger, run evidence, and versioning impact.
|
|
32
|
+
18. Commit with approved identity.
|
|
33
|
+
19. Push `main` using credential-free remotes.
|
|
34
|
+
20. Confirm a clean synchronized worktree.
|
|
35
|
+
21. Create and push the annotated version tag.
|
|
36
|
+
22. Publish with `npm publish --access public --registry=https://registry.npmjs.org/`.
|
|
37
|
+
23. Install the published package into a temporary prefix and smoke-test the installed CLI.
|
|
38
|
+
24. Create the GitHub Release for the pushed tag.
|
|
36
39
|
|
|
37
40
|
Deployments, migrations, runtime mutation, platform actions, and target-project builds or
|
|
38
41
|
tests remain outside this release process unless separately approved.
|