@agent-surface/cli 0.20.1 → 0.21.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/README.md +1 -0
- package/dist/bin.js +28 -11
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-KMAH2WU5.js → chunk-SBN4KLS2.js} +153 -27
- package/dist/chunk-SBN4KLS2.js.map +1 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +1 -1
- package/dist/ink-7PDZ7AIC.js +169 -0
- package/dist/ink-7PDZ7AIC.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-KMAH2WU5.js.map +0 -1
- package/dist/ink-4CUU77KD.js +0 -146
- package/dist/ink-4CUU77KD.js.map +0 -1
package/README.md
CHANGED
package/dist/bin.js
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
} from "./chunk-XCQACLOT.js";
|
|
8
8
|
import {
|
|
9
9
|
diffContracts,
|
|
10
|
-
renderReport
|
|
11
|
-
|
|
10
|
+
renderReport,
|
|
11
|
+
supportsColor
|
|
12
|
+
} from "./chunk-SBN4KLS2.js";
|
|
12
13
|
|
|
13
14
|
// src/bin.ts
|
|
14
15
|
import { realpathSync } from "fs";
|
|
@@ -71,13 +72,16 @@ function shouldFail(policy, changes) {
|
|
|
71
72
|
}
|
|
72
73
|
async function present(report, options) {
|
|
73
74
|
const interactive = options.format === "human" && !options.plain && process.stdout.isTTY === true && !process.env["CI"] && !process.env["NO_COLOR"];
|
|
74
|
-
const
|
|
75
|
+
const verbosity = options.verbosity ?? (options.detail ? "detail" : "normal");
|
|
76
|
+
const render = { root: options.root, verbosity };
|
|
75
77
|
if (interactive) {
|
|
76
|
-
const { renderInk } = await import("./ink-
|
|
78
|
+
const { renderInk } = await import("./ink-7PDZ7AIC.js");
|
|
77
79
|
await renderInk(report, render);
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
|
-
process.stdout.write(
|
|
82
|
+
process.stdout.write(
|
|
83
|
+
renderReport(report, options.format, { ...render, color: supportsColor(process.stdout) })
|
|
84
|
+
);
|
|
81
85
|
}
|
|
82
86
|
async function runInspect(options) {
|
|
83
87
|
const manifest = await compile(options);
|
|
@@ -133,6 +137,9 @@ async function runCheck(options) {
|
|
|
133
137
|
...pr ? { pullRequest: pr } : {}
|
|
134
138
|
};
|
|
135
139
|
await present(report, options);
|
|
140
|
+
if (failed && !integrityCurrent && options.format === "human") {
|
|
141
|
+
process.stderr.write("\nUpdate the snapshot in this change: agent-surface snapshot\n");
|
|
142
|
+
}
|
|
136
143
|
return failed ? 1 : 0;
|
|
137
144
|
}
|
|
138
145
|
|
|
@@ -156,15 +163,18 @@ Contract
|
|
|
156
163
|
--policy <mode> all | widening | narrowing | neutral | none (default: all)
|
|
157
164
|
|
|
158
165
|
Output
|
|
159
|
-
--
|
|
160
|
-
|
|
166
|
+
--verbosity <level> min | normal | detail (default: normal)
|
|
167
|
+
min: headline and counts only
|
|
168
|
+
detail: descriptions, provenance, grouped inventory
|
|
169
|
+
--detail alias for --verbosity detail
|
|
170
|
+
--format <format> human | json | md | github (default: human)
|
|
161
171
|
--json alias for --format json
|
|
162
172
|
--plain plain text instead of the drawn terminal view
|
|
163
173
|
-h, --help
|
|
164
174
|
-v, --version
|
|
165
175
|
|
|
166
176
|
Examples
|
|
167
|
-
agent-surface inspect --detail
|
|
177
|
+
agent-surface inspect --verbosity detail
|
|
168
178
|
agent-surface check --base origin/main --format github
|
|
169
179
|
|
|
170
180
|
Exit: 0 clean/viewed, 1 deterministic drift/policy finding, 2 completeness failure.
|
|
@@ -172,6 +182,7 @@ Exit: 0 clean/viewed, 1 deterministic drift/policy finding, 2 completeness failu
|
|
|
172
182
|
var COMMANDS = /* @__PURE__ */ new Set(["inspect", "snapshot", "check"]);
|
|
173
183
|
var FORMATS = /* @__PURE__ */ new Set(["human", "json", "github", "markdown"]);
|
|
174
184
|
var POLICIES = /* @__PURE__ */ new Set(["all", "widening", "narrowing", "neutral", "none"]);
|
|
185
|
+
var VERBOSITIES = /* @__PURE__ */ new Set(["min", "normal", "detail"]);
|
|
175
186
|
function write(text, error = false) {
|
|
176
187
|
(error ? process.stderr : process.stdout).write(text.endsWith("\n") ? text : `${text}
|
|
177
188
|
`);
|
|
@@ -197,6 +208,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
197
208
|
format: { type: "string", default: "human" },
|
|
198
209
|
json: { type: "boolean", default: false },
|
|
199
210
|
plain: { type: "boolean", default: false },
|
|
211
|
+
verbosity: { type: "string", default: "normal" },
|
|
200
212
|
detail: { type: "boolean", default: false },
|
|
201
213
|
help: { type: "boolean", short: "h", default: false },
|
|
202
214
|
version: { type: "boolean", short: "v", default: false }
|
|
@@ -222,9 +234,14 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
222
234
|
write(USAGE, true);
|
|
223
235
|
return 2;
|
|
224
236
|
}
|
|
225
|
-
const format = values.json ? "json" : values.format;
|
|
237
|
+
const format = values.json ? "json" : values.format === "md" ? "markdown" : values.format;
|
|
226
238
|
if (!FORMATS.has(format)) {
|
|
227
|
-
write(`--format must be human, json,
|
|
239
|
+
write(`--format must be human, json, md, markdown, or github`, true);
|
|
240
|
+
return 2;
|
|
241
|
+
}
|
|
242
|
+
const verbosity = values.detail ? "detail" : values.verbosity;
|
|
243
|
+
if (!VERBOSITIES.has(verbosity)) {
|
|
244
|
+
write(`--verbosity must be min, normal, or detail`, true);
|
|
228
245
|
return 2;
|
|
229
246
|
}
|
|
230
247
|
if (!POLICIES.has(values.policy)) {
|
|
@@ -252,7 +269,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
252
269
|
policy: values.policy,
|
|
253
270
|
...allow.length > 0 ? { externalContracts: { allow } } : {},
|
|
254
271
|
...values.plain ? { plain: true } : {},
|
|
255
|
-
|
|
272
|
+
verbosity
|
|
256
273
|
};
|
|
257
274
|
try {
|
|
258
275
|
if (command === "inspect") return await runInspect(options);
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bin.ts","../src/commands.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { parseArgs } from \"node:util\";\nimport { runCheck, runInspect, runSnapshot, type CommandOptions } from \"./commands.js\";\nimport type { OutputFormat } from \"./report.js\";\n\nconst USAGE = `agent-surface — compiled production capability contract\n\nUsage\n agent-surface inspect [options] view the contract and any drift\n agent-surface snapshot [options] write the committed contract\n agent-surface check [options] fail on drift, for CI\n\nCompilation\n --root <path> application root (default: cwd)\n --config <path> Vite config, relative to root\n --target <name> production build target; repeatable\n --allow <pkg>=<d> approve a dependency to contribute capabilities; repeatable\n\nContract\n --snapshot <path> committed contract (default: .agent-surface/contract.json)\n --base <git-ref> render committed PR drift against Git base\n --policy <mode> all | widening | narrowing | neutral | none (default: all)\n\nOutput\n --detail add descriptions, confirmation, policies, and tags\n --format <format> human | json | github | markdown (default: human)\n --json alias for --format json\n --plain plain text instead of the drawn terminal view\n -h, --help\n -v, --version\n\nExamples\n agent-surface inspect --detail\n agent-surface check --base origin/main --format github\n\nExit: 0 clean/viewed, 1 deterministic drift/policy finding, 2 completeness failure.\n`;\n\nconst COMMANDS = new Set([\"inspect\", \"snapshot\", \"check\"]);\nconst FORMATS = new Set<OutputFormat>([\"human\", \"json\", \"github\", \"markdown\"]);\nconst POLICIES = new Set([\"all\", \"widening\", \"narrowing\", \"neutral\", \"none\"]);\n\nfunction write(text: string, error = false): void {\n (error ? process.stderr : process.stdout).write(text.endsWith(\"\\n\") ? text : `${text}\\n`);\n}\n\n/**\n * `pnpm run <script> -- --plain` forwards the separator itself, and `parseArgs`\n * turns everything after it into positionals — so the flag arrived as a second\n * command and the run failed as `invalid command inspect`. This CLI takes no\n * literal operands, so the first separator is dropped and the pass-through\n * idiom every package manager documents works.\n */\nfunction stripSeparator(argv: string[]): string[] {\n const index = argv.indexOf(\"--\");\n return index === -1 ? argv : [...argv.slice(0, index), ...argv.slice(index + 1)];\n}\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<number> {\n let parsed;\n try {\n parsed = parseArgs({\n args: stripSeparator(argv),\n allowPositionals: true,\n options: {\n root: { type: \"string\", default: process.cwd() },\n config: { type: \"string\" },\n snapshot: { type: \"string\" },\n target: { type: \"string\", multiple: true },\n base: { type: \"string\" },\n allow: { type: \"string\", multiple: true },\n policy: { type: \"string\", default: \"all\" },\n format: { type: \"string\", default: \"human\" },\n json: { type: \"boolean\", default: false },\n plain: { type: \"boolean\", default: false },\n detail: { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n version: { type: \"boolean\", short: \"v\", default: false },\n },\n });\n } catch (error) {\n write(error instanceof Error ? error.message : String(error), true);\n write(USAGE, true);\n return 2;\n }\n const { values, positionals } = parsed;\n if (values.help) {\n write(USAGE);\n return 0;\n }\n if (values.version) {\n write(await readVersion());\n return 0;\n }\n const [command, ...extra] = positionals;\n if (!command || !COMMANDS.has(command) || extra.length > 0) {\n write(command === \"init\" ? \"init removed: configure the Vite compiler plugin\" : `invalid command ${command ?? \"\"}`, true);\n write(USAGE, true);\n return 2;\n }\n const format = (values.json ? \"json\" : values.format) as OutputFormat;\n if (!FORMATS.has(format)) {\n write(`--format must be human, json, github, or markdown`, true);\n return 2;\n }\n if (!POLICIES.has(values.policy)) {\n write(`--policy must be all, widening, narrowing, neutral, or none`, true);\n return 2;\n }\n const allow = [];\n for (const entry of values.allow ?? []) {\n const separator = entry.lastIndexOf(\"=\");\n const name = separator === -1 ? \"\" : entry.slice(0, separator);\n const digest = separator === -1 ? \"\" : entry.slice(separator + 1);\n if (!name || !/^[0-9a-f]{64}$/.test(digest)) {\n write(`--allow must be <package>=<sha256>, got \"${entry}\"`, true);\n return 2;\n }\n allow.push({ package: name, digest });\n }\n const options: CommandOptions = {\n root: values.root,\n ...(values.config ? { configFile: values.config } : {}),\n ...(values.snapshot ? { snapshot: values.snapshot } : {}),\n targets: values.target ?? [],\n ...(values.base ? { base: values.base } : {}),\n format,\n policy: values.policy as CommandOptions[\"policy\"],\n ...(allow.length > 0 ? { externalContracts: { allow } } : {}),\n ...(values.plain ? { plain: true } : {}),\n ...(values.detail ? { detail: true } : {}),\n };\n try {\n if (command === \"inspect\") return await runInspect(options);\n if (command === \"snapshot\") return await runSnapshot(options);\n return await runCheck(options);\n } catch (error) {\n write(error instanceof Error ? error.message : String(error), true);\n if (error instanceof Error && error.stack && process.env[\"AGENT_SURFACE_DEBUG\"]) {\n write(error.stack, true);\n }\n return 2;\n }\n}\n\nasync function readVersion(): Promise<string> {\n const { readFileSync } = await import(\"node:fs\");\n const path = fileURLToPath(new URL(\"../package.json\", import.meta.url));\n return (JSON.parse(readFileSync(path, \"utf8\")) as { version: string }).version;\n}\n\nfunction invokedAsBinary(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n return fileURLToPath(import.meta.url) === realpathSync(entry);\n } catch {\n return false;\n }\n}\n\nif (invokedAsBinary()) {\n void main().then((code) => {\n process.exitCode = code;\n });\n}\n","import { resolve } from \"node:path\";\nimport type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\nimport {\n compileCapabilityContract,\n computeManifestHash,\n type ExternalContractPolicy,\n} from \"@agent-surface/compiler\";\nimport { diffContracts, type ChangeClassification } from \"./diff.js\";\nimport { DEFAULT_SNAPSHOT, readBaseManifest, readManifest, writeManifest } from \"./files.js\";\nimport type { ContractReport, OutputFormat, RenderOptions } from \"./report.js\";\nimport { renderReport } from \"./report.js\";\n\nexport interface CommandOptions {\n root: string;\n configFile?: string;\n snapshot?: string;\n targets: string[];\n base?: string;\n format: OutputFormat;\n policy: \"all\" | ChangeClassification | \"none\";\n /** Dependencies approved to contribute, as `--allow <package>=<sha256>`. */\n externalContracts?: ExternalContractPolicy;\n plain?: boolean;\n detail?: boolean;\n}\n\nfunction mergeManifests(manifests: CapabilityContractManifest[]): CapabilityContractManifest {\n const entries = new Map<string, CapabilityContractEntry>();\n for (const manifest of manifests) {\n for (const entry of manifest.capabilities) {\n const key = `${entry.declarationId}\\0${entry.capabilityId}`;\n const existing = entries.get(key);\n if (!existing) entries.set(key, { ...entry, targets: [...entry.targets] });\n else {\n if (existing.contractHash !== entry.contractHash) {\n throw new Error(`contract ${entry.declarationId} / ${entry.capabilityId} differs across targets`);\n }\n existing.targets = [...new Set([...existing.targets, ...entry.targets])].sort();\n }\n }\n }\n const payload = {\n formatVersion: 5 as const,\n compilerVersion: manifests[0]?.compilerVersion ?? \"unknown\",\n targets: [...new Set(manifests.flatMap((manifest) => manifest.targets))].sort(),\n capabilities: [...entries.values()].sort((a, b) =>\n `${a.declarationId}\\0${a.capabilityId}`.localeCompare(`${b.declarationId}\\0${b.capabilityId}`),\n ),\n // One attribution per package: the same dependency contributes identically\n // to every target, and a divergence would already have failed the compile.\n externalContracts: manifests\n .flatMap((manifest) => manifest.externalContracts)\n .filter((entry, index, all) => all.findIndex((candidate) => candidate.package === entry.package) === index)\n .sort((a, b) => a.package.localeCompare(b.package)),\n completeness: { status: \"proven\" as const },\n };\n return { ...payload, hash: computeManifestHash(payload) };\n}\n\nasync function compile(options: CommandOptions): Promise<CapabilityContractManifest> {\n const targets = options.targets.length > 0 ? options.targets : [\"web-production\"];\n const manifests = await Promise.all(\n targets.map((target) =>\n compileCapabilityContract({\n root: options.root,\n ...(options.configFile ? { configFile: options.configFile } : {}),\n ...(options.externalContracts ? { externalContracts: options.externalContracts } : {}),\n target,\n }),\n ),\n );\n return mergeManifests(manifests);\n}\n\nfunction shouldFail(\n policy: CommandOptions[\"policy\"],\n changes: ReturnType<typeof diffContracts>,\n): boolean {\n if (policy === \"none\") return false;\n if (policy === \"all\") return changes.length > 0;\n return changes.some((change) => change.classification === policy);\n}\n\nasync function present(report: ContractReport, options: CommandOptions): Promise<void> {\n const interactive =\n options.format === \"human\" &&\n !options.plain &&\n process.stdout.isTTY === true &&\n !process.env[\"CI\"] &&\n !process.env[\"NO_COLOR\"];\n const render: RenderOptions = { root: options.root, ...(options.detail ? { detail: true } : {}) };\n if (interactive) {\n const { renderInk } = await import(\"./ink.js\");\n await renderInk(report, render);\n return;\n }\n process.stdout.write(renderReport(report, options.format, render));\n}\n\nexport async function runInspect(options: CommandOptions): Promise<number> {\n const manifest = await compile(options);\n const snapshotPath = resolve(options.root, options.snapshot ?? DEFAULT_SNAPSHOT);\n const snapshot = readManifest(snapshotPath);\n const integrityChanges = diffContracts(snapshot, manifest);\n const report: ContractReport = {\n command: \"inspect\",\n status: \"view\",\n manifest,\n snapshotPath,\n integrity: {\n status: !snapshot ? \"missing\" : snapshot.hash === manifest.hash ? \"current\" : \"stale\",\n changes: integrityChanges,\n },\n ...(options.base\n ? {\n pullRequest: {\n base: options.base,\n changes: diffContracts(readBaseManifest(options.base, snapshotPath, options.root), manifest),\n },\n }\n : {}),\n };\n await present(report, options);\n return 0;\n}\n\nexport async function runSnapshot(options: CommandOptions): Promise<number> {\n const manifest = await compile(options);\n const snapshotPath = resolve(options.root, options.snapshot ?? DEFAULT_SNAPSHOT);\n writeManifest(snapshotPath, manifest);\n await present({ command: \"snapshot\", status: \"written\", manifest, snapshotPath }, options);\n return 0;\n}\n\nexport async function runCheck(options: CommandOptions): Promise<number> {\n const manifest = await compile(options);\n const snapshotPath = resolve(options.root, options.snapshot ?? DEFAULT_SNAPSHOT);\n const snapshot = readManifest(snapshotPath);\n const integrityChanges = diffContracts(snapshot, manifest);\n const integrityCurrent = snapshot?.hash === manifest.hash;\n const pr = options.base\n ? {\n base: options.base,\n changes: diffContracts(readBaseManifest(options.base, snapshotPath, options.root), snapshot ?? manifest),\n }\n : undefined;\n const failed = !integrityCurrent || (pr ? shouldFail(options.policy, pr.changes) : false);\n const report: ContractReport = {\n command: \"check\",\n status: failed ? \"fail\" : \"pass\",\n manifest,\n snapshotPath,\n integrity: {\n status: !snapshot ? \"missing\" : integrityCurrent ? \"current\" : \"stale\",\n changes: integrityChanges,\n },\n ...(pr ? { pullRequest: pr } : {}),\n };\n await present(report, options);\n return failed ? 1 : 0;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/bin.ts","../src/commands.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { parseArgs } from \"node:util\";\nimport { runCheck, runInspect, runSnapshot, type CommandOptions } from \"./commands.js\";\nimport type { OutputFormat, Verbosity } from \"./report.js\";\n\nconst USAGE = `agent-surface — compiled production capability contract\n\nUsage\n agent-surface inspect [options] view the contract and any drift\n agent-surface snapshot [options] write the committed contract\n agent-surface check [options] fail on drift, for CI\n\nCompilation\n --root <path> application root (default: cwd)\n --config <path> Vite config, relative to root\n --target <name> production build target; repeatable\n --allow <pkg>=<d> approve a dependency to contribute capabilities; repeatable\n\nContract\n --snapshot <path> committed contract (default: .agent-surface/contract.json)\n --base <git-ref> render committed PR drift against Git base\n --policy <mode> all | widening | narrowing | neutral | none (default: all)\n\nOutput\n --verbosity <level> min | normal | detail (default: normal)\n min: headline and counts only\n detail: descriptions, provenance, grouped inventory\n --detail alias for --verbosity detail\n --format <format> human | json | md | github (default: human)\n --json alias for --format json\n --plain plain text instead of the drawn terminal view\n -h, --help\n -v, --version\n\nExamples\n agent-surface inspect --verbosity detail\n agent-surface check --base origin/main --format github\n\nExit: 0 clean/viewed, 1 deterministic drift/policy finding, 2 completeness failure.\n`;\n\nconst COMMANDS = new Set([\"inspect\", \"snapshot\", \"check\"]);\nconst FORMATS = new Set<OutputFormat>([\"human\", \"json\", \"github\", \"markdown\"]);\nconst POLICIES = new Set([\"all\", \"widening\", \"narrowing\", \"neutral\", \"none\"]);\nconst VERBOSITIES = new Set<Verbosity>([\"min\", \"normal\", \"detail\"]);\n\nfunction write(text: string, error = false): void {\n (error ? process.stderr : process.stdout).write(text.endsWith(\"\\n\") ? text : `${text}\\n`);\n}\n\n/**\n * `pnpm run <script> -- --plain` forwards the separator itself, and `parseArgs`\n * turns everything after it into positionals — so the flag arrived as a second\n * command and the run failed as `invalid command inspect`. This CLI takes no\n * literal operands, so the first separator is dropped and the pass-through\n * idiom every package manager documents works.\n */\nfunction stripSeparator(argv: string[]): string[] {\n const index = argv.indexOf(\"--\");\n return index === -1 ? argv : [...argv.slice(0, index), ...argv.slice(index + 1)];\n}\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<number> {\n let parsed;\n try {\n parsed = parseArgs({\n args: stripSeparator(argv),\n allowPositionals: true,\n options: {\n root: { type: \"string\", default: process.cwd() },\n config: { type: \"string\" },\n snapshot: { type: \"string\" },\n target: { type: \"string\", multiple: true },\n base: { type: \"string\" },\n allow: { type: \"string\", multiple: true },\n policy: { type: \"string\", default: \"all\" },\n format: { type: \"string\", default: \"human\" },\n json: { type: \"boolean\", default: false },\n plain: { type: \"boolean\", default: false },\n verbosity: { type: \"string\", default: \"normal\" },\n detail: { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n version: { type: \"boolean\", short: \"v\", default: false },\n },\n });\n } catch (error) {\n write(error instanceof Error ? error.message : String(error), true);\n write(USAGE, true);\n return 2;\n }\n const { values, positionals } = parsed;\n if (values.help) {\n write(USAGE);\n return 0;\n }\n if (values.version) {\n write(await readVersion());\n return 0;\n }\n const [command, ...extra] = positionals;\n if (!command || !COMMANDS.has(command) || extra.length > 0) {\n write(command === \"init\" ? \"init removed: configure the Vite compiler plugin\" : `invalid command ${command ?? \"\"}`, true);\n write(USAGE, true);\n return 2;\n }\n // `md` is what the sibling orpc-agent CLI calls it; both spellings work here.\n const format = (values.json ? \"json\" : values.format === \"md\" ? \"markdown\" : values.format) as OutputFormat;\n if (!FORMATS.has(format)) {\n write(`--format must be human, json, md, markdown, or github`, true);\n return 2;\n }\n const verbosity = (values.detail ? \"detail\" : values.verbosity) as Verbosity;\n if (!VERBOSITIES.has(verbosity)) {\n write(`--verbosity must be min, normal, or detail`, true);\n return 2;\n }\n if (!POLICIES.has(values.policy)) {\n write(`--policy must be all, widening, narrowing, neutral, or none`, true);\n return 2;\n }\n const allow = [];\n for (const entry of values.allow ?? []) {\n const separator = entry.lastIndexOf(\"=\");\n const name = separator === -1 ? \"\" : entry.slice(0, separator);\n const digest = separator === -1 ? \"\" : entry.slice(separator + 1);\n if (!name || !/^[0-9a-f]{64}$/.test(digest)) {\n write(`--allow must be <package>=<sha256>, got \"${entry}\"`, true);\n return 2;\n }\n allow.push({ package: name, digest });\n }\n const options: CommandOptions = {\n root: values.root,\n ...(values.config ? { configFile: values.config } : {}),\n ...(values.snapshot ? { snapshot: values.snapshot } : {}),\n targets: values.target ?? [],\n ...(values.base ? { base: values.base } : {}),\n format,\n policy: values.policy as CommandOptions[\"policy\"],\n ...(allow.length > 0 ? { externalContracts: { allow } } : {}),\n ...(values.plain ? { plain: true } : {}),\n verbosity,\n };\n try {\n if (command === \"inspect\") return await runInspect(options);\n if (command === \"snapshot\") return await runSnapshot(options);\n return await runCheck(options);\n } catch (error) {\n write(error instanceof Error ? error.message : String(error), true);\n if (error instanceof Error && error.stack && process.env[\"AGENT_SURFACE_DEBUG\"]) {\n write(error.stack, true);\n }\n return 2;\n }\n}\n\nasync function readVersion(): Promise<string> {\n const { readFileSync } = await import(\"node:fs\");\n const path = fileURLToPath(new URL(\"../package.json\", import.meta.url));\n return (JSON.parse(readFileSync(path, \"utf8\")) as { version: string }).version;\n}\n\nfunction invokedAsBinary(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n return fileURLToPath(import.meta.url) === realpathSync(entry);\n } catch {\n return false;\n }\n}\n\nif (invokedAsBinary()) {\n void main().then((code) => {\n process.exitCode = code;\n });\n}\n","import { resolve } from \"node:path\";\nimport type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\nimport {\n compileCapabilityContract,\n computeManifestHash,\n type ExternalContractPolicy,\n} from \"@agent-surface/compiler\";\nimport { diffContracts, type ChangeClassification } from \"./diff.js\";\nimport { DEFAULT_SNAPSHOT, readBaseManifest, readManifest, writeManifest } from \"./files.js\";\nimport type { ContractReport, OutputFormat, RenderOptions, Verbosity } from \"./report.js\";\nimport { renderReport, supportsColor } from \"./report.js\";\n\nexport interface CommandOptions {\n root: string;\n configFile?: string;\n snapshot?: string;\n targets: string[];\n base?: string;\n format: OutputFormat;\n policy: \"all\" | ChangeClassification | \"none\";\n /** Dependencies approved to contribute, as `--allow <package>=<sha256>`. */\n externalContracts?: ExternalContractPolicy;\n plain?: boolean;\n /** Deprecated alias for `verbosity: \"detail\"`. */\n detail?: boolean;\n verbosity?: Verbosity;\n}\n\nfunction mergeManifests(manifests: CapabilityContractManifest[]): CapabilityContractManifest {\n const entries = new Map<string, CapabilityContractEntry>();\n for (const manifest of manifests) {\n for (const entry of manifest.capabilities) {\n const key = `${entry.declarationId}\\0${entry.capabilityId}`;\n const existing = entries.get(key);\n if (!existing) entries.set(key, { ...entry, targets: [...entry.targets] });\n else {\n if (existing.contractHash !== entry.contractHash) {\n throw new Error(`contract ${entry.declarationId} / ${entry.capabilityId} differs across targets`);\n }\n existing.targets = [...new Set([...existing.targets, ...entry.targets])].sort();\n }\n }\n }\n const payload = {\n formatVersion: 5 as const,\n compilerVersion: manifests[0]?.compilerVersion ?? \"unknown\",\n targets: [...new Set(manifests.flatMap((manifest) => manifest.targets))].sort(),\n capabilities: [...entries.values()].sort((a, b) =>\n `${a.declarationId}\\0${a.capabilityId}`.localeCompare(`${b.declarationId}\\0${b.capabilityId}`),\n ),\n // One attribution per package: the same dependency contributes identically\n // to every target, and a divergence would already have failed the compile.\n externalContracts: manifests\n .flatMap((manifest) => manifest.externalContracts)\n .filter((entry, index, all) => all.findIndex((candidate) => candidate.package === entry.package) === index)\n .sort((a, b) => a.package.localeCompare(b.package)),\n completeness: { status: \"proven\" as const },\n };\n return { ...payload, hash: computeManifestHash(payload) };\n}\n\nasync function compile(options: CommandOptions): Promise<CapabilityContractManifest> {\n const targets = options.targets.length > 0 ? options.targets : [\"web-production\"];\n const manifests = await Promise.all(\n targets.map((target) =>\n compileCapabilityContract({\n root: options.root,\n ...(options.configFile ? { configFile: options.configFile } : {}),\n ...(options.externalContracts ? { externalContracts: options.externalContracts } : {}),\n target,\n }),\n ),\n );\n return mergeManifests(manifests);\n}\n\nfunction shouldFail(\n policy: CommandOptions[\"policy\"],\n changes: ReturnType<typeof diffContracts>,\n): boolean {\n if (policy === \"none\") return false;\n if (policy === \"all\") return changes.length > 0;\n return changes.some((change) => change.classification === policy);\n}\n\nasync function present(report: ContractReport, options: CommandOptions): Promise<void> {\n const interactive =\n options.format === \"human\" &&\n !options.plain &&\n process.stdout.isTTY === true &&\n !process.env[\"CI\"] &&\n !process.env[\"NO_COLOR\"];\n const verbosity = options.verbosity ?? (options.detail ? \"detail\" : \"normal\");\n const render: RenderOptions = { root: options.root, verbosity };\n if (interactive) {\n const { renderInk } = await import(\"./ink.js\");\n await renderInk(report, render);\n return;\n }\n // `--plain` at a terminal still paints; a pipe, CI, or NO_COLOR never does.\n process.stdout.write(\n renderReport(report, options.format, { ...render, color: supportsColor(process.stdout) }),\n );\n}\n\nexport async function runInspect(options: CommandOptions): Promise<number> {\n const manifest = await compile(options);\n const snapshotPath = resolve(options.root, options.snapshot ?? DEFAULT_SNAPSHOT);\n const snapshot = readManifest(snapshotPath);\n const integrityChanges = diffContracts(snapshot, manifest);\n const report: ContractReport = {\n command: \"inspect\",\n status: \"view\",\n manifest,\n snapshotPath,\n integrity: {\n status: !snapshot ? \"missing\" : snapshot.hash === manifest.hash ? \"current\" : \"stale\",\n changes: integrityChanges,\n },\n ...(options.base\n ? {\n pullRequest: {\n base: options.base,\n changes: diffContracts(readBaseManifest(options.base, snapshotPath, options.root), manifest),\n },\n }\n : {}),\n };\n await present(report, options);\n return 0;\n}\n\nexport async function runSnapshot(options: CommandOptions): Promise<number> {\n const manifest = await compile(options);\n const snapshotPath = resolve(options.root, options.snapshot ?? DEFAULT_SNAPSHOT);\n writeManifest(snapshotPath, manifest);\n await present({ command: \"snapshot\", status: \"written\", manifest, snapshotPath }, options);\n return 0;\n}\n\nexport async function runCheck(options: CommandOptions): Promise<number> {\n const manifest = await compile(options);\n const snapshotPath = resolve(options.root, options.snapshot ?? DEFAULT_SNAPSHOT);\n const snapshot = readManifest(snapshotPath);\n const integrityChanges = diffContracts(snapshot, manifest);\n const integrityCurrent = snapshot?.hash === manifest.hash;\n const pr = options.base\n ? {\n base: options.base,\n changes: diffContracts(readBaseManifest(options.base, snapshotPath, options.root), snapshot ?? manifest),\n }\n : undefined;\n const failed = !integrityCurrent || (pr ? shouldFail(options.policy, pr.changes) : false);\n const report: ContractReport = {\n command: \"check\",\n status: failed ? \"fail\" : \"pass\",\n manifest,\n snapshotPath,\n integrity: {\n status: !snapshot ? \"missing\" : integrityCurrent ? \"current\" : \"stale\",\n changes: integrityChanges,\n },\n ...(pr ? { pullRequest: pr } : {}),\n };\n await present(report, options);\n // stderr, like the report hint in orpc-agent: it survives a piped report.\n if (failed && !integrityCurrent && options.format === \"human\") {\n process.stderr.write(\"\\nUpdate the snapshot in this change: agent-surface snapshot\\n\");\n }\n return failed ? 1 : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;AACA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;;;ACH1B,SAAS,eAAe;AAExB;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAsBP,SAAS,eAAe,WAAqE;AAC3F,QAAM,UAAU,oBAAI,IAAqC;AACzD,aAAW,YAAY,WAAW;AAChC,eAAW,SAAS,SAAS,cAAc;AACzC,YAAM,MAAM,GAAG,MAAM,aAAa,KAAK,MAAM,YAAY;AACzD,YAAM,WAAW,QAAQ,IAAI,GAAG;AAChC,UAAI,CAAC,SAAU,SAAQ,IAAI,KAAK,EAAE,GAAG,OAAO,SAAS,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;AAAA,WACpE;AACH,YAAI,SAAS,iBAAiB,MAAM,cAAc;AAChD,gBAAM,IAAI,MAAM,YAAY,MAAM,aAAa,MAAM,MAAM,YAAY,yBAAyB;AAAA,QAClG;AACA,iBAAS,UAAU,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,SAAS,SAAS,GAAG,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AACA,QAAM,UAAU;AAAA,IACd,eAAe;AAAA,IACf,iBAAiB,UAAU,CAAC,GAAG,mBAAmB;AAAA,IAClD,SAAS,CAAC,GAAG,IAAI,IAAI,UAAU,QAAQ,CAAC,aAAa,SAAS,OAAO,CAAC,CAAC,EAAE,KAAK;AAAA,IAC9E,cAAc,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE;AAAA,MAAK,CAAC,GAAG,MAC3C,GAAG,EAAE,aAAa,KAAK,EAAE,YAAY,GAAG,cAAc,GAAG,EAAE,aAAa,KAAK,EAAE,YAAY,EAAE;AAAA,IAC/F;AAAA;AAAA;AAAA,IAGA,mBAAmB,UAChB,QAAQ,CAAC,aAAa,SAAS,iBAAiB,EAChD,OAAO,CAAC,OAAO,OAAO,QAAQ,IAAI,UAAU,CAAC,cAAc,UAAU,YAAY,MAAM,OAAO,MAAM,KAAK,EACzG,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAC;AAAA,IACpD,cAAc,EAAE,QAAQ,SAAkB;AAAA,EAC5C;AACA,SAAO,EAAE,GAAG,SAAS,MAAM,oBAAoB,OAAO,EAAE;AAC1D;AAEA,eAAe,QAAQ,SAA8D;AACnF,QAAM,UAAU,QAAQ,QAAQ,SAAS,IAAI,QAAQ,UAAU,CAAC,gBAAgB;AAChF,QAAM,YAAY,MAAM,QAAQ;AAAA,IAC9B,QAAQ;AAAA,MAAI,CAAC,WACX,0BAA0B;AAAA,QACxB,MAAM,QAAQ;AAAA,QACd,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,QAC/D,GAAI,QAAQ,oBAAoB,EAAE,mBAAmB,QAAQ,kBAAkB,IAAI,CAAC;AAAA,QACpF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,eAAe,SAAS;AACjC;AAEA,SAAS,WACP,QACA,SACS;AACT,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,MAAO,QAAO,QAAQ,SAAS;AAC9C,SAAO,QAAQ,KAAK,CAAC,WAAW,OAAO,mBAAmB,MAAM;AAClE;AAEA,eAAe,QAAQ,QAAwB,SAAwC;AACrF,QAAM,cACJ,QAAQ,WAAW,WACnB,CAAC,QAAQ,SACT,QAAQ,OAAO,UAAU,QACzB,CAAC,QAAQ,IAAI,IAAI,KACjB,CAAC,QAAQ,IAAI,UAAU;AACzB,QAAM,YAAY,QAAQ,cAAc,QAAQ,SAAS,WAAW;AACpE,QAAM,SAAwB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAC9D,MAAI,aAAa;AACf,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,mBAAU;AAC7C,UAAM,UAAU,QAAQ,MAAM;AAC9B;AAAA,EACF;AAEA,UAAQ,OAAO;AAAA,IACb,aAAa,QAAQ,QAAQ,QAAQ,EAAE,GAAG,QAAQ,OAAO,cAAc,QAAQ,MAAM,EAAE,CAAC;AAAA,EAC1F;AACF;AAEA,eAAsB,WAAW,SAA0C;AACzE,QAAM,WAAW,MAAM,QAAQ,OAAO;AACtC,QAAM,eAAe,QAAQ,QAAQ,MAAM,QAAQ,YAAY,gBAAgB;AAC/E,QAAM,WAAW,aAAa,YAAY;AAC1C,QAAM,mBAAmB,cAAc,UAAU,QAAQ;AACzD,QAAM,SAAyB;AAAA,IAC7B,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,WAAW;AAAA,MACT,QAAQ,CAAC,WAAW,YAAY,SAAS,SAAS,SAAS,OAAO,YAAY;AAAA,MAC9E,SAAS;AAAA,IACX;AAAA,IACA,GAAI,QAAQ,OACR;AAAA,MACE,aAAa;AAAA,QACX,MAAM,QAAQ;AAAA,QACd,SAAS,cAAc,iBAAiB,QAAQ,MAAM,cAAc,QAAQ,IAAI,GAAG,QAAQ;AAAA,MAC7F;AAAA,IACF,IACA,CAAC;AAAA,EACP;AACA,QAAM,QAAQ,QAAQ,OAAO;AAC7B,SAAO;AACT;AAEA,eAAsB,YAAY,SAA0C;AAC1E,QAAM,WAAW,MAAM,QAAQ,OAAO;AACtC,QAAM,eAAe,QAAQ,QAAQ,MAAM,QAAQ,YAAY,gBAAgB;AAC/E,gBAAc,cAAc,QAAQ;AACpC,QAAM,QAAQ,EAAE,SAAS,YAAY,QAAQ,WAAW,UAAU,aAAa,GAAG,OAAO;AACzF,SAAO;AACT;AAEA,eAAsB,SAAS,SAA0C;AACvE,QAAM,WAAW,MAAM,QAAQ,OAAO;AACtC,QAAM,eAAe,QAAQ,QAAQ,MAAM,QAAQ,YAAY,gBAAgB;AAC/E,QAAM,WAAW,aAAa,YAAY;AAC1C,QAAM,mBAAmB,cAAc,UAAU,QAAQ;AACzD,QAAM,mBAAmB,UAAU,SAAS,SAAS;AACrD,QAAM,KAAK,QAAQ,OACf;AAAA,IACE,MAAM,QAAQ;AAAA,IACd,SAAS,cAAc,iBAAiB,QAAQ,MAAM,cAAc,QAAQ,IAAI,GAAG,YAAY,QAAQ;AAAA,EACzG,IACA;AACJ,QAAM,SAAS,CAAC,qBAAqB,KAAK,WAAW,QAAQ,QAAQ,GAAG,OAAO,IAAI;AACnF,QAAM,SAAyB;AAAA,IAC7B,SAAS;AAAA,IACT,QAAQ,SAAS,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,WAAW;AAAA,MACT,QAAQ,CAAC,WAAW,YAAY,mBAAmB,YAAY;AAAA,MAC/D,SAAS;AAAA,IACX;AAAA,IACA,GAAI,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;AAAA,EAClC;AACA,QAAM,QAAQ,QAAQ,OAAO;AAE7B,MAAI,UAAU,CAAC,oBAAoB,QAAQ,WAAW,SAAS;AAC7D,YAAQ,OAAO,MAAM,gEAAgE;AAAA,EACvF;AACA,SAAO,SAAS,IAAI;AACtB;;;ADnKA,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCd,IAAM,WAAW,oBAAI,IAAI,CAAC,WAAW,YAAY,OAAO,CAAC;AACzD,IAAM,UAAU,oBAAI,IAAkB,CAAC,SAAS,QAAQ,UAAU,UAAU,CAAC;AAC7E,IAAM,WAAW,oBAAI,IAAI,CAAC,OAAO,YAAY,aAAa,WAAW,MAAM,CAAC;AAC5E,IAAM,cAAc,oBAAI,IAAe,CAAC,OAAO,UAAU,QAAQ,CAAC;AAElE,SAAS,MAAM,MAAc,QAAQ,OAAa;AAChD,GAAC,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,MAAM,KAAK,SAAS,IAAI,IAAI,OAAO,GAAG,IAAI;AAAA,CAAI;AAC1F;AASA,SAAS,eAAe,MAA0B;AAChD,QAAM,QAAQ,KAAK,QAAQ,IAAI;AAC/B,SAAO,UAAU,KAAK,OAAO,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,GAAG,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC;AACjF;AAEA,eAAsB,KAAK,OAAiB,QAAQ,KAAK,MAAM,CAAC,GAAoB;AAClF,MAAI;AACJ,MAAI;AACF,aAAS,UAAU;AAAA,MACjB,MAAM,eAAe,IAAI;AAAA,MACzB,kBAAkB;AAAA,MAClB,SAAS;AAAA,QACP,MAAM,EAAE,MAAM,UAAU,SAAS,QAAQ,IAAI,EAAE;AAAA,QAC/C,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,UAAU,EAAE,MAAM,SAAS;AAAA,QAC3B,QAAQ,EAAE,MAAM,UAAU,UAAU,KAAK;AAAA,QACzC,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,OAAO,EAAE,MAAM,UAAU,UAAU,KAAK;AAAA,QACxC,QAAQ,EAAE,MAAM,UAAU,SAAS,MAAM;AAAA,QACzC,QAAQ,EAAE,MAAM,UAAU,SAAS,QAAQ;AAAA,QAC3C,MAAM,EAAE,MAAM,WAAW,SAAS,MAAM;AAAA,QACxC,OAAO,EAAE,MAAM,WAAW,SAAS,MAAM;AAAA,QACzC,WAAW,EAAE,MAAM,UAAU,SAAS,SAAS;AAAA,QAC/C,QAAQ,EAAE,MAAM,WAAW,SAAS,MAAM;AAAA,QAC1C,MAAM,EAAE,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM;AAAA,QACpD,SAAS,EAAE,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,IAAI;AAClE,UAAM,OAAO,IAAI;AACjB,WAAO;AAAA,EACT;AACA,QAAM,EAAE,QAAQ,YAAY,IAAI;AAChC,MAAI,OAAO,MAAM;AACf,UAAM,KAAK;AACX,WAAO;AAAA,EACT;AACA,MAAI,OAAO,SAAS;AAClB,UAAM,MAAM,YAAY,CAAC;AACzB,WAAO;AAAA,EACT;AACA,QAAM,CAAC,SAAS,GAAG,KAAK,IAAI;AAC5B,MAAI,CAAC,WAAW,CAAC,SAAS,IAAI,OAAO,KAAK,MAAM,SAAS,GAAG;AAC1D,UAAM,YAAY,SAAS,qDAAqD,mBAAmB,WAAW,EAAE,IAAI,IAAI;AACxH,UAAM,OAAO,IAAI;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,SAAU,OAAO,OAAO,SAAS,OAAO,WAAW,OAAO,aAAa,OAAO;AACpF,MAAI,CAAC,QAAQ,IAAI,MAAM,GAAG;AACxB,UAAM,yDAAyD,IAAI;AACnE,WAAO;AAAA,EACT;AACA,QAAM,YAAa,OAAO,SAAS,WAAW,OAAO;AACrD,MAAI,CAAC,YAAY,IAAI,SAAS,GAAG;AAC/B,UAAM,8CAA8C,IAAI;AACxD,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS,IAAI,OAAO,MAAM,GAAG;AAChC,UAAM,+DAA+D,IAAI;AACzE,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,CAAC;AACf,aAAW,SAAS,OAAO,SAAS,CAAC,GAAG;AACtC,UAAM,YAAY,MAAM,YAAY,GAAG;AACvC,UAAM,OAAO,cAAc,KAAK,KAAK,MAAM,MAAM,GAAG,SAAS;AAC7D,UAAM,SAAS,cAAc,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AAChE,QAAI,CAAC,QAAQ,CAAC,iBAAiB,KAAK,MAAM,GAAG;AAC3C,YAAM,4CAA4C,KAAK,KAAK,IAAI;AAChE,aAAO;AAAA,IACT;AACA,UAAM,KAAK,EAAE,SAAS,MAAM,OAAO,CAAC;AAAA,EACtC;AACA,QAAM,UAA0B;AAAA,IAC9B,MAAM,OAAO;AAAA,IACb,GAAI,OAAO,SAAS,EAAE,YAAY,OAAO,OAAO,IAAI,CAAC;AAAA,IACrD,GAAI,OAAO,WAAW,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,IACvD,SAAS,OAAO,UAAU,CAAC;AAAA,IAC3B,GAAI,OAAO,OAAO,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,IAC3C;AAAA,IACA,QAAQ,OAAO;AAAA,IACf,GAAI,MAAM,SAAS,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,CAAC;AAAA,IAC3D,GAAI,OAAO,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;AAAA,IACtC;AAAA,EACF;AACA,MAAI;AACF,QAAI,YAAY,UAAW,QAAO,MAAM,WAAW,OAAO;AAC1D,QAAI,YAAY,WAAY,QAAO,MAAM,YAAY,OAAO;AAC5D,WAAO,MAAM,SAAS,OAAO;AAAA,EAC/B,SAAS,OAAO;AACd,UAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,IAAI;AAClE,QAAI,iBAAiB,SAAS,MAAM,SAAS,QAAQ,IAAI,qBAAqB,GAAG;AAC/E,YAAM,MAAM,OAAO,IAAI;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AACF;AAEA,eAAe,cAA+B;AAC5C,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,IAAS;AAC/C,QAAM,OAAO,cAAc,IAAI,IAAI,mBAAmB,YAAY,GAAG,CAAC;AACtE,SAAQ,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC,EAA0B;AACzE;AAEA,SAAS,kBAA2B;AAClC,QAAM,QAAQ,QAAQ,KAAK,CAAC;AAC5B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,WAAO,cAAc,YAAY,GAAG,MAAM,aAAa,KAAK;AAAA,EAC9D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAI,gBAAgB,GAAG;AACrB,OAAK,KAAK,EAAE,KAAK,CAAC,SAAS;AACzB,YAAQ,WAAW;AAAA,EACrB,CAAC;AACH;","names":[]}
|
|
@@ -121,11 +121,38 @@ function changeCounts(changes) {
|
|
|
121
121
|
// src/report.ts
|
|
122
122
|
import { relative } from "path";
|
|
123
123
|
import { canonicalJson } from "@agent-surface/compiler";
|
|
124
|
+
function verbosityOf(options) {
|
|
125
|
+
return options.verbosity ?? (options.detail ? "detail" : "normal");
|
|
126
|
+
}
|
|
127
|
+
var ANSI = {
|
|
128
|
+
reset: "\x1B[0m",
|
|
129
|
+
bold: "\x1B[1m",
|
|
130
|
+
dim: "\x1B[2m",
|
|
131
|
+
red: "\x1B[31m",
|
|
132
|
+
green: "\x1B[32m",
|
|
133
|
+
yellow: "\x1B[33m",
|
|
134
|
+
blue: "\x1B[34m",
|
|
135
|
+
magenta: "\x1B[35m",
|
|
136
|
+
cyan: "\x1B[36m",
|
|
137
|
+
gray: "\x1B[90m"
|
|
138
|
+
};
|
|
139
|
+
function supportsColor(stream) {
|
|
140
|
+
return stream.isTTY === true && !process.env["CI"] && !process.env["NO_COLOR"] && process.env["TERM"] !== "dumb";
|
|
141
|
+
}
|
|
142
|
+
function painter(options) {
|
|
143
|
+
if (!options.color) return (text) => text;
|
|
144
|
+
return (text, style) => style ? `${ANSI[style] ?? ""}${text}${ANSI.reset}` : text;
|
|
145
|
+
}
|
|
124
146
|
function value(value2) {
|
|
125
147
|
if (value2 === void 0) return "\u2014";
|
|
126
148
|
const text = typeof value2 === "string" ? value2 : JSON.stringify(value2);
|
|
127
149
|
return text.length > 100 ? `${text.slice(0, 97)}\u2026` : text;
|
|
128
150
|
}
|
|
151
|
+
function changeStyle(change) {
|
|
152
|
+
if (change.classification === "widening") return "yellow";
|
|
153
|
+
if (change.classification === "narrowing") return "cyan";
|
|
154
|
+
return "gray";
|
|
155
|
+
}
|
|
129
156
|
function changeLine(change) {
|
|
130
157
|
const mark = change.kind === "added" ? "+" : change.kind === "removed" ? "-" : "~";
|
|
131
158
|
return `${mark} ${change.classification.padEnd(9)} ${change.capabilityId} \xB7 ${change.declarationId} \xB7 ${change.field}${change.kind === "changed" ? `: ${value(change.before)} \u2192 ${value(change.after)}` : ""}`;
|
|
@@ -134,8 +161,12 @@ function sectionTitle(title, changes) {
|
|
|
134
161
|
const counts = changeCounts(changes);
|
|
135
162
|
return `${title} (${changes.length}) \xB7 widening ${counts.widening} \xB7 narrowing ${counts.narrowing} \xB7 neutral ${counts.neutral}`;
|
|
136
163
|
}
|
|
137
|
-
function section(title, changes) {
|
|
138
|
-
|
|
164
|
+
function section(title, changes, options, rows) {
|
|
165
|
+
const paint = painter(options);
|
|
166
|
+
const lines = [paint(sectionTitle(title, changes), "bold")];
|
|
167
|
+
if (!rows) return lines;
|
|
168
|
+
if (changes.length === 0) return [...lines, paint("no changes", "dim")];
|
|
169
|
+
return [...lines, ...changes.map((change) => paint(changeLine(change), changeStyle(change)))];
|
|
139
170
|
}
|
|
140
171
|
var EFFECT_ORDER = [
|
|
141
172
|
"read",
|
|
@@ -165,6 +196,21 @@ function reachOf(effect) {
|
|
|
165
196
|
if (rank <= 3) return "medium";
|
|
166
197
|
return "high";
|
|
167
198
|
}
|
|
199
|
+
var REACH_COLOR = { low: "green", medium: "yellow", high: "red" };
|
|
200
|
+
var EFFECT_COLOR = {
|
|
201
|
+
read: "cyan",
|
|
202
|
+
"local-state": "gray",
|
|
203
|
+
navigation: "blue",
|
|
204
|
+
"server-query": "cyan",
|
|
205
|
+
"server-mutation": "yellow",
|
|
206
|
+
"external-side-effect": "magenta",
|
|
207
|
+
destructive: "red"
|
|
208
|
+
};
|
|
209
|
+
function confirmStyle(confirm) {
|
|
210
|
+
if (confirm === "required") return "green";
|
|
211
|
+
if (confirm === "optional") return "cyan";
|
|
212
|
+
return "dim";
|
|
213
|
+
}
|
|
168
214
|
var NONE = "\u2014";
|
|
169
215
|
var CONTRACT_HEADERS = ["CAPABILITY", "KIND", "EFFECT", "REACH", "CONFIRM", "POLICIES"];
|
|
170
216
|
function contractRow(entry) {
|
|
@@ -210,6 +256,14 @@ function headline(manifest) {
|
|
|
210
256
|
`reach ${reach || NONE} \xB7 declared gates: ${gated} confirmation \xB7 ${policed} policy`
|
|
211
257
|
];
|
|
212
258
|
}
|
|
259
|
+
function integrityWord(report) {
|
|
260
|
+
if (!report.integrity) return void 0;
|
|
261
|
+
return `snapshot ${report.integrity.status}`;
|
|
262
|
+
}
|
|
263
|
+
var CONTRACT_CAVEAT_SHORT = [
|
|
264
|
+
"Declared contract, compiled from the production graph \u2014 what this code can expose,",
|
|
265
|
+
"not what a mount exposed at runtime; a policy's verdict needs a real invocation."
|
|
266
|
+
];
|
|
213
267
|
var CONTRACT_CAVEAT = [
|
|
214
268
|
"Declarations, compiled from the production graph \u2014 what this code can expose,",
|
|
215
269
|
"not what a mount exposed at runtime. CONFIRM and POLICIES are declared per",
|
|
@@ -225,13 +279,28 @@ function contractColumns(capabilities) {
|
|
|
225
279
|
function contractLine(cells, widths) {
|
|
226
280
|
return cells.map((cell, index) => index === cells.length - 1 ? cell : cell.padEnd(widths[index] ?? 0)).join(" ").trimEnd();
|
|
227
281
|
}
|
|
282
|
+
function paintedRow(row, widths, options) {
|
|
283
|
+
const paint = painter(options);
|
|
284
|
+
const cells = contractCells(row).map((cell, index) => index === 5 ? cell : cell.padEnd(widths[index] ?? 0));
|
|
285
|
+
return [
|
|
286
|
+
cells[0],
|
|
287
|
+
paint(cells[1] ?? "", "dim"),
|
|
288
|
+
paint(cells[2] ?? "", EFFECT_COLOR[row.effect]),
|
|
289
|
+
paint(cells[3] ?? "", REACH_COLOR[row.reach]),
|
|
290
|
+
paint(cells[4] ?? "", confirmStyle(row.confirm)),
|
|
291
|
+
row.policies === NONE ? paint(cells[5] ?? "", "dim") : cells[5]
|
|
292
|
+
].join(" ").trimEnd();
|
|
293
|
+
}
|
|
228
294
|
function displayPath(path, root) {
|
|
229
295
|
if (!root) return path;
|
|
230
296
|
const relativePath = relative(root, path);
|
|
231
297
|
return !relativePath || relativePath.startsWith("..") ? path : relativePath;
|
|
232
298
|
}
|
|
233
|
-
function
|
|
234
|
-
|
|
299
|
+
function contractView(report, options = {}) {
|
|
300
|
+
const verbosity = verbosityOf(options);
|
|
301
|
+
if (verbosity === "detail") return "grouped";
|
|
302
|
+
if (report.command !== "inspect" || verbosity === "min") return "none";
|
|
303
|
+
return "flat";
|
|
235
304
|
}
|
|
236
305
|
function summaryFields(report, options = {}) {
|
|
237
306
|
const { manifest } = report;
|
|
@@ -245,32 +314,80 @@ function summaryFields(report, options = {}) {
|
|
|
245
314
|
if (report.integrity) fields.push(["Integrity", report.integrity.status]);
|
|
246
315
|
return fields;
|
|
247
316
|
}
|
|
248
|
-
function
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
|
|
317
|
+
function bannerLine(report, options) {
|
|
318
|
+
const paint = painter(options);
|
|
319
|
+
const ok = report.status !== "fail";
|
|
320
|
+
return paint(
|
|
252
321
|
`AGENT SURFACE ${report.command.toUpperCase()} \xB7 ${report.status.toUpperCase()}`,
|
|
322
|
+
ok ? "green" : "red"
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
function headlineLines(report, options) {
|
|
326
|
+
const paint = painter(options);
|
|
327
|
+
const [size, gates] = headline(report.manifest);
|
|
328
|
+
const integrity = integrityWord(report);
|
|
329
|
+
const stale = report.integrity && report.integrity.status !== "current";
|
|
330
|
+
return [
|
|
331
|
+
paint(size ?? "", "bold"),
|
|
332
|
+
`${gates}${integrity ? ` \xB7 ${stale ? paint(integrity, "yellow") : integrity}` : ""}`
|
|
333
|
+
];
|
|
334
|
+
}
|
|
335
|
+
function flatContract(manifest, options) {
|
|
336
|
+
const paint = painter(options);
|
|
337
|
+
const widths = contractColumns(manifest.capabilities);
|
|
338
|
+
return [
|
|
339
|
+
paint(contractLine(CONTRACT_HEADERS, widths), "dim"),
|
|
340
|
+
...manifest.capabilities.map((entry) => paintedRow(contractRow(entry), widths, options))
|
|
341
|
+
];
|
|
342
|
+
}
|
|
343
|
+
function groupedContract(manifest, options) {
|
|
344
|
+
const paint = painter(options);
|
|
345
|
+
const widths = contractColumns(manifest.capabilities);
|
|
346
|
+
const lines = [
|
|
347
|
+
paint(contractHeading(manifest), "bold"),
|
|
253
348
|
"",
|
|
254
|
-
|
|
255
|
-
"",
|
|
256
|
-
...fields.map(([name, value2]) => `${name.padEnd(label)} ${value2}`)
|
|
349
|
+
` ${paint(contractLine(CONTRACT_HEADERS, widths), "dim")}`
|
|
257
350
|
];
|
|
258
|
-
|
|
351
|
+
for (const group of groupByDeclaration(manifest.capabilities)) {
|
|
352
|
+
lines.push("", `${paint(group.declarationId, "blue")} (${group.entries.length})`);
|
|
353
|
+
for (const entry of group.entries) {
|
|
354
|
+
const row = contractRow(entry);
|
|
355
|
+
lines.push(` ${paintedRow(row, widths, options)}`);
|
|
356
|
+
if (row.note) lines.push(paint(` ${row.note}`, "dim"));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return lines;
|
|
360
|
+
}
|
|
361
|
+
function humanReport(report, options = {}) {
|
|
362
|
+
const paint = painter(options);
|
|
363
|
+
const verbosity = verbosityOf(options);
|
|
364
|
+
const view = contractView(report, options);
|
|
365
|
+
const lines = [];
|
|
366
|
+
if (report.command !== "inspect" || verbosity === "detail") {
|
|
367
|
+
lines.push(bannerLine(report, options), "");
|
|
368
|
+
}
|
|
369
|
+
lines.push(...headlineLines(report, options));
|
|
370
|
+
if (report.command === "snapshot") {
|
|
371
|
+
lines.push("", `wrote ${displayPath(report.snapshotPath, options.root)}`);
|
|
372
|
+
}
|
|
373
|
+
if (verbosity === "detail") {
|
|
374
|
+
const fields = summaryFields(report, options);
|
|
375
|
+
const label = Math.max(...fields.map(([name]) => name.length));
|
|
376
|
+
lines.push("", ...fields.map(([name, value2]) => `${paint(name.padEnd(label), "dim")} ${value2}`));
|
|
377
|
+
}
|
|
378
|
+
const rows = verbosity !== "min";
|
|
379
|
+
if (report.integrity && (report.command === "check" || verbosity === "detail" || report.integrity.changes.length > 0)) {
|
|
380
|
+
lines.push("", ...section("SOURCE \u2194 SNAPSHOT", report.integrity.changes, options, rows));
|
|
381
|
+
}
|
|
259
382
|
if (report.pullRequest) {
|
|
260
|
-
lines.push("", ...section(`PR DRIFT vs ${report.pullRequest.base}`, report.pullRequest.changes));
|
|
383
|
+
lines.push("", ...section(`PR DRIFT vs ${report.pullRequest.base}`, report.pullRequest.changes, options, rows));
|
|
261
384
|
}
|
|
262
|
-
if (
|
|
263
|
-
|
|
264
|
-
lines.push("",
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const row = contractRow(entry);
|
|
269
|
-
lines.push(` ${contractLine(contractCells(row), widths)}`);
|
|
270
|
-
if (options.detail && row.note) lines.push(` ${row.note}`);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
lines.push("", ...CONTRACT_CAVEAT);
|
|
385
|
+
if (view === "flat") {
|
|
386
|
+
lines.push("", ...flatContract(report.manifest, options));
|
|
387
|
+
lines.push("", ...CONTRACT_CAVEAT_SHORT.map((line) => paint(line, "dim")));
|
|
388
|
+
} else if (view === "grouped") {
|
|
389
|
+
lines.push("", ...groupedContract(report.manifest, options));
|
|
390
|
+
lines.push("", ...CONTRACT_CAVEAT.map((line) => paint(line, "dim")));
|
|
274
391
|
}
|
|
275
392
|
return `${lines.join("\n")}
|
|
276
393
|
`;
|
|
@@ -316,18 +433,27 @@ function renderReport(report, format, options = {}) {
|
|
|
316
433
|
export {
|
|
317
434
|
diffContracts,
|
|
318
435
|
changeCounts,
|
|
436
|
+
verbosityOf,
|
|
437
|
+
supportsColor,
|
|
438
|
+
changeStyle,
|
|
319
439
|
sectionTitle,
|
|
320
440
|
groupByDeclaration,
|
|
441
|
+
REACH_COLOR,
|
|
442
|
+
EFFECT_COLOR,
|
|
443
|
+
confirmStyle,
|
|
321
444
|
CONTRACT_HEADERS,
|
|
322
445
|
contractRow,
|
|
323
446
|
contractCells,
|
|
324
447
|
contractHeading,
|
|
325
448
|
headline,
|
|
449
|
+
integrityWord,
|
|
450
|
+
CONTRACT_CAVEAT_SHORT,
|
|
326
451
|
CONTRACT_CAVEAT,
|
|
327
452
|
contractColumns,
|
|
328
453
|
contractLine,
|
|
329
|
-
|
|
454
|
+
displayPath,
|
|
455
|
+
contractView,
|
|
330
456
|
summaryFields,
|
|
331
457
|
renderReport
|
|
332
458
|
};
|
|
333
|
-
//# sourceMappingURL=chunk-
|
|
459
|
+
//# sourceMappingURL=chunk-SBN4KLS2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/diff.ts","../src/report.ts"],"sourcesContent":["import type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\n\nexport type ChangeClassification = \"widening\" | \"narrowing\" | \"neutral\";\nexport type ChangeKind = \"added\" | \"removed\" | \"changed\";\n\nexport interface ContractChange {\n declarationId: string;\n capabilityId: string;\n kind: ChangeKind;\n field: string;\n classification: ChangeClassification;\n before?: unknown;\n after?: unknown;\n}\n\nconst RISK: Record<string, number> = {\n read: 0,\n \"local-state\": 1,\n navigation: 2,\n \"server-query\": 3,\n \"server-mutation\": 4,\n \"external-side-effect\": 5,\n destructive: 6,\n};\n\nconst CONFIRMATION: Record<string, number> = { never: 0, optional: 1, required: 2 };\n\nfunction key(entry: CapabilityContractEntry): string {\n return `${entry.declarationId}\\0${entry.capabilityId}`;\n}\n\nfunction equal(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\nfunction stringSet(value: unknown): Set<string> {\n return new Set(Array.isArray(value) ? value.map((item) => JSON.stringify(item)) : []);\n}\n\nfunction setDirection(before: unknown, after: unknown): \"added\" | \"removed\" | \"mixed\" | \"same\" {\n const a = stringSet(before);\n const b = stringSet(after);\n const added = [...b].some((item) => !a.has(item));\n const removed = [...a].some((item) => !b.has(item));\n if (added && removed) return \"mixed\";\n if (added) return \"added\";\n if (removed) return \"removed\";\n return \"same\";\n}\n\nfunction classify(field: string, before: unknown, after: unknown): ChangeClassification {\n if (field === \"targets\") {\n const direction = setDirection(before, after);\n return direction === \"added\" ? \"widening\" : direction === \"removed\" ? \"narrowing\" : \"neutral\";\n }\n if (field === \"policies\") {\n const direction = setDirection(before, after);\n return direction === \"removed\" || direction === \"mixed\"\n ? \"widening\"\n : direction === \"added\"\n ? \"narrowing\"\n : \"neutral\";\n }\n if (field === \"confirmation\") {\n const a = CONFIRMATION[String(before ?? \"never\")] ?? 0;\n const b = CONFIRMATION[String(after ?? \"never\")] ?? 0;\n return b < a ? \"widening\" : b > a ? \"narrowing\" : \"neutral\";\n }\n if (field === \"effect\") {\n const a = RISK[String(before)] ?? 0;\n const b = RISK[String(after)] ?? 0;\n // Lowering declared risk weakens review/approval posture.\n return b < a ? \"widening\" : b > a ? \"narrowing\" : \"neutral\";\n }\n return \"neutral\";\n}\n\nexport function diffContracts(\n before: CapabilityContractManifest | undefined,\n after: CapabilityContractManifest,\n): ContractChange[] {\n if (!before) {\n return after.capabilities.map((entry) => ({\n declarationId: entry.declarationId,\n capabilityId: entry.capabilityId,\n kind: \"added\",\n field: \"capability\",\n classification: \"widening\",\n after: entry,\n }));\n }\n const left = new Map(before.capabilities.map((entry) => [key(entry), entry]));\n const right = new Map(after.capabilities.map((entry) => [key(entry), entry]));\n const changes: ContractChange[] = [];\n for (const entryKey of [...new Set([...left.keys(), ...right.keys()])].sort()) {\n const a = left.get(entryKey);\n const b = right.get(entryKey);\n if (!a && b) {\n changes.push({\n declarationId: b.declarationId,\n capabilityId: b.capabilityId,\n kind: \"added\",\n field: \"capability\",\n classification: \"widening\",\n after: b,\n });\n continue;\n }\n if (a && !b) {\n changes.push({\n declarationId: a.declarationId,\n capabilityId: a.capabilityId,\n kind: \"removed\",\n field: \"capability\",\n classification: \"narrowing\",\n before: a,\n });\n continue;\n }\n if (!a || !b) continue;\n const fields = new Set([...Object.keys(a), ...Object.keys(b)]);\n fields.delete(\"declarationId\");\n fields.delete(\"capabilityId\");\n fields.delete(\"contractHash\");\n for (const field of [...fields].sort()) {\n const beforeValue = (a as unknown as Record<string, unknown>)[field];\n const afterValue = (b as unknown as Record<string, unknown>)[field];\n if (equal(beforeValue, afterValue)) continue;\n changes.push({\n declarationId: b.declarationId,\n capabilityId: b.capabilityId,\n kind: \"changed\",\n field,\n classification: classify(field, beforeValue, afterValue),\n before: beforeValue,\n after: afterValue,\n });\n }\n }\n return changes;\n}\n\nexport function changeCounts(changes: readonly ContractChange[]): Record<ChangeClassification, number> {\n return {\n widening: changes.filter((change) => change.classification === \"widening\").length,\n narrowing: changes.filter((change) => change.classification === \"narrowing\").length,\n neutral: changes.filter((change) => change.classification === \"neutral\").length,\n };\n}\n","import { relative } from \"node:path\";\nimport type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\nimport { canonicalJson } from \"@agent-surface/compiler\";\nimport type { ContractChange } from \"./diff.js\";\nimport { changeCounts } from \"./diff.js\";\n\nexport type OutputFormat = \"human\" | \"json\" | \"github\" | \"markdown\";\n\n/**\n * How much of the report the human renderers show. `normal` is the compact\n * inventory; `min` stops at the headline and counts; `detail` adds provenance,\n * descriptions and the grouped view. Machine formats ignore the knob: `--json`\n * always carries every field.\n */\nexport type Verbosity = \"min\" | \"normal\" | \"detail\";\n\n/**\n * Presentation-only inputs. They never reach the report model, because `--json`\n * is canonical machine output and a checkout path would make it differ between\n * two machines that compiled the same source.\n */\nexport interface RenderOptions {\n /** Application root, used to show the snapshot path as the user typed it. */\n root?: string;\n /** Deprecated alias for `verbosity: \"detail\"`, kept for the exported API. */\n detail?: boolean;\n /** Human renderings only; `min` and `detail` widen or narrow the same blocks. */\n verbosity?: Verbosity;\n /** Paint with ANSI. Off by default so piped output stays byte-stable. */\n color?: boolean;\n}\n\nexport function verbosityOf(options: RenderOptions): Verbosity {\n return options.verbosity ?? (options.detail ? \"detail\" : \"normal\");\n}\n\nexport interface ContractReport {\n command: \"inspect\" | \"check\" | \"snapshot\";\n status: \"pass\" | \"fail\" | \"written\" | \"view\";\n manifest: CapabilityContractManifest;\n snapshotPath: string;\n integrity?: {\n status: \"current\" | \"missing\" | \"stale\";\n changes: ContractChange[];\n };\n pullRequest?: {\n base: string;\n changes: ContractChange[];\n };\n}\n\n/**\n * The same eight ANSI styles the sibling `orpc-agent` CLI paints with, so the\n * two inventories read alike. Colour is applied after padding and only when\n * the caller asked for it: the tested contract stays the uncoloured bytes.\n */\nconst ANSI: Record<string, string> = {\n reset: \"\\u001b[0m\",\n bold: \"\\u001b[1m\",\n dim: \"\\u001b[2m\",\n red: \"\\u001b[31m\",\n green: \"\\u001b[32m\",\n yellow: \"\\u001b[33m\",\n blue: \"\\u001b[34m\",\n magenta: \"\\u001b[35m\",\n cyan: \"\\u001b[36m\",\n gray: \"\\u001b[90m\",\n};\n\nexport function supportsColor(stream: { isTTY?: boolean }): boolean {\n return (\n stream.isTTY === true &&\n !process.env[\"CI\"] &&\n !process.env[\"NO_COLOR\"] &&\n process.env[\"TERM\"] !== \"dumb\"\n );\n}\n\nfunction painter(options: RenderOptions): (text: string, style?: string) => string {\n if (!options.color) return (text) => text;\n return (text, style) => (style ? `${ANSI[style] ?? \"\"}${text}${ANSI.reset}` : text);\n}\n\nfunction value(value: unknown): string {\n if (value === undefined) return \"—\";\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n return text.length > 100 ? `${text.slice(0, 97)}…` : text;\n}\n\n/** The classification colour, shared by the plain and drawn change rows. */\nexport function changeStyle(change: ContractChange): string {\n if (change.classification === \"widening\") return \"yellow\";\n if (change.classification === \"narrowing\") return \"cyan\";\n return \"gray\";\n}\n\nfunction changeLine(change: ContractChange): string {\n const mark = change.kind === \"added\" ? \"+\" : change.kind === \"removed\" ? \"-\" : \"~\";\n return `${mark} ${change.classification.padEnd(9)} ${change.capabilityId} · ${change.declarationId} · ${change.field}${\n change.kind === \"changed\" ? `: ${value(change.before)} → ${value(change.after)}` : \"\"\n }`;\n}\n\nexport function sectionTitle(title: string, changes: readonly ContractChange[]): string {\n const counts = changeCounts(changes);\n return `${title} (${changes.length}) · widening ${counts.widening} · narrowing ${counts.narrowing} · neutral ${counts.neutral}`;\n}\n\nfunction section(\n title: string,\n changes: readonly ContractChange[],\n options: RenderOptions,\n rows: boolean,\n): string[] {\n const paint = painter(options);\n const lines = [paint(sectionTitle(title, changes), \"bold\")];\n if (!rows) return lines;\n if (changes.length === 0) return [...lines, paint(\"no changes\", \"dim\")];\n return [...lines, ...changes.map((change) => paint(changeLine(change), changeStyle(change)))];\n}\n\n/**\n * Effects in escalating order of reach, so a renderer can grade one without\n * restating the vocabulary. Anything unknown sorts last: a capability whose\n * effect this CLI does not recognize is the one worth looking at.\n */\nconst EFFECT_ORDER = [\n \"read\",\n \"local-state\",\n \"navigation\",\n \"server-query\",\n \"server-mutation\",\n \"external-side-effect\",\n \"destructive\",\n] as const;\n\nexport function effectRank(effect: string): number {\n const index = EFFECT_ORDER.indexOf(effect as (typeof EFFECT_ORDER)[number]);\n return index === -1 ? EFFECT_ORDER.length : index;\n}\n\nexport interface ContractGroup {\n declarationId: string;\n entries: CapabilityContractEntry[];\n}\n\n/** Capabilities grouped by the declaration that owns them, input order kept. */\nexport function groupByDeclaration(capabilities: readonly CapabilityContractEntry[]): ContractGroup[] {\n const groups = new Map<string, CapabilityContractEntry[]>();\n for (const entry of capabilities) {\n const existing = groups.get(entry.declarationId);\n if (existing) existing.push(entry);\n else groups.set(entry.declarationId, [entry]);\n }\n return [...groups].map(([declarationId, entries]) => ({ declarationId, entries }));\n}\n\nexport type Reach = \"low\" | \"medium\" | \"high\";\n\n/**\n * The effect ladder, graded. The effect is the fact; the grade is how it reads\n * to someone who has not memorised the ladder. It is printed as a word rather\n * than left to colour alone, because the streams that matter most — a pipe, a\n * CI log, `--plain` — have no colour to read.\n */\nexport function reachOf(effect: string): Reach {\n const rank = effectRank(effect);\n if (rank <= 1) return \"low\";\n if (rank <= 3) return \"medium\";\n return \"high\";\n}\n\n/**\n * Colour vocabulary shared with the drawn view, one hue per fact. The scale\n * matches the sibling `orpc-agent` CLI: reads cool, writes warm, destructive\n * red, external magenta — so a reader who knows one CLI can skim the other.\n */\nexport const REACH_COLOR: Record<Reach, string> = { low: \"green\", medium: \"yellow\", high: \"red\" };\n\nexport const EFFECT_COLOR: Record<string, string> = {\n read: \"cyan\",\n \"local-state\": \"gray\",\n navigation: \"blue\",\n \"server-query\": \"cyan\",\n \"server-mutation\": \"yellow\",\n \"external-side-effect\": \"magenta\",\n destructive: \"red\",\n};\n\nexport function confirmStyle(confirm: string): string | undefined {\n if (confirm === \"required\") return \"green\";\n if (confirm === \"optional\") return \"cyan\";\n return \"dim\";\n}\n\n/** Nothing declared. A column still has to read as a column. */\nconst NONE = \"—\";\n\nexport const CONTRACT_HEADERS = [\"CAPABILITY\", \"KIND\", \"EFFECT\", \"REACH\", \"CONFIRM\", \"POLICIES\"] as const;\n\nexport interface ContractRow {\n capabilityId: string;\n kind: string;\n effect: string;\n reach: Reach;\n confirm: string;\n policies: string;\n /** Description and tags, shown under detail verbosity. */\n note: string;\n}\n\nexport function contractRow(entry: CapabilityContractEntry): ContractRow {\n const policies = (entry.policies ?? []).map((policy) => `${policy.name}${policy.phase ? `@${policy.phase}` : \"\"}`);\n const tags = (entry.tags ?? []).map((tag) => `#${tag}`).join(\" \");\n return {\n capabilityId: entry.capabilityId,\n kind: entry.kind,\n effect: entry.effect,\n reach: reachOf(entry.effect),\n confirm: entry.confirmation ?? NONE,\n policies: policies.length > 0 ? policies.join(\", \") : NONE,\n note: [entry.description, tags].filter(Boolean).join(\" \"),\n };\n}\n\nexport function contractCells(row: ContractRow): string[] {\n return [row.capabilityId, row.kind, row.effect, row.reach, row.confirm, row.policies];\n}\n\nfunction tally(values: readonly string[]): string {\n const counts = new Map<string, number>();\n for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1);\n return [...counts]\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n .map(([name, count]) => `${count} ${name}`)\n .join(\" · \");\n}\n\nfunction plural(count: number, noun: string, suffix = \"s\"): string {\n return `${count} ${noun}${count === 1 ? \"\" : suffix}`;\n}\n\nexport function contractHeading(manifest: CapabilityContractManifest): string {\n const count = manifest.capabilities.length;\n const groups = groupByDeclaration(manifest.capabilities).length;\n return `REPOSITORY CONTRACT · ${count} ${count === 1 ? \"capability\" : \"capabilities\"} · ${plural(groups, \"declaration\")}`;\n}\n\n/**\n * The answer, before the evidence for it. A reader who stops after this line\n * should still know how large the surface is and how much of it is gated.\n */\nexport function headline(manifest: CapabilityContractManifest): string[] {\n const capabilities = manifest.capabilities;\n const count = capabilities.length;\n const gated = capabilities.filter((entry) => entry.confirmation && entry.confirmation !== \"never\").length;\n const policed = capabilities.filter((entry) => (entry.policies ?? []).length > 0).length;\n // Along the ladder, not by frequency: \"34 low · 1 high · 1 medium\" reads as\n // a miscount rather than a distribution.\n const reach = ([\"low\", \"medium\", \"high\"] as const)\n .map((grade) => [grade, capabilities.filter((entry) => reachOf(entry.effect) === grade).length] as const)\n .filter(([, count]) => count > 0)\n .map(([grade, count]) => `${count} ${grade}`)\n .join(\" · \");\n return [\n `${count} ${count === 1 ? \"capability\" : \"capabilities\"} · ${plural(\n groupByDeclaration(capabilities).length,\n \"declaration\",\n )}${count > 0 ? ` · ${tally(capabilities.map((entry) => entry.kind))}` : \"\"}`,\n `reach ${reach || NONE} · declared gates: ${gated} confirmation · ${policed} policy`,\n ];\n}\n\n/** The integrity word for the headline, so `min` still answers \"am I current\". */\nexport function integrityWord(report: ContractReport): string | undefined {\n if (!report.integrity) return undefined;\n return `snapshot ${report.integrity.status}`;\n}\n\n/**\n * What a compiled contract cannot tell you, in two lines the compact view can\n * afford. The columns are declarations the graph proves reachable — not a\n * transcript of a run.\n */\nexport const CONTRACT_CAVEAT_SHORT = [\n \"Declared contract, compiled from the production graph — what this code can expose,\",\n \"not what a mount exposed at runtime; a policy's verdict needs a real invocation.\",\n];\n\n/** The full statement, kept for detail verbosity where prose has room. */\nexport const CONTRACT_CAVEAT = [\n \"Declarations, compiled from the production graph — what this code can expose,\",\n \"not what a mount exposed at runtime. CONFIRM and POLICIES are declared per\",\n \"capability; whether a policy admits, denies or hides one depends on the actor,\",\n \"input and context of a real invocation, which this command never performs.\",\n];\n\n/** Column widths shared by the plain and drawn renderers, so both align alike. */\nexport function contractColumns(capabilities: readonly CapabilityContractEntry[]): number[] {\n const rows = capabilities.map((entry) => contractCells(contractRow(entry)));\n return CONTRACT_HEADERS.map((header, index) =>\n Math.max(header.length, ...rows.map((cells) => cells[index]?.length ?? 0)),\n );\n}\n\n/** One table line, padded to the shared widths. The last cell is never padded. */\nexport function contractLine(cells: readonly string[], widths: readonly number[]): string {\n return cells\n .map((cell, index) => (index === cells.length - 1 ? cell : cell.padEnd(widths[index] ?? 0)))\n .join(\" \")\n .trimEnd();\n}\n\n/** A table row, each cell padded then painted so the grid survives the colour. */\nfunction paintedRow(row: ContractRow, widths: readonly number[], options: RenderOptions): string {\n const paint = painter(options);\n const cells = contractCells(row).map((cell, index) => (index === 5 ? cell : cell.padEnd(widths[index] ?? 0)));\n return [\n cells[0],\n paint(cells[1] ?? \"\", \"dim\"),\n paint(cells[2] ?? \"\", EFFECT_COLOR[row.effect]),\n paint(cells[3] ?? \"\", REACH_COLOR[row.reach]),\n paint(cells[4] ?? \"\", confirmStyle(row.confirm)),\n row.policies === NONE ? paint(cells[5] ?? \"\", \"dim\") : cells[5],\n ]\n .join(\" \")\n .trimEnd();\n}\n\n/** Show the snapshot where the user would type it, not as an absolute path. */\nexport function displayPath(path: string, root?: string): string {\n if (!root) return path;\n const relativePath = relative(root, path);\n return !relativePath || relativePath.startsWith(\"..\") ? path : relativePath;\n}\n\n/** How the inventory table is drawn, per command and verbosity. */\nexport type ContractView = \"none\" | \"flat\" | \"grouped\";\n\n/**\n * `inspect` exists to show the inventory: compact and flat by default, grouped\n * by declaration under detail. The other commands lead with a verdict and keep\n * the inventory out of the way — until detail is asked for, because the reason\n * to ask a gate for detail is to read what it gated.\n */\nexport function contractView(report: ContractReport, options: RenderOptions = {}): ContractView {\n const verbosity = verbosityOf(options);\n if (verbosity === \"detail\") return \"grouped\";\n if (report.command !== \"inspect\" || verbosity === \"min\") return \"none\";\n return \"flat\";\n}\n\n/** Kept for the exported API; true whenever any inventory is rendered. */\nexport function showsContract(report: ContractReport, options: RenderOptions = {}): boolean {\n return contractView(report, options) !== \"none\";\n}\n\n/** Provenance. True, needed, and not what the reader came for — so it sits below. */\nexport function summaryFields(report: ContractReport, options: RenderOptions = {}): [string, string][] {\n const { manifest } = report;\n const fields: [string, string][] = [\n [\"Contract\", manifest.hash],\n [\"Compiler\", manifest.compilerVersion],\n [\"Completeness\", manifest.completeness.status],\n [\"Targets\", manifest.targets.join(\", \") || NONE],\n [\"Snapshot\", displayPath(report.snapshotPath, options.root)],\n ];\n if (report.integrity) fields.push([\"Integrity\", report.integrity.status]);\n return fields;\n}\n\nfunction bannerLine(report: ContractReport, options: RenderOptions): string {\n const paint = painter(options);\n const ok = report.status !== \"fail\";\n return paint(\n `AGENT SURFACE ${report.command.toUpperCase()} · ${report.status.toUpperCase()}`,\n ok ? \"green\" : \"red\",\n );\n}\n\nfunction headlineLines(report: ContractReport, options: RenderOptions): string[] {\n const paint = painter(options);\n const [size, gates] = headline(report.manifest);\n const integrity = integrityWord(report);\n const stale = report.integrity && report.integrity.status !== \"current\";\n return [\n paint(size ?? \"\", \"bold\"),\n `${gates}${integrity ? ` · ${stale ? paint(integrity, \"yellow\") : integrity}` : \"\"}`,\n ];\n}\n\nfunction flatContract(manifest: CapabilityContractManifest, options: RenderOptions): string[] {\n const paint = painter(options);\n const widths = contractColumns(manifest.capabilities);\n return [\n paint(contractLine(CONTRACT_HEADERS, widths), \"dim\"),\n ...manifest.capabilities.map((entry) => paintedRow(contractRow(entry), widths, options)),\n ];\n}\n\nfunction groupedContract(manifest: CapabilityContractManifest, options: RenderOptions): string[] {\n const paint = painter(options);\n const widths = contractColumns(manifest.capabilities);\n const lines = [\n paint(contractHeading(manifest), \"bold\"),\n \"\",\n ` ${paint(contractLine(CONTRACT_HEADERS, widths), \"dim\")}`,\n ];\n for (const group of groupByDeclaration(manifest.capabilities)) {\n lines.push(\"\", `${paint(group.declarationId, \"blue\")} (${group.entries.length})`);\n for (const entry of group.entries) {\n const row = contractRow(entry);\n lines.push(` ${paintedRow(row, widths, options)}`);\n if (row.note) lines.push(paint(` ${row.note}`, \"dim\"));\n }\n }\n return lines;\n}\n\n/**\n * One human report for every command; verbosity widens or narrows blocks\n * rather than swapping layouts. `min` stops after the headline and change\n * counts; `detail` adds provenance fields, the grouped inventory with notes,\n * and the full caveat.\n */\nexport function humanReport(report: ContractReport, options: RenderOptions = {}): string {\n const paint = painter(options);\n const verbosity = verbosityOf(options);\n const view = contractView(report, options);\n const lines: string[] = [];\n\n // `inspect` leads with the inventory itself; a verdict banner would restate\n // the exit code. The writing and gating commands lead with theirs.\n if (report.command !== \"inspect\" || verbosity === \"detail\") {\n lines.push(bannerLine(report, options), \"\");\n }\n lines.push(...headlineLines(report, options));\n\n if (report.command === \"snapshot\") {\n lines.push(\"\", `wrote ${displayPath(report.snapshotPath, options.root)}`);\n }\n\n if (verbosity === \"detail\") {\n const fields = summaryFields(report, options);\n const label = Math.max(...fields.map(([name]) => name.length));\n lines.push(\"\", ...fields.map(([name, value]) => `${paint(name.padEnd(label), \"dim\")} ${value}`));\n }\n\n // `min` keeps section titles — the counts are the point — and drops rows.\n // Under `normal`, inspect shows integrity rows only when there is drift;\n // an explicit --base always gets its answer, even when that answer is none.\n const rows = verbosity !== \"min\";\n if (report.integrity && (report.command === \"check\" || verbosity === \"detail\" || report.integrity.changes.length > 0)) {\n lines.push(\"\", ...section(\"SOURCE ↔ SNAPSHOT\", report.integrity.changes, options, rows));\n }\n if (report.pullRequest) {\n lines.push(\"\", ...section(`PR DRIFT vs ${report.pullRequest.base}`, report.pullRequest.changes, options, rows));\n }\n\n if (view === \"flat\") {\n lines.push(\"\", ...flatContract(report.manifest, options));\n lines.push(\"\", ...CONTRACT_CAVEAT_SHORT.map((line) => paint(line, \"dim\")));\n } else if (view === \"grouped\") {\n lines.push(\"\", ...groupedContract(report.manifest, options));\n lines.push(\"\", ...CONTRACT_CAVEAT.map((line) => paint(line, \"dim\")));\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction markdownChanges(changes: readonly ContractChange[]): string {\n if (changes.length === 0) return \"No changes.\\n\";\n return [\n \"| Class | Change | Capability | Declaration | Field |\",\n \"|---|---|---|---|---|\",\n ...changes.map(\n (change) =>\n `| ${change.classification} | ${change.kind} | \\`${change.capabilityId}\\` | \\`${change.declarationId}\\` | \\`${change.field}\\` |`,\n ),\n ].join(\"\\n\");\n}\n\nexport function markdownReport(report: ContractReport, github = false): string {\n const lines = [\n `## Agent Surface ${report.command} — ${report.status}`,\n \"\",\n `- Contract: \\`${report.manifest.hash}\\``,\n `- Completeness: **${report.manifest.completeness.status}**`,\n `- Capabilities: **${report.manifest.capabilities.length}**`,\n `- Targets: ${report.manifest.targets.map((target) => `\\`${target}\\``).join(\", \") || \"—\"}`,\n ];\n if (report.integrity) {\n lines.push(\"\", `### Source ↔ snapshot — ${report.integrity.status}`, \"\", markdownChanges(report.integrity.changes));\n }\n if (report.pullRequest) {\n lines.push(\"\", `### PR drift vs \\`${report.pullRequest.base}\\``, \"\", markdownChanges(report.pullRequest.changes));\n }\n if (github && report.status === \"fail\") {\n lines.unshift(`::error title=Agent Surface contract drift::${report.integrity?.changes.length ?? 0} integrity change(s)`);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function renderReport(report: ContractReport, format: OutputFormat, options: RenderOptions = {}): string {\n if (format === \"json\") return canonicalJson(report, true);\n if (format === \"markdown\") return markdownReport(report);\n if (format === \"github\") return markdownReport(report, true);\n return humanReport(report, options);\n}\n"],"mappings":"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","names":["value","value","count","value"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ declare function readManifest(path: string): CapabilityContractManifest | undefi
|
|
|
19
19
|
declare function writeManifest(path: string, manifest: CapabilityContractManifest): void;
|
|
20
20
|
|
|
21
21
|
type OutputFormat = "human" | "json" | "github" | "markdown";
|
|
22
|
+
/**
|
|
23
|
+
* How much of the report the human renderers show. `normal` is the compact
|
|
24
|
+
* inventory; `min` stops at the headline and counts; `detail` adds provenance,
|
|
25
|
+
* descriptions and the grouped view. Machine formats ignore the knob: `--json`
|
|
26
|
+
* always carries every field.
|
|
27
|
+
*/
|
|
28
|
+
type Verbosity = "min" | "normal" | "detail";
|
|
22
29
|
/**
|
|
23
30
|
* Presentation-only inputs. They never reach the report model, because `--json`
|
|
24
31
|
* is canonical machine output and a checkout path would make it differ between
|
|
@@ -27,8 +34,12 @@ type OutputFormat = "human" | "json" | "github" | "markdown";
|
|
|
27
34
|
interface RenderOptions {
|
|
28
35
|
/** Application root, used to show the snapshot path as the user typed it. */
|
|
29
36
|
root?: string;
|
|
30
|
-
/**
|
|
37
|
+
/** Deprecated alias for `verbosity: "detail"`, kept for the exported API. */
|
|
31
38
|
detail?: boolean;
|
|
39
|
+
/** Human renderings only; `min` and `detail` widen or narrow the same blocks. */
|
|
40
|
+
verbosity?: Verbosity;
|
|
41
|
+
/** Paint with ANSI. Off by default so piped output stays byte-stable. */
|
|
42
|
+
color?: boolean;
|
|
32
43
|
}
|
|
33
44
|
interface ContractReport {
|
|
34
45
|
command: "inspect" | "check" | "snapshot";
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CONTRACT_CAVEAT,
|
|
3
|
+
CONTRACT_CAVEAT_SHORT,
|
|
4
|
+
CONTRACT_HEADERS,
|
|
5
|
+
EFFECT_COLOR,
|
|
6
|
+
REACH_COLOR,
|
|
7
|
+
changeStyle,
|
|
8
|
+
confirmStyle,
|
|
9
|
+
contractCells,
|
|
10
|
+
contractColumns,
|
|
11
|
+
contractHeading,
|
|
12
|
+
contractLine,
|
|
13
|
+
contractRow,
|
|
14
|
+
contractView,
|
|
15
|
+
displayPath,
|
|
16
|
+
groupByDeclaration,
|
|
17
|
+
headline,
|
|
18
|
+
integrityWord,
|
|
19
|
+
sectionTitle,
|
|
20
|
+
summaryFields,
|
|
21
|
+
verbosityOf
|
|
22
|
+
} from "./chunk-SBN4KLS2.js";
|
|
23
|
+
|
|
24
|
+
// src/ink.tsx
|
|
25
|
+
import { Box, Text, render } from "ink";
|
|
26
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
27
|
+
function pad(text, width) {
|
|
28
|
+
return text.padEnd(width);
|
|
29
|
+
}
|
|
30
|
+
function Cell({ text, style }) {
|
|
31
|
+
if (!style) return /* @__PURE__ */ jsx(Text, { children: text });
|
|
32
|
+
if (style === "dim") return /* @__PURE__ */ jsx(Text, { dimColor: true, children: text });
|
|
33
|
+
return /* @__PURE__ */ jsx(Text, { color: style, children: text });
|
|
34
|
+
}
|
|
35
|
+
function Summary({ report, options }) {
|
|
36
|
+
const fields = summaryFields(report, options);
|
|
37
|
+
const label = Math.max(...fields.map(([name]) => name.length));
|
|
38
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: fields.map(([name, value]) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
39
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: pad(name, label) }),
|
|
40
|
+
" ",
|
|
41
|
+
/* @__PURE__ */ jsx(Text, { color: name === "Integrity" && value !== "current" ? "yellow" : void 0, children: value })
|
|
42
|
+
] }, name)) });
|
|
43
|
+
}
|
|
44
|
+
function Changes({ title, changes, rows }) {
|
|
45
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
46
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: sectionTitle(title, changes) }),
|
|
47
|
+
!rows ? null : changes.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "no changes" }) : changes.map((change, index) => /* @__PURE__ */ jsxs(
|
|
48
|
+
Text,
|
|
49
|
+
{
|
|
50
|
+
color: changeStyle(change),
|
|
51
|
+
children: [
|
|
52
|
+
change.kind === "added" ? "+" : change.kind === "removed" ? "-" : "~",
|
|
53
|
+
" ",
|
|
54
|
+
change.classification.padEnd(9),
|
|
55
|
+
" ",
|
|
56
|
+
change.capabilityId,
|
|
57
|
+
" \xB7 ",
|
|
58
|
+
change.field
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
`${change.capabilityId}\0${change.declarationId}\0${change.field}\0${index}`
|
|
62
|
+
))
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
function Row({ row, widths, indent }) {
|
|
66
|
+
const [id, kind, effect, reach, confirm, policies] = contractCells(row);
|
|
67
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
68
|
+
indent,
|
|
69
|
+
pad(id ?? "", widths[0] ?? 0),
|
|
70
|
+
" ",
|
|
71
|
+
/* @__PURE__ */ jsx(Cell, { text: pad(kind ?? "", widths[1] ?? 0), style: "dim" }),
|
|
72
|
+
" ",
|
|
73
|
+
/* @__PURE__ */ jsx(Cell, { text: pad(effect ?? "", widths[2] ?? 0), style: EFFECT_COLOR[row.effect] }),
|
|
74
|
+
" ",
|
|
75
|
+
/* @__PURE__ */ jsx(Cell, { text: pad(reach ?? "", widths[3] ?? 0), style: REACH_COLOR[row.reach] }),
|
|
76
|
+
" ",
|
|
77
|
+
/* @__PURE__ */ jsx(Cell, { text: pad(confirm ?? "", widths[4] ?? 0), style: confirmStyle(row.confirm) }),
|
|
78
|
+
" ",
|
|
79
|
+
/* @__PURE__ */ jsx(Cell, { text: policies ?? "", style: row.policies === "\u2014" ? "dim" : void 0 })
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
function FlatContract({ manifest }) {
|
|
83
|
+
const widths = contractColumns(manifest.capabilities);
|
|
84
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
85
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: contractLine(CONTRACT_HEADERS, widths) }),
|
|
86
|
+
manifest.capabilities.map((entry) => /* @__PURE__ */ jsx(Row, { row: contractRow(entry), widths, indent: "" }, `${entry.declarationId}\0${entry.capabilityId}`))
|
|
87
|
+
] });
|
|
88
|
+
}
|
|
89
|
+
function GroupedContract({ manifest }) {
|
|
90
|
+
const widths = contractColumns(manifest.capabilities);
|
|
91
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: contractHeading(manifest) }),
|
|
93
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${contractLine(CONTRACT_HEADERS, widths)}` }) }),
|
|
94
|
+
groupByDeclaration(manifest.capabilities).map((group) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
95
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
96
|
+
/* @__PURE__ */ jsx(Text, { color: "blue", children: group.declarationId }),
|
|
97
|
+
" ",
|
|
98
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
99
|
+
"(",
|
|
100
|
+
group.entries.length,
|
|
101
|
+
")"
|
|
102
|
+
] })
|
|
103
|
+
] }),
|
|
104
|
+
group.entries.map((entry) => /* @__PURE__ */ jsx(Capability, { entry, widths }, entry.capabilityId))
|
|
105
|
+
] }, group.declarationId))
|
|
106
|
+
] });
|
|
107
|
+
}
|
|
108
|
+
function Capability({ entry, widths }) {
|
|
109
|
+
const row = contractRow(entry);
|
|
110
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
111
|
+
/* @__PURE__ */ jsx(Row, { row, widths, indent: " " }),
|
|
112
|
+
row.note ? /* @__PURE__ */ jsx(Box, { paddingLeft: 6, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: row.note }) }) : null
|
|
113
|
+
] });
|
|
114
|
+
}
|
|
115
|
+
function Caveat({ lines, boxed }) {
|
|
116
|
+
if (!boxed) {
|
|
117
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: lines.map((line) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, line)) });
|
|
118
|
+
}
|
|
119
|
+
return (
|
|
120
|
+
// flex-start, or the border stretches to the width of the terminal.
|
|
121
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", alignSelf: "flex-start", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: lines.map((line) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, line)) })
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
function App({ report, options }) {
|
|
125
|
+
const ok = report.status !== "fail";
|
|
126
|
+
const verbosity = verbosityOf(options);
|
|
127
|
+
const view = contractView(report, options);
|
|
128
|
+
const [size, gates] = headline(report.manifest);
|
|
129
|
+
const integrity = integrityWord(report);
|
|
130
|
+
const stale = report.integrity && report.integrity.status !== "current";
|
|
131
|
+
const banner = report.command !== "inspect" || verbosity === "detail";
|
|
132
|
+
const rows = verbosity !== "min";
|
|
133
|
+
const showIntegrity = report.integrity !== void 0 && (report.command === "check" || verbosity === "detail" || report.integrity.changes.length > 0);
|
|
134
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
135
|
+
banner ? /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { bold: true, color: ok ? "green" : "red", children: [
|
|
136
|
+
"AGENT SURFACE ",
|
|
137
|
+
report.command.toUpperCase(),
|
|
138
|
+
" \xB7 ",
|
|
139
|
+
report.status.toUpperCase()
|
|
140
|
+
] }) }) : null,
|
|
141
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: size }),
|
|
142
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
143
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: gates }),
|
|
144
|
+
integrity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
145
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
146
|
+
/* @__PURE__ */ jsx(Text, { color: stale ? "yellow" : void 0, dimColor: !stale, children: integrity })
|
|
147
|
+
] }) : null
|
|
148
|
+
] }),
|
|
149
|
+
report.command === "snapshot" ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
150
|
+
"wrote ",
|
|
151
|
+
displayPath(report.snapshotPath, options.root)
|
|
152
|
+
] }) }) : null,
|
|
153
|
+
verbosity === "detail" ? /* @__PURE__ */ jsx(Summary, { report, options }) : null,
|
|
154
|
+
showIntegrity && report.integrity ? /* @__PURE__ */ jsx(Changes, { title: "SOURCE \u2194 SNAPSHOT", changes: report.integrity.changes, rows }) : null,
|
|
155
|
+
report.pullRequest ? /* @__PURE__ */ jsx(Changes, { title: `PR DRIFT vs ${report.pullRequest.base}`, changes: report.pullRequest.changes, rows }) : null,
|
|
156
|
+
view === "flat" ? /* @__PURE__ */ jsx(FlatContract, { manifest: report.manifest }) : null,
|
|
157
|
+
view === "grouped" ? /* @__PURE__ */ jsx(GroupedContract, { manifest: report.manifest }) : null,
|
|
158
|
+
view === "flat" ? /* @__PURE__ */ jsx(Caveat, { lines: CONTRACT_CAVEAT_SHORT, boxed: false }) : null,
|
|
159
|
+
view === "grouped" ? /* @__PURE__ */ jsx(Caveat, { lines: CONTRACT_CAVEAT, boxed: true }) : null
|
|
160
|
+
] });
|
|
161
|
+
}
|
|
162
|
+
async function renderInk(report, options = {}) {
|
|
163
|
+
const instance = render(/* @__PURE__ */ jsx(App, { report, options }));
|
|
164
|
+
await instance.waitUntilExit();
|
|
165
|
+
}
|
|
166
|
+
export {
|
|
167
|
+
renderInk
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=ink-7PDZ7AIC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ink.tsx"],"sourcesContent":["import { Box, Text, render } from \"ink\";\nimport type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\nimport type { ContractChange } from \"./diff.js\";\nimport type { ContractReport, ContractRow, RenderOptions } from \"./report.js\";\nimport {\n CONTRACT_CAVEAT,\n CONTRACT_CAVEAT_SHORT,\n CONTRACT_HEADERS,\n EFFECT_COLOR,\n REACH_COLOR,\n changeStyle,\n confirmStyle,\n contractCells,\n contractColumns,\n contractHeading,\n contractLine,\n contractRow,\n contractView,\n displayPath,\n groupByDeclaration,\n headline,\n integrityWord,\n sectionTitle,\n summaryFields,\n verbosityOf,\n} from \"./report.js\";\n\n/**\n * The drawn twin of `humanReport`: same blocks, same words, same colour\n * vocabulary — colour repeats a word, it never carries the fact alone.\n */\n\nfunction pad(text: string, width: number): string {\n return text.padEnd(width);\n}\n\n/** Ink takes the style names as colours; \"dim\" alone maps to dimColor. */\nfunction Cell({ text, style }: { text: string; style?: string | undefined }) {\n if (!style) return <Text>{text}</Text>;\n if (style === \"dim\") return <Text dimColor>{text}</Text>;\n return <Text color={style}>{text}</Text>;\n}\n\nfunction Summary({ report, options }: { report: ContractReport; options: RenderOptions }) {\n const fields = summaryFields(report, options);\n const label = Math.max(...fields.map(([name]) => name.length));\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {fields.map(([name, value]) => (\n <Text key={name}>\n <Text dimColor>{pad(name, label)}</Text>\n {\" \"}\n <Text color={name === \"Integrity\" && value !== \"current\" ? \"yellow\" : undefined}>{value}</Text>\n </Text>\n ))}\n </Box>\n );\n}\n\nfunction Changes({ title, changes, rows }: { title: string; changes: ContractChange[]; rows: boolean }) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>{sectionTitle(title, changes)}</Text>\n {!rows ? null : changes.length === 0 ? (\n <Text dimColor>no changes</Text>\n ) : (\n changes.map((change, index) => (\n <Text\n key={`${change.capabilityId}\\0${change.declarationId}\\0${change.field}\\0${index}`}\n color={changeStyle(change)}\n >\n {change.kind === \"added\" ? \"+\" : change.kind === \"removed\" ? \"-\" : \"~\"} {change.classification.padEnd(9)}{\" \"}\n {change.capabilityId} · {change.field}\n </Text>\n ))\n )}\n </Box>\n );\n}\n\nfunction Row({ row, widths, indent }: { row: ContractRow; widths: number[]; indent: string }) {\n const [id, kind, effect, reach, confirm, policies] = contractCells(row);\n return (\n <Text>\n {indent}\n {pad(id ?? \"\", widths[0] ?? 0)}\n {\" \"}\n <Cell text={pad(kind ?? \"\", widths[1] ?? 0)} style=\"dim\" />\n {\" \"}\n <Cell text={pad(effect ?? \"\", widths[2] ?? 0)} style={EFFECT_COLOR[row.effect]} />\n {\" \"}\n <Cell text={pad(reach ?? \"\", widths[3] ?? 0)} style={REACH_COLOR[row.reach]} />\n {\" \"}\n <Cell text={pad(confirm ?? \"\", widths[4] ?? 0)} style={confirmStyle(row.confirm)} />\n {\" \"}\n <Cell text={policies ?? \"\"} style={row.policies === \"—\" ? \"dim\" : undefined} />\n </Text>\n );\n}\n\nfunction FlatContract({ manifest }: { manifest: CapabilityContractManifest }) {\n const widths = contractColumns(manifest.capabilities);\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text dimColor>{contractLine(CONTRACT_HEADERS, widths)}</Text>\n {manifest.capabilities.map((entry) => (\n <Row key={`${entry.declarationId}\\0${entry.capabilityId}`} row={contractRow(entry)} widths={widths} indent=\"\" />\n ))}\n </Box>\n );\n}\n\nfunction GroupedContract({ manifest }: { manifest: CapabilityContractManifest }) {\n const widths = contractColumns(manifest.capabilities);\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>{contractHeading(manifest)}</Text>\n <Box marginTop={1}>\n <Text dimColor>{` ${contractLine(CONTRACT_HEADERS, widths)}`}</Text>\n </Box>\n {groupByDeclaration(manifest.capabilities).map((group) => (\n <Box key={group.declarationId} flexDirection=\"column\" marginTop={1}>\n <Text>\n <Text color=\"blue\">{group.declarationId}</Text> <Text dimColor>({group.entries.length})</Text>\n </Text>\n {group.entries.map((entry) => (\n <Capability key={entry.capabilityId} entry={entry} widths={widths} />\n ))}\n </Box>\n ))}\n </Box>\n );\n}\n\nfunction Capability({ entry, widths }: { entry: CapabilityContractEntry; widths: number[] }) {\n const row = contractRow(entry);\n return (\n <Box flexDirection=\"column\">\n <Row row={row} widths={widths} indent=\" \" />\n {/* Padding rather than a prefix, so a wrapped description stays in its column. */}\n {row.note ? (\n <Box paddingLeft={6}>\n <Text dimColor>{row.note}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction Caveat({ lines, boxed }: { lines: readonly string[]; boxed: boolean }) {\n if (!boxed) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {lines.map((line) => (\n <Text key={line} dimColor>\n {line}\n </Text>\n ))}\n </Box>\n );\n }\n return (\n // flex-start, or the border stretches to the width of the terminal.\n <Box flexDirection=\"column\" alignSelf=\"flex-start\" marginTop={1} borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n {lines.map((line) => (\n <Text key={line} dimColor>\n {line}\n </Text>\n ))}\n </Box>\n );\n}\n\nfunction App({ report, options }: { report: ContractReport; options: RenderOptions }) {\n const ok = report.status !== \"fail\";\n const verbosity = verbosityOf(options);\n const view = contractView(report, options);\n const [size, gates] = headline(report.manifest);\n const integrity = integrityWord(report);\n const stale = report.integrity && report.integrity.status !== \"current\";\n const banner = report.command !== \"inspect\" || verbosity === \"detail\";\n const rows = verbosity !== \"min\";\n const showIntegrity =\n report.integrity !== undefined &&\n (report.command === \"check\" || verbosity === \"detail\" || report.integrity.changes.length > 0);\n return (\n <Box flexDirection=\"column\">\n {banner ? (\n <Box marginBottom={1}>\n <Text bold color={ok ? \"green\" : \"red\"}>\n AGENT SURFACE {report.command.toUpperCase()} · {report.status.toUpperCase()}\n </Text>\n </Box>\n ) : null}\n <Text bold>{size}</Text>\n <Text>\n <Text dimColor>{gates}</Text>\n {integrity ? (\n <>\n <Text dimColor> · </Text>\n <Text color={stale ? \"yellow\" : undefined} dimColor={!stale}>\n {integrity}\n </Text>\n </>\n ) : null}\n </Text>\n {report.command === \"snapshot\" ? (\n <Box marginTop={1}>\n <Text>wrote {displayPath(report.snapshotPath, options.root)}</Text>\n </Box>\n ) : null}\n {verbosity === \"detail\" ? <Summary report={report} options={options} /> : null}\n {showIntegrity && report.integrity ? (\n <Changes title=\"SOURCE ↔ SNAPSHOT\" changes={report.integrity.changes} rows={rows} />\n ) : null}\n {report.pullRequest ? (\n <Changes title={`PR DRIFT vs ${report.pullRequest.base}`} changes={report.pullRequest.changes} rows={rows} />\n ) : null}\n {view === \"flat\" ? <FlatContract manifest={report.manifest} /> : null}\n {view === \"grouped\" ? <GroupedContract manifest={report.manifest} /> : null}\n {view === \"flat\" ? <Caveat lines={CONTRACT_CAVEAT_SHORT} boxed={false} /> : null}\n {view === \"grouped\" ? <Caveat lines={CONTRACT_CAVEAT} boxed /> : null}\n </Box>\n );\n}\n\nexport async function renderInk(report: ContractReport, options: RenderOptions = {}): Promise<void> {\n const instance = render(<App report={report} options={options} />);\n await instance.waitUntilExit();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,KAAK,MAAM,cAAc;AAsCb,SAgKX,UAhKW,KAWb,YAXa;AANrB,SAAS,IAAI,MAAc,OAAuB;AAChD,SAAO,KAAK,OAAO,KAAK;AAC1B;AAGA,SAAS,KAAK,EAAE,MAAM,MAAM,GAAiD;AAC3E,MAAI,CAAC,MAAO,QAAO,oBAAC,QAAM,gBAAK;AAC/B,MAAI,UAAU,MAAO,QAAO,oBAAC,QAAK,UAAQ,MAAE,gBAAK;AACjD,SAAO,oBAAC,QAAK,OAAO,OAAQ,gBAAK;AACnC;AAEA,SAAS,QAAQ,EAAE,QAAQ,QAAQ,GAAuD;AACxF,QAAM,SAAS,cAAc,QAAQ,OAAO;AAC5C,QAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,CAAC;AAC7D,SACE,oBAAC,OAAI,eAAc,UAAS,WAAW,GACpC,iBAAO,IAAI,CAAC,CAAC,MAAM,KAAK,MACvB,qBAAC,QACC;AAAA,wBAAC,QAAK,UAAQ,MAAE,cAAI,MAAM,KAAK,GAAE;AAAA,IAChC;AAAA,IACD,oBAAC,QAAK,OAAO,SAAS,eAAe,UAAU,YAAY,WAAW,QAAY,iBAAM;AAAA,OAH/E,IAIX,CACD,GACH;AAEJ;AAEA,SAAS,QAAQ,EAAE,OAAO,SAAS,KAAK,GAAgE;AACtG,SACE,qBAAC,OAAI,eAAc,UAAS,WAAW,GACrC;AAAA,wBAAC,QAAK,MAAI,MAAE,uBAAa,OAAO,OAAO,GAAE;AAAA,IACxC,CAAC,OAAO,OAAO,QAAQ,WAAW,IACjC,oBAAC,QAAK,UAAQ,MAAC,wBAAU,IAEzB,QAAQ,IAAI,CAAC,QAAQ,UACnB;AAAA,MAAC;AAAA;AAAA,QAEC,OAAO,YAAY,MAAM;AAAA,QAExB;AAAA,iBAAO,SAAS,UAAU,MAAM,OAAO,SAAS,YAAY,MAAM;AAAA,UAAI;AAAA,UAAE,OAAO,eAAe,OAAO,CAAC;AAAA,UAAG;AAAA,UACzG,OAAO;AAAA,UAAa;AAAA,UAAI,OAAO;AAAA;AAAA;AAAA,MAJ3B,GAAG,OAAO,YAAY,KAAK,OAAO,aAAa,KAAK,OAAO,KAAK,KAAK,KAAK;AAAA,IAKjF,CACD;AAAA,KAEL;AAEJ;AAEA,SAAS,IAAI,EAAE,KAAK,QAAQ,OAAO,GAA2D;AAC5F,QAAM,CAAC,IAAI,MAAM,QAAQ,OAAO,SAAS,QAAQ,IAAI,cAAc,GAAG;AACtE,SACE,qBAAC,QACE;AAAA;AAAA,IACA,IAAI,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC;AAAA,IAC5B;AAAA,IACD,oBAAC,QAAK,MAAM,IAAI,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,OAAM,OAAM;AAAA,IACxD;AAAA,IACD,oBAAC,QAAK,MAAM,IAAI,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,aAAa,IAAI,MAAM,GAAG;AAAA,IAC/E;AAAA,IACD,oBAAC,QAAK,MAAM,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,YAAY,IAAI,KAAK,GAAG;AAAA,IAC5E;AAAA,IACD,oBAAC,QAAK,MAAM,IAAI,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,aAAa,IAAI,OAAO,GAAG;AAAA,IACjF;AAAA,IACD,oBAAC,QAAK,MAAM,YAAY,IAAI,OAAO,IAAI,aAAa,WAAM,QAAQ,QAAW;AAAA,KAC/E;AAEJ;AAEA,SAAS,aAAa,EAAE,SAAS,GAA6C;AAC5E,QAAM,SAAS,gBAAgB,SAAS,YAAY;AACpD,SACE,qBAAC,OAAI,eAAc,UAAS,WAAW,GACrC;AAAA,wBAAC,QAAK,UAAQ,MAAE,uBAAa,kBAAkB,MAAM,GAAE;AAAA,IACtD,SAAS,aAAa,IAAI,CAAC,UAC1B,oBAAC,OAA0D,KAAK,YAAY,KAAK,GAAG,QAAgB,QAAO,MAAjG,GAAG,MAAM,aAAa,KAAK,MAAM,YAAY,EAAuD,CAC/G;AAAA,KACH;AAEJ;AAEA,SAAS,gBAAgB,EAAE,SAAS,GAA6C;AAC/E,QAAM,SAAS,gBAAgB,SAAS,YAAY;AACpD,SACE,qBAAC,OAAI,eAAc,UAAS,WAAW,GACrC;AAAA,wBAAC,QAAK,MAAI,MAAE,0BAAgB,QAAQ,GAAE;AAAA,IACtC,oBAAC,OAAI,WAAW,GACd,8BAAC,QAAK,UAAQ,MAAE,eAAK,aAAa,kBAAkB,MAAM,CAAC,IAAG,GAChE;AAAA,IACC,mBAAmB,SAAS,YAAY,EAAE,IAAI,CAAC,UAC9C,qBAAC,OAA8B,eAAc,UAAS,WAAW,GAC/D;AAAA,2BAAC,QACC;AAAA,4BAAC,QAAK,OAAM,QAAQ,gBAAM,eAAc;AAAA,QAAO;AAAA,QAAC,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,UAAE,MAAM,QAAQ;AAAA,UAAO;AAAA,WAAC;AAAA,SACzF;AAAA,MACC,MAAM,QAAQ,IAAI,CAAC,UAClB,oBAAC,cAAoC,OAAc,UAAlC,MAAM,YAA4C,CACpE;AAAA,SANO,MAAM,aAOhB,CACD;AAAA,KACH;AAEJ;AAEA,SAAS,WAAW,EAAE,OAAO,OAAO,GAAyD;AAC3F,QAAM,MAAM,YAAY,KAAK;AAC7B,SACE,qBAAC,OAAI,eAAc,UACjB;AAAA,wBAAC,OAAI,KAAU,QAAgB,QAAO,MAAK;AAAA,IAE1C,IAAI,OACH,oBAAC,OAAI,aAAa,GAChB,8BAAC,QAAK,UAAQ,MAAE,cAAI,MAAK,GAC3B,IACE;AAAA,KACN;AAEJ;AAEA,SAAS,OAAO,EAAE,OAAO,MAAM,GAAiD;AAC9E,MAAI,CAAC,OAAO;AACV,WACE,oBAAC,OAAI,eAAc,UAAS,WAAW,GACpC,gBAAM,IAAI,CAAC,SACV,oBAAC,QAAgB,UAAQ,MACtB,kBADQ,IAEX,CACD,GACH;AAAA,EAEJ;AACA;AAAA;AAAA,IAEE,oBAAC,OAAI,eAAc,UAAS,WAAU,cAAa,WAAW,GAAG,aAAY,SAAQ,aAAY,QAAO,UAAU,GAC/G,gBAAM,IAAI,CAAC,SACV,oBAAC,QAAgB,UAAQ,MACtB,kBADQ,IAEX,CACD,GACH;AAAA;AAEJ;AAEA,SAAS,IAAI,EAAE,QAAQ,QAAQ,GAAuD;AACpF,QAAM,KAAK,OAAO,WAAW;AAC7B,QAAM,YAAY,YAAY,OAAO;AACrC,QAAM,OAAO,aAAa,QAAQ,OAAO;AACzC,QAAM,CAAC,MAAM,KAAK,IAAI,SAAS,OAAO,QAAQ;AAC9C,QAAM,YAAY,cAAc,MAAM;AACtC,QAAM,QAAQ,OAAO,aAAa,OAAO,UAAU,WAAW;AAC9D,QAAM,SAAS,OAAO,YAAY,aAAa,cAAc;AAC7D,QAAM,OAAO,cAAc;AAC3B,QAAM,gBACJ,OAAO,cAAc,WACpB,OAAO,YAAY,WAAW,cAAc,YAAY,OAAO,UAAU,QAAQ,SAAS;AAC7F,SACE,qBAAC,OAAI,eAAc,UAChB;AAAA,aACC,oBAAC,OAAI,cAAc,GACjB,+BAAC,QAAK,MAAI,MAAC,OAAO,KAAK,UAAU,OAAO;AAAA;AAAA,MACvB,OAAO,QAAQ,YAAY;AAAA,MAAE;AAAA,MAAI,OAAO,OAAO,YAAY;AAAA,OAC5E,GACF,IACE;AAAA,IACJ,oBAAC,QAAK,MAAI,MAAE,gBAAK;AAAA,IACjB,qBAAC,QACC;AAAA,0BAAC,QAAK,UAAQ,MAAE,iBAAM;AAAA,MACrB,YACC,iCACE;AAAA,4BAAC,QAAK,UAAQ,MAAC,oBAAG;AAAA,QAClB,oBAAC,QAAK,OAAO,QAAQ,WAAW,QAAW,UAAU,CAAC,OACnD,qBACH;AAAA,SACF,IACE;AAAA,OACN;AAAA,IACC,OAAO,YAAY,aAClB,oBAAC,OAAI,WAAW,GACd,+BAAC,QAAK;AAAA;AAAA,MAAO,YAAY,OAAO,cAAc,QAAQ,IAAI;AAAA,OAAE,GAC9D,IACE;AAAA,IACH,cAAc,WAAW,oBAAC,WAAQ,QAAgB,SAAkB,IAAK;AAAA,IACzE,iBAAiB,OAAO,YACvB,oBAAC,WAAQ,OAAM,0BAAoB,SAAS,OAAO,UAAU,SAAS,MAAY,IAChF;AAAA,IACH,OAAO,cACN,oBAAC,WAAQ,OAAO,eAAe,OAAO,YAAY,IAAI,IAAI,SAAS,OAAO,YAAY,SAAS,MAAY,IACzG;AAAA,IACH,SAAS,SAAS,oBAAC,gBAAa,UAAU,OAAO,UAAU,IAAK;AAAA,IAChE,SAAS,YAAY,oBAAC,mBAAgB,UAAU,OAAO,UAAU,IAAK;AAAA,IACtE,SAAS,SAAS,oBAAC,UAAO,OAAO,uBAAuB,OAAO,OAAO,IAAK;AAAA,IAC3E,SAAS,YAAY,oBAAC,UAAO,OAAO,iBAAiB,OAAK,MAAC,IAAK;AAAA,KACnE;AAEJ;AAEA,eAAsB,UAAU,QAAwB,UAAyB,CAAC,GAAkB;AAClG,QAAM,WAAW,OAAO,oBAAC,OAAI,QAAgB,SAAkB,CAAE;AACjE,QAAM,SAAS,cAAc;AAC/B;","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/diff.ts","../src/report.ts"],"sourcesContent":["import type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\n\nexport type ChangeClassification = \"widening\" | \"narrowing\" | \"neutral\";\nexport type ChangeKind = \"added\" | \"removed\" | \"changed\";\n\nexport interface ContractChange {\n declarationId: string;\n capabilityId: string;\n kind: ChangeKind;\n field: string;\n classification: ChangeClassification;\n before?: unknown;\n after?: unknown;\n}\n\nconst RISK: Record<string, number> = {\n read: 0,\n \"local-state\": 1,\n navigation: 2,\n \"server-query\": 3,\n \"server-mutation\": 4,\n \"external-side-effect\": 5,\n destructive: 6,\n};\n\nconst CONFIRMATION: Record<string, number> = { never: 0, optional: 1, required: 2 };\n\nfunction key(entry: CapabilityContractEntry): string {\n return `${entry.declarationId}\\0${entry.capabilityId}`;\n}\n\nfunction equal(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\nfunction stringSet(value: unknown): Set<string> {\n return new Set(Array.isArray(value) ? value.map((item) => JSON.stringify(item)) : []);\n}\n\nfunction setDirection(before: unknown, after: unknown): \"added\" | \"removed\" | \"mixed\" | \"same\" {\n const a = stringSet(before);\n const b = stringSet(after);\n const added = [...b].some((item) => !a.has(item));\n const removed = [...a].some((item) => !b.has(item));\n if (added && removed) return \"mixed\";\n if (added) return \"added\";\n if (removed) return \"removed\";\n return \"same\";\n}\n\nfunction classify(field: string, before: unknown, after: unknown): ChangeClassification {\n if (field === \"targets\") {\n const direction = setDirection(before, after);\n return direction === \"added\" ? \"widening\" : direction === \"removed\" ? \"narrowing\" : \"neutral\";\n }\n if (field === \"policies\") {\n const direction = setDirection(before, after);\n return direction === \"removed\" || direction === \"mixed\"\n ? \"widening\"\n : direction === \"added\"\n ? \"narrowing\"\n : \"neutral\";\n }\n if (field === \"confirmation\") {\n const a = CONFIRMATION[String(before ?? \"never\")] ?? 0;\n const b = CONFIRMATION[String(after ?? \"never\")] ?? 0;\n return b < a ? \"widening\" : b > a ? \"narrowing\" : \"neutral\";\n }\n if (field === \"effect\") {\n const a = RISK[String(before)] ?? 0;\n const b = RISK[String(after)] ?? 0;\n // Lowering declared risk weakens review/approval posture.\n return b < a ? \"widening\" : b > a ? \"narrowing\" : \"neutral\";\n }\n return \"neutral\";\n}\n\nexport function diffContracts(\n before: CapabilityContractManifest | undefined,\n after: CapabilityContractManifest,\n): ContractChange[] {\n if (!before) {\n return after.capabilities.map((entry) => ({\n declarationId: entry.declarationId,\n capabilityId: entry.capabilityId,\n kind: \"added\",\n field: \"capability\",\n classification: \"widening\",\n after: entry,\n }));\n }\n const left = new Map(before.capabilities.map((entry) => [key(entry), entry]));\n const right = new Map(after.capabilities.map((entry) => [key(entry), entry]));\n const changes: ContractChange[] = [];\n for (const entryKey of [...new Set([...left.keys(), ...right.keys()])].sort()) {\n const a = left.get(entryKey);\n const b = right.get(entryKey);\n if (!a && b) {\n changes.push({\n declarationId: b.declarationId,\n capabilityId: b.capabilityId,\n kind: \"added\",\n field: \"capability\",\n classification: \"widening\",\n after: b,\n });\n continue;\n }\n if (a && !b) {\n changes.push({\n declarationId: a.declarationId,\n capabilityId: a.capabilityId,\n kind: \"removed\",\n field: \"capability\",\n classification: \"narrowing\",\n before: a,\n });\n continue;\n }\n if (!a || !b) continue;\n const fields = new Set([...Object.keys(a), ...Object.keys(b)]);\n fields.delete(\"declarationId\");\n fields.delete(\"capabilityId\");\n fields.delete(\"contractHash\");\n for (const field of [...fields].sort()) {\n const beforeValue = (a as unknown as Record<string, unknown>)[field];\n const afterValue = (b as unknown as Record<string, unknown>)[field];\n if (equal(beforeValue, afterValue)) continue;\n changes.push({\n declarationId: b.declarationId,\n capabilityId: b.capabilityId,\n kind: \"changed\",\n field,\n classification: classify(field, beforeValue, afterValue),\n before: beforeValue,\n after: afterValue,\n });\n }\n }\n return changes;\n}\n\nexport function changeCounts(changes: readonly ContractChange[]): Record<ChangeClassification, number> {\n return {\n widening: changes.filter((change) => change.classification === \"widening\").length,\n narrowing: changes.filter((change) => change.classification === \"narrowing\").length,\n neutral: changes.filter((change) => change.classification === \"neutral\").length,\n };\n}\n","import { relative } from \"node:path\";\nimport type { CapabilityContractEntry, CapabilityContractManifest } from \"@agent-surface/core\";\nimport { canonicalJson } from \"@agent-surface/compiler\";\nimport type { ContractChange } from \"./diff.js\";\nimport { changeCounts } from \"./diff.js\";\n\nexport type OutputFormat = \"human\" | \"json\" | \"github\" | \"markdown\";\n\n/**\n * Presentation-only inputs. They never reach the report model, because `--json`\n * is canonical machine output and a checkout path would make it differ between\n * two machines that compiled the same source.\n */\nexport interface RenderOptions {\n /** Application root, used to show the snapshot path as the user typed it. */\n root?: string;\n /** Include descriptions, confirmation, policies, and tags. */\n detail?: boolean;\n}\n\nexport interface ContractReport {\n command: \"inspect\" | \"check\" | \"snapshot\";\n status: \"pass\" | \"fail\" | \"written\" | \"view\";\n manifest: CapabilityContractManifest;\n snapshotPath: string;\n integrity?: {\n status: \"current\" | \"missing\" | \"stale\";\n changes: ContractChange[];\n };\n pullRequest?: {\n base: string;\n changes: ContractChange[];\n };\n}\n\nfunction value(value: unknown): string {\n if (value === undefined) return \"—\";\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n return text.length > 100 ? `${text.slice(0, 97)}…` : text;\n}\n\nfunction changeLine(change: ContractChange): string {\n const mark = change.kind === \"added\" ? \"+\" : change.kind === \"removed\" ? \"-\" : \"~\";\n return `${mark} ${change.classification.padEnd(9)} ${change.capabilityId} · ${change.declarationId} · ${change.field}${\n change.kind === \"changed\" ? `: ${value(change.before)} → ${value(change.after)}` : \"\"\n }`;\n}\n\nexport function sectionTitle(title: string, changes: readonly ContractChange[]): string {\n const counts = changeCounts(changes);\n return `${title} (${changes.length}) · widening ${counts.widening} · narrowing ${counts.narrowing} · neutral ${counts.neutral}`;\n}\n\nfunction section(title: string, changes: readonly ContractChange[]): string[] {\n return [sectionTitle(title, changes), ...(changes.length > 0 ? changes.map(changeLine) : [\"no changes\"])];\n}\n\n/**\n * Effects in escalating order of reach, so a renderer can grade one without\n * restating the vocabulary. Anything unknown sorts last: a capability whose\n * effect this CLI does not recognize is the one worth looking at.\n */\nconst EFFECT_ORDER = [\n \"read\",\n \"local-state\",\n \"navigation\",\n \"server-query\",\n \"server-mutation\",\n \"external-side-effect\",\n \"destructive\",\n] as const;\n\nexport function effectRank(effect: string): number {\n const index = EFFECT_ORDER.indexOf(effect as (typeof EFFECT_ORDER)[number]);\n return index === -1 ? EFFECT_ORDER.length : index;\n}\n\nexport interface ContractGroup {\n declarationId: string;\n entries: CapabilityContractEntry[];\n}\n\n/** Capabilities grouped by the declaration that owns them, input order kept. */\nexport function groupByDeclaration(capabilities: readonly CapabilityContractEntry[]): ContractGroup[] {\n const groups = new Map<string, CapabilityContractEntry[]>();\n for (const entry of capabilities) {\n const existing = groups.get(entry.declarationId);\n if (existing) existing.push(entry);\n else groups.set(entry.declarationId, [entry]);\n }\n return [...groups].map(([declarationId, entries]) => ({ declarationId, entries }));\n}\n\nexport type Reach = \"low\" | \"medium\" | \"high\";\n\n/**\n * The effect ladder, graded. The effect is the fact; the grade is how it reads\n * to someone who has not memorised the ladder. It is printed as a word rather\n * than left to colour alone, because the streams that matter most — a pipe, a\n * CI log, `--plain` — have no colour to read.\n */\nexport function reachOf(effect: string): Reach {\n const rank = effectRank(effect);\n if (rank <= 1) return \"low\";\n if (rank <= 3) return \"medium\";\n return \"high\";\n}\n\n/** Nothing declared. A column still has to read as a column. */\nconst NONE = \"—\";\n\nexport const CONTRACT_HEADERS = [\"CAPABILITY\", \"KIND\", \"EFFECT\", \"REACH\", \"CONFIRM\", \"POLICIES\"] as const;\n\nexport interface ContractRow {\n capabilityId: string;\n kind: string;\n effect: string;\n reach: Reach;\n confirm: string;\n policies: string;\n /** Description and tags, shown under --detail. */\n note: string;\n}\n\nexport function contractRow(entry: CapabilityContractEntry): ContractRow {\n const policies = (entry.policies ?? []).map((policy) => `${policy.name}${policy.phase ? `@${policy.phase}` : \"\"}`);\n const tags = (entry.tags ?? []).map((tag) => `#${tag}`).join(\" \");\n return {\n capabilityId: entry.capabilityId,\n kind: entry.kind,\n effect: entry.effect,\n reach: reachOf(entry.effect),\n confirm: entry.confirmation ?? NONE,\n policies: policies.length > 0 ? policies.join(\", \") : NONE,\n note: [entry.description, tags].filter(Boolean).join(\" \"),\n };\n}\n\nexport function contractCells(row: ContractRow): string[] {\n return [row.capabilityId, row.kind, row.effect, row.reach, row.confirm, row.policies];\n}\n\nfunction tally(values: readonly string[]): string {\n const counts = new Map<string, number>();\n for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1);\n return [...counts]\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n .map(([name, count]) => `${count} ${name}`)\n .join(\" · \");\n}\n\nfunction plural(count: number, noun: string, suffix = \"s\"): string {\n return `${count} ${noun}${count === 1 ? \"\" : suffix}`;\n}\n\nexport function contractHeading(manifest: CapabilityContractManifest): string {\n const count = manifest.capabilities.length;\n const groups = groupByDeclaration(manifest.capabilities).length;\n return `REPOSITORY CONTRACT · ${count} ${count === 1 ? \"capability\" : \"capabilities\"} · ${plural(groups, \"declaration\")}`;\n}\n\n/**\n * The answer, before the evidence for it. A reader who stops after this line\n * should still know how large the surface is and how much of it is gated.\n */\nexport function headline(manifest: CapabilityContractManifest): string[] {\n const capabilities = manifest.capabilities;\n const count = capabilities.length;\n const gated = capabilities.filter((entry) => entry.confirmation && entry.confirmation !== \"never\").length;\n const policed = capabilities.filter((entry) => (entry.policies ?? []).length > 0).length;\n // Along the ladder, not by frequency: \"34 low · 1 high · 1 medium\" reads as\n // a miscount rather than a distribution.\n const reach = ([\"low\", \"medium\", \"high\"] as const)\n .map((grade) => [grade, capabilities.filter((entry) => reachOf(entry.effect) === grade).length] as const)\n .filter(([, count]) => count > 0)\n .map(([grade, count]) => `${count} ${grade}`)\n .join(\" · \");\n return [\n `${count} ${count === 1 ? \"capability\" : \"capabilities\"} · ${plural(\n groupByDeclaration(capabilities).length,\n \"declaration\",\n )}${count > 0 ? ` · ${tally(capabilities.map((entry) => entry.kind))}` : \"\"}`,\n `reach ${reach || NONE} · declared gates: ${gated} confirmation · ${policed} policy`,\n ];\n}\n\n/**\n * What a compiled contract cannot tell you. The columns above are declarations\n * the graph proves are reachable — not a transcript of a run, and a policy's\n * verdict is not knowable until there is an actor and an input to judge.\n */\nexport const CONTRACT_CAVEAT = [\n \"Declarations, compiled from the production graph — what this code can expose,\",\n \"not what a mount exposed at runtime. CONFIRM and POLICIES are declared per\",\n \"capability; whether a policy admits, denies or hides one depends on the actor,\",\n \"input and context of a real invocation, which this command never performs.\",\n];\n\n/** Column widths shared by the plain and drawn renderers, so both align alike. */\nexport function contractColumns(capabilities: readonly CapabilityContractEntry[]): number[] {\n const rows = capabilities.map((entry) => contractCells(contractRow(entry)));\n return CONTRACT_HEADERS.map((header, index) =>\n Math.max(header.length, ...rows.map((cells) => cells[index]?.length ?? 0)),\n );\n}\n\n/** One table line, padded to the shared widths. The last cell is never padded. */\nexport function contractLine(cells: readonly string[], widths: readonly number[]): string {\n return cells\n .map((cell, index) => (index === cells.length - 1 ? cell : cell.padEnd(widths[index] ?? 0)))\n .join(\" \")\n .trimEnd();\n}\n\n/** Show the snapshot where the user would type it, not as an absolute path. */\nexport function displayPath(path: string, root?: string): string {\n if (!root) return path;\n const relativePath = relative(root, path);\n return !relativePath || relativePath.startsWith(\"..\") ? path : relativePath;\n}\n\n/**\n * `inspect` exists to show the inventory. The other commands lead with a\n * verdict and keep it out of the way — until `--detail` is asked for, because\n * the reason to ask a gate for detail is to read what it gated.\n */\nexport function showsContract(report: ContractReport, options: RenderOptions = {}): boolean {\n return report.command === \"inspect\" || options.detail === true;\n}\n\n/** Provenance. True, needed, and not what the reader came for — so it sits below. */\nexport function summaryFields(report: ContractReport, options: RenderOptions = {}): [string, string][] {\n const { manifest } = report;\n const fields: [string, string][] = [\n [\"Contract\", manifest.hash],\n [\"Compiler\", manifest.compilerVersion],\n [\"Completeness\", manifest.completeness.status],\n [\"Targets\", manifest.targets.join(\", \") || NONE],\n [\"Snapshot\", displayPath(report.snapshotPath, options.root)],\n ];\n if (report.integrity) fields.push([\"Integrity\", report.integrity.status]);\n return fields;\n}\n\nexport function humanReport(report: ContractReport, options: RenderOptions = {}): string {\n const fields = summaryFields(report, options);\n const label = Math.max(...fields.map(([name]) => name.length));\n const lines = [\n `AGENT SURFACE ${report.command.toUpperCase()} · ${report.status.toUpperCase()}`,\n \"\",\n ...headline(report.manifest),\n \"\",\n ...fields.map(([name, value]) => `${name.padEnd(label)} ${value}`),\n ];\n if (report.integrity) lines.push(\"\", ...section(\"SOURCE ↔ SNAPSHOT\", report.integrity.changes));\n if (report.pullRequest) {\n lines.push(\"\", ...section(`PR DRIFT vs ${report.pullRequest.base}`, report.pullRequest.changes));\n }\n if (showsContract(report, options)) {\n const widths = contractColumns(report.manifest.capabilities);\n lines.push(\"\", contractHeading(report.manifest), \"\", ` ${contractLine(CONTRACT_HEADERS, widths)}`);\n for (const group of groupByDeclaration(report.manifest.capabilities)) {\n lines.push(\"\", `${group.declarationId} (${group.entries.length})`);\n for (const entry of group.entries) {\n const row = contractRow(entry);\n lines.push(` ${contractLine(contractCells(row), widths)}`);\n if (options.detail && row.note) lines.push(` ${row.note}`);\n }\n }\n lines.push(\"\", ...CONTRACT_CAVEAT);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction markdownChanges(changes: readonly ContractChange[]): string {\n if (changes.length === 0) return \"No changes.\\n\";\n return [\n \"| Class | Change | Capability | Declaration | Field |\",\n \"|---|---|---|---|---|\",\n ...changes.map(\n (change) =>\n `| ${change.classification} | ${change.kind} | \\`${change.capabilityId}\\` | \\`${change.declarationId}\\` | \\`${change.field}\\` |`,\n ),\n ].join(\"\\n\");\n}\n\nexport function markdownReport(report: ContractReport, github = false): string {\n const lines = [\n `## Agent Surface ${report.command} — ${report.status}`,\n \"\",\n `- Contract: \\`${report.manifest.hash}\\``,\n `- Completeness: **${report.manifest.completeness.status}**`,\n `- Capabilities: **${report.manifest.capabilities.length}**`,\n `- Targets: ${report.manifest.targets.map((target) => `\\`${target}\\``).join(\", \") || \"—\"}`,\n ];\n if (report.integrity) {\n lines.push(\"\", `### Source ↔ snapshot — ${report.integrity.status}`, \"\", markdownChanges(report.integrity.changes));\n }\n if (report.pullRequest) {\n lines.push(\"\", `### PR drift vs \\`${report.pullRequest.base}\\``, \"\", markdownChanges(report.pullRequest.changes));\n }\n if (github && report.status === \"fail\") {\n lines.unshift(`::error title=Agent Surface contract drift::${report.integrity?.changes.length ?? 0} integrity change(s)`);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function renderReport(report: ContractReport, format: OutputFormat, options: RenderOptions = {}): string {\n if (format === \"json\") return canonicalJson(report, true);\n if (format === \"markdown\") return markdownReport(report);\n if (format === \"github\") return markdownReport(report, true);\n return humanReport(report, options);\n}\n"],"mappings":"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","names":["value","value","count"]}
|
package/dist/ink-4CUU77KD.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CONTRACT_CAVEAT,
|
|
3
|
-
CONTRACT_HEADERS,
|
|
4
|
-
contractCells,
|
|
5
|
-
contractColumns,
|
|
6
|
-
contractHeading,
|
|
7
|
-
contractLine,
|
|
8
|
-
contractRow,
|
|
9
|
-
groupByDeclaration,
|
|
10
|
-
headline,
|
|
11
|
-
sectionTitle,
|
|
12
|
-
showsContract,
|
|
13
|
-
summaryFields
|
|
14
|
-
} from "./chunk-KMAH2WU5.js";
|
|
15
|
-
|
|
16
|
-
// src/ink.tsx
|
|
17
|
-
import { Box, Text, render } from "ink";
|
|
18
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
-
var REACH_COLOR = { low: "green", medium: "yellow", high: "red" };
|
|
20
|
-
function changeColor(change) {
|
|
21
|
-
if (change.classification === "widening") return "yellow";
|
|
22
|
-
if (change.classification === "narrowing") return "cyan";
|
|
23
|
-
return "gray";
|
|
24
|
-
}
|
|
25
|
-
function pad(text, width) {
|
|
26
|
-
return text.padEnd(width);
|
|
27
|
-
}
|
|
28
|
-
function Summary({ report, options }) {
|
|
29
|
-
const fields = summaryFields(report, options);
|
|
30
|
-
const label = Math.max(...fields.map(([name]) => name.length));
|
|
31
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: fields.map(([name, value]) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
32
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: pad(name, label) }),
|
|
33
|
-
" ",
|
|
34
|
-
/* @__PURE__ */ jsx(Text, { color: name === "Integrity" && value !== "current" ? "yellow" : void 0, children: value })
|
|
35
|
-
] }, name)) });
|
|
36
|
-
}
|
|
37
|
-
function Changes({ title, changes }) {
|
|
38
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
39
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: sectionTitle(title, changes) }),
|
|
40
|
-
changes.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "no changes" }) : changes.map((change, index) => /* @__PURE__ */ jsxs(
|
|
41
|
-
Text,
|
|
42
|
-
{
|
|
43
|
-
color: changeColor(change),
|
|
44
|
-
children: [
|
|
45
|
-
change.kind === "added" ? "+" : change.kind === "removed" ? "-" : "~",
|
|
46
|
-
" ",
|
|
47
|
-
change.classification.padEnd(9),
|
|
48
|
-
" ",
|
|
49
|
-
change.capabilityId,
|
|
50
|
-
" \xB7 ",
|
|
51
|
-
change.field
|
|
52
|
-
]
|
|
53
|
-
},
|
|
54
|
-
`${change.capabilityId}\0${change.declarationId}\0${change.field}\0${index}`
|
|
55
|
-
))
|
|
56
|
-
] });
|
|
57
|
-
}
|
|
58
|
-
function Capability({
|
|
59
|
-
entry,
|
|
60
|
-
widths,
|
|
61
|
-
detail
|
|
62
|
-
}) {
|
|
63
|
-
const row = contractRow(entry);
|
|
64
|
-
const [id, kind, effect, reach, confirm, policies] = contractCells(row);
|
|
65
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
66
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
67
|
-
" ",
|
|
68
|
-
pad(id ?? "", widths[0] ?? 0),
|
|
69
|
-
" ",
|
|
70
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: pad(kind ?? "", widths[1] ?? 0) }),
|
|
71
|
-
" ",
|
|
72
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: pad(effect ?? "", widths[2] ?? 0) }),
|
|
73
|
-
" ",
|
|
74
|
-
/* @__PURE__ */ jsx(Text, { color: REACH_COLOR[row.reach], children: pad(reach ?? "", widths[3] ?? 0) }),
|
|
75
|
-
" ",
|
|
76
|
-
/* @__PURE__ */ jsx(Text, { color: row.confirm === "required" ? "magenta" : void 0, dimColor: row.confirm === "\u2014", children: pad(confirm ?? "", widths[4] ?? 0) }),
|
|
77
|
-
" ",
|
|
78
|
-
/* @__PURE__ */ jsx(Text, { color: "magenta", dimColor: row.policies === "\u2014", children: policies })
|
|
79
|
-
] }),
|
|
80
|
-
detail && row.note ? /* @__PURE__ */ jsx(Box, { paddingLeft: 6, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: row.note }) }) : null
|
|
81
|
-
] });
|
|
82
|
-
}
|
|
83
|
-
function App({ report, options }) {
|
|
84
|
-
const ok = report.status === "pass" || report.status === "written" || report.status === "view";
|
|
85
|
-
const widths = contractColumns(report.manifest.capabilities);
|
|
86
|
-
const [size, gates] = headline(report.manifest);
|
|
87
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
88
|
-
/* @__PURE__ */ jsxs(Text, { bold: true, color: ok ? "green" : "red", children: [
|
|
89
|
-
"AGENT SURFACE ",
|
|
90
|
-
report.command.toUpperCase(),
|
|
91
|
-
" \xB7 ",
|
|
92
|
-
report.status.toUpperCase()
|
|
93
|
-
] }),
|
|
94
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
95
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: size }),
|
|
96
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: gates })
|
|
97
|
-
] }),
|
|
98
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Summary, { report, options }) }),
|
|
99
|
-
report.integrity ? /* @__PURE__ */ jsx(Changes, { title: "SOURCE \u2194 SNAPSHOT", changes: report.integrity.changes }) : null,
|
|
100
|
-
report.pullRequest ? /* @__PURE__ */ jsx(Changes, { title: `PR DRIFT vs ${report.pullRequest.base}`, changes: report.pullRequest.changes }) : null,
|
|
101
|
-
showsContract(report, options) ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
102
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: contractHeading(report.manifest) }),
|
|
103
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${contractLine(CONTRACT_HEADERS, widths)}` }) }),
|
|
104
|
-
groupByDeclaration(report.manifest.capabilities).map((group) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
105
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
106
|
-
/* @__PURE__ */ jsx(Text, { color: "blue", children: group.declarationId }),
|
|
107
|
-
" ",
|
|
108
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
109
|
-
"(",
|
|
110
|
-
group.entries.length,
|
|
111
|
-
")"
|
|
112
|
-
] })
|
|
113
|
-
] }),
|
|
114
|
-
group.entries.map((entry) => /* @__PURE__ */ jsx(
|
|
115
|
-
Capability,
|
|
116
|
-
{
|
|
117
|
-
entry,
|
|
118
|
-
widths,
|
|
119
|
-
detail: options.detail === true
|
|
120
|
-
},
|
|
121
|
-
entry.capabilityId
|
|
122
|
-
))
|
|
123
|
-
] }, group.declarationId)),
|
|
124
|
-
/* @__PURE__ */ jsx(
|
|
125
|
-
Box,
|
|
126
|
-
{
|
|
127
|
-
flexDirection: "column",
|
|
128
|
-
alignSelf: "flex-start",
|
|
129
|
-
marginTop: 1,
|
|
130
|
-
borderStyle: "round",
|
|
131
|
-
borderColor: "gray",
|
|
132
|
-
paddingX: 1,
|
|
133
|
-
children: CONTRACT_CAVEAT.map((line) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, line))
|
|
134
|
-
}
|
|
135
|
-
)
|
|
136
|
-
] }) : null
|
|
137
|
-
] });
|
|
138
|
-
}
|
|
139
|
-
async function renderInk(report, options = {}) {
|
|
140
|
-
const instance = render(/* @__PURE__ */ jsx(App, { report, options }));
|
|
141
|
-
await instance.waitUntilExit();
|
|
142
|
-
}
|
|
143
|
-
export {
|
|
144
|
-
renderInk
|
|
145
|
-
};
|
|
146
|
-
//# sourceMappingURL=ink-4CUU77KD.js.map
|
package/dist/ink-4CUU77KD.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ink.tsx"],"sourcesContent":["import { Box, Text, render } from \"ink\";\nimport type { CapabilityContractEntry } from \"@agent-surface/core\";\nimport type { ContractChange } from \"./diff.js\";\nimport type { ContractReport, Reach, RenderOptions } from \"./report.js\";\nimport {\n CONTRACT_CAVEAT,\n CONTRACT_HEADERS,\n contractCells,\n contractColumns,\n contractHeading,\n contractLine,\n contractRow,\n groupByDeclaration,\n headline,\n sectionTitle,\n showsContract,\n summaryFields,\n} from \"./report.js\";\n\n/** Colour repeats the REACH word; it never carries the grade on its own. */\nconst REACH_COLOR: Record<Reach, string> = { low: \"green\", medium: \"yellow\", high: \"red\" };\n\nfunction changeColor(change: ContractChange): string {\n if (change.classification === \"widening\") return \"yellow\";\n if (change.classification === \"narrowing\") return \"cyan\";\n return \"gray\";\n}\n\nfunction pad(text: string, width: number): string {\n return text.padEnd(width);\n}\n\nfunction Summary({ report, options }: { report: ContractReport; options: RenderOptions }) {\n const fields = summaryFields(report, options);\n const label = Math.max(...fields.map(([name]) => name.length));\n return (\n <Box flexDirection=\"column\">\n {fields.map(([name, value]) => (\n <Text key={name}>\n <Text dimColor>{pad(name, label)}</Text>\n {\" \"}\n <Text color={name === \"Integrity\" && value !== \"current\" ? \"yellow\" : undefined}>{value}</Text>\n </Text>\n ))}\n </Box>\n );\n}\n\nfunction Changes({ title, changes }: { title: string; changes: ContractChange[] }) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>{sectionTitle(title, changes)}</Text>\n {changes.length === 0 ? (\n <Text dimColor>no changes</Text>\n ) : (\n changes.map((change, index) => (\n <Text\n key={`${change.capabilityId}\\0${change.declarationId}\\0${change.field}\\0${index}`}\n color={changeColor(change)}\n >\n {change.kind === \"added\" ? \"+\" : change.kind === \"removed\" ? \"-\" : \"~\"} {change.classification.padEnd(9)}{\" \"}\n {change.capabilityId} · {change.field}\n </Text>\n ))\n )}\n </Box>\n );\n}\n\nfunction Capability({\n entry,\n widths,\n detail,\n}: {\n entry: CapabilityContractEntry;\n widths: number[];\n detail: boolean;\n}) {\n const row = contractRow(entry);\n const [id, kind, effect, reach, confirm, policies] = contractCells(row);\n return (\n <Box flexDirection=\"column\">\n <Text>\n {\" \"}\n {pad(id ?? \"\", widths[0] ?? 0)}\n {\" \"}\n <Text dimColor>{pad(kind ?? \"\", widths[1] ?? 0)}</Text>\n {\" \"}\n <Text dimColor>{pad(effect ?? \"\", widths[2] ?? 0)}</Text>\n {\" \"}\n <Text color={REACH_COLOR[row.reach]}>{pad(reach ?? \"\", widths[3] ?? 0)}</Text>\n {\" \"}\n <Text color={row.confirm === \"required\" ? \"magenta\" : undefined} dimColor={row.confirm === \"—\"}>\n {pad(confirm ?? \"\", widths[4] ?? 0)}\n </Text>\n {\" \"}\n <Text color=\"magenta\" dimColor={row.policies === \"—\"}>\n {policies}\n </Text>\n </Text>\n {/* Padding rather than a prefix, so a wrapped description stays in its column. */}\n {detail && row.note ? (\n <Box paddingLeft={6}>\n <Text dimColor>{row.note}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction App({ report, options }: { report: ContractReport; options: RenderOptions }) {\n const ok = report.status === \"pass\" || report.status === \"written\" || report.status === \"view\";\n const widths = contractColumns(report.manifest.capabilities);\n const [size, gates] = headline(report.manifest);\n return (\n <Box flexDirection=\"column\">\n <Text bold color={ok ? \"green\" : \"red\"}>\n AGENT SURFACE {report.command.toUpperCase()} · {report.status.toUpperCase()}\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold color=\"cyan\">\n {size}\n </Text>\n <Text dimColor>{gates}</Text>\n </Box>\n <Box marginTop={1}>\n <Summary report={report} options={options} />\n </Box>\n {report.integrity ? <Changes title=\"SOURCE ↔ SNAPSHOT\" changes={report.integrity.changes} /> : null}\n {report.pullRequest ? (\n <Changes title={`PR DRIFT vs ${report.pullRequest.base}`} changes={report.pullRequest.changes} />\n ) : null}\n {showsContract(report, options) ? (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>{contractHeading(report.manifest)}</Text>\n <Box marginTop={1}>\n <Text dimColor>{` ${contractLine(CONTRACT_HEADERS, widths)}`}</Text>\n </Box>\n {groupByDeclaration(report.manifest.capabilities).map((group) => (\n <Box key={group.declarationId} flexDirection=\"column\" marginTop={1}>\n <Text>\n <Text color=\"blue\">{group.declarationId}</Text> <Text dimColor>({group.entries.length})</Text>\n </Text>\n {group.entries.map((entry) => (\n <Capability\n key={entry.capabilityId}\n entry={entry}\n widths={widths}\n detail={options.detail === true}\n />\n ))}\n </Box>\n ))}\n {/* flex-start, or the border stretches to the width of the terminal. */}\n <Box\n flexDirection=\"column\"\n alignSelf=\"flex-start\"\n marginTop={1}\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n >\n {CONTRACT_CAVEAT.map((line) => (\n <Text key={line} dimColor>\n {line}\n </Text>\n ))}\n </Box>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nexport async function renderInk(report: ContractReport, options: RenderOptions = {}): Promise<void> {\n const instance = render(<App report={report} options={options} />);\n await instance.waitUntilExit();\n}\n"],"mappings":"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","names":[]}
|