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.
Files changed (48) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +31 -1
  3. package/ROADMAP.md +7 -2
  4. package/bin/coding-agent-skills +340 -2
  5. package/docs/adapters/README.md +21 -0
  6. package/docs/adapters/project-installation.md +14 -0
  7. package/docs/adapters/real-project-adoption.md +2 -2
  8. package/docs/architecture/README.md +3 -2
  9. package/docs/release/README.md +13 -10
  10. package/docs/release/npm-package.md +27 -2
  11. package/docs/safety/README.md +6 -1
  12. package/docs/testing/README.md +16 -0
  13. package/docs/usage/README.md +59 -5
  14. package/examples/command-policies/deployment-preflight.json +70 -0
  15. package/examples/evidence-packs/deployment-preflight.json +60 -0
  16. package/examples/manifests/deployment-preflight.json +14 -0
  17. package/examples/workflows/deployment-preflight.md +8 -0
  18. package/package.json +2 -1
  19. package/runs/skill-runs.md +36 -0
  20. package/schemas/project-adapter-installation.schema.json +2 -0
  21. package/schemas/project-adapter.schema.json +2 -0
  22. package/scripts/lib/deployment-preflight.mjs +655 -0
  23. package/scripts/lib/pack-rules.mjs +11 -2
  24. package/scripts/render-deployment-preflight.mjs +9 -0
  25. package/scripts/test-pack.mjs +151 -1
  26. package/scripts/validate-pack.mjs +5 -2
  27. package/skills/deployment-preflight/SKILL.md +89 -0
  28. package/skills/deployment-preflight/adapter-interface.md +17 -0
  29. package/skills/deployment-preflight/agents/openai.yaml +3 -0
  30. package/skills/deployment-preflight/checklist.md +7 -0
  31. package/skills/deployment-preflight/evidence-template.md +19 -0
  32. package/skills/deployment-preflight/examples.md +11 -0
  33. package/skills/deployment-preflight/failure-modes.md +11 -0
  34. package/tests/fixtures/deployment-preflight/adapter-project/.coding-agent/adapters/deployment-preflight-fixture/adapter.json +56 -0
  35. package/tests/fixtures/deployment-preflight/adapter-project/.coding-agent/skills.json +23 -0
  36. package/tests/fixtures/deployment-preflight/adapter-project/README.md +3 -0
  37. package/tests/fixtures/deployment-preflight/adapter-project/deploy/netlify.toml +3 -0
  38. package/tests/fixtures/deployment-preflight/adapter-project/ignored/render.yaml +3 -0
  39. package/tests/fixtures/deployment-preflight/adapter-project/package.json +5 -0
  40. package/tests/fixtures/deployment-preflight/static-project/Dockerfile +2 -0
  41. package/tests/fixtures/deployment-preflight/static-project/README.md +3 -0
  42. package/tests/fixtures/deployment-preflight/static-project/docs/deployment.md +4 -0
  43. package/tests/fixtures/deployment-preflight/static-project/package.json +6 -0
  44. package/tests/fixtures/deployment-preflight/static-project/src/index.js +1 -0
  45. package/tests/fixtures/deployment-preflight/static-project/wrangler.toml +3 -0
  46. package/tests/fixtures/triggers/cases.json +13 -1
  47. package/tests/trigger/README.md +2 -0
  48. 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 eleven approved shared skills. Builder-mode approval is
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 | Builder-mode approved; next in wave |
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 |
@@ -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
- const [commandName, ...args] = process.argv.slice(2);
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
  }
@@ -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`, `runtime-truth`, or
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. Deployment
30
- preflight, provider operations, and additional project adapters remain separate future
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.
@@ -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 any new CLI command such as `coding-agent-skills route-trace`,
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
- or `coding-agent-skills github-handoff`
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
- 16. Review changelog, ledger, run evidence, and versioning impact.
29
- 17. Commit with approved identity.
30
- 18. Push `main` using credential-free remotes.
31
- 19. Confirm a clean synchronized worktree.
32
- 20. Create and push the annotated version tag.
33
- 21. Publish with `npm publish --access public --registry=https://registry.npmjs.org/`.
34
- 22. Install the published package into a temporary prefix and smoke-test the installed CLI.
35
- 23. Create the GitHub Release for the pushed tag.
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.