specky-sdd 3.7.1 → 3.7.3
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/.apm/agents/design-architect.agent.md +1 -1
- package/.apm/agents/implementer.agent.md +1 -1
- package/.apm/agents/quality-reviewer.agent.md +1 -1
- package/.apm/agents/release-engineer.agent.md +1 -1
- package/.apm/agents/requirements-engineer.agent.md +1 -1
- package/.apm/agents/research-analyst.agent.md +1 -1
- package/.apm/agents/sdd-clarify.agent.md +1 -1
- package/.apm/agents/sdd-init.agent.md +1 -1
- package/.apm/agents/spec-engineer.agent.md +1 -1
- package/.apm/agents/specky-onboarding.agent.md +1 -1
- package/.apm/agents/specky-orchestrator.agent.md +1 -1
- package/.apm/agents/task-planner.agent.md +1 -1
- package/.apm/agents/test-verifier.agent.md +1 -1
- package/.apm/prompts/specky-api.prompt.md +1 -1
- package/.apm/prompts/specky-brownfield.prompt.md +1 -1
- package/.apm/prompts/specky-check-drift.prompt.md +1 -1
- package/.apm/prompts/specky-clarify.prompt.md +1 -1
- package/.apm/prompts/specky-debug-hook.prompt.md +1 -1
- package/.apm/prompts/specky-deploy.prompt.md +1 -1
- package/.apm/prompts/specky-design.prompt.md +1 -1
- package/.apm/prompts/specky-from-figma.prompt.md +1 -1
- package/.apm/prompts/specky-from-meeting.prompt.md +1 -1
- package/.apm/prompts/specky-greenfield.prompt.md +1 -1
- package/.apm/prompts/specky-implement.prompt.md +1 -1
- package/.apm/prompts/specky-migration.prompt.md +1 -1
- package/.apm/prompts/specky-onboarding.prompt.md +1 -1
- package/.apm/prompts/specky-orchestrate.prompt.md +1 -1
- package/.apm/prompts/specky-pipeline-status.prompt.md +1 -1
- package/.apm/prompts/specky-release.prompt.md +1 -1
- package/.apm/prompts/specky-research.prompt.md +1 -1
- package/.apm/prompts/specky-reset-phase.prompt.md +1 -1
- package/.apm/prompts/specky-resolve-conflict.prompt.md +1 -1
- package/.apm/prompts/specky-specify.prompt.md +1 -1
- package/.apm/prompts/specky-tasks.prompt.md +1 -1
- package/.apm/prompts/specky-verify.prompt.md +1 -1
- package/CHANGELOG.md +47 -0
- package/README.md +4 -0
- package/apm-policy.yml +41 -0
- package/apm.lock.yaml +71 -0
- package/apm.yml +29 -2
- package/dist/cli/commands/apm.d.ts +2 -0
- package/dist/cli/commands/apm.d.ts.map +1 -0
- package/dist/cli/commands/apm.js +139 -0
- package/dist/cli/commands/apm.js.map +1 -0
- package/dist/cli/index.js +10 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/apm/lock.d.ts +23 -0
- package/dist/cli/lib/apm/lock.d.ts.map +1 -0
- package/dist/cli/lib/apm/lock.js +90 -0
- package/dist/cli/lib/apm/lock.js.map +1 -0
- package/dist/cli/lib/apm/manifest.d.ts +31 -0
- package/dist/cli/lib/apm/manifest.d.ts.map +1 -0
- package/dist/cli/lib/apm/manifest.js +65 -0
- package/dist/cli/lib/apm/manifest.js.map +1 -0
- package/dist/cli/lib/apm/policy.d.ts +23 -0
- package/dist/cli/lib/apm/policy.d.ts.map +1 -0
- package/dist/cli/lib/apm/policy.js +85 -0
- package/dist/cli/lib/apm/policy.js.map +1 -0
- package/dist/cli/lib/asset-copier.d.ts.map +1 -1
- package/dist/cli/lib/asset-copier.js +36 -20
- package/dist/cli/lib/asset-copier.js.map +1 -1
- package/dist/cli/lib/harness/compilers/claude.d.ts +10 -0
- package/dist/cli/lib/harness/compilers/claude.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/claude.js +29 -0
- package/dist/cli/lib/harness/compilers/claude.js.map +1 -0
- package/dist/cli/lib/harness/compilers/common.d.ts +14 -0
- package/dist/cli/lib/harness/compilers/common.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/common.js +43 -0
- package/dist/cli/lib/harness/compilers/common.js.map +1 -0
- package/dist/cli/lib/harness/compilers/copilot.d.ts +10 -0
- package/dist/cli/lib/harness/compilers/copilot.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/copilot.js +32 -0
- package/dist/cli/lib/harness/compilers/copilot.js.map +1 -0
- package/dist/cli/lib/harness/index.d.ts +12 -0
- package/dist/cli/lib/harness/index.d.ts.map +1 -0
- package/dist/cli/lib/harness/index.js +18 -0
- package/dist/cli/lib/harness/index.js.map +1 -0
- package/dist/cli/lib/harness/tool-map.d.ts +15 -0
- package/dist/cli/lib/harness/tool-map.d.ts.map +1 -0
- package/dist/cli/lib/harness/tool-map.js +92 -0
- package/dist/cli/lib/harness/tool-map.js.map +1 -0
- package/dist/cli/lib/harness/types.d.ts +42 -0
- package/dist/cli/lib/harness/types.d.ts.map +1 -0
- package/dist/cli/lib/harness/types.js +12 -0
- package/dist/cli/lib/harness/types.js.map +1 -0
- package/dist/cli/lib/paths.d.ts +1 -0
- package/dist/cli/lib/paths.d.ts.map +1 -1
- package/dist/cli/lib/paths.js +1 -0
- package/dist/cli/lib/paths.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/apm.ts — `specky apm <subcommand>` governance surface.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* validate Validate apm.yml against on-disk primitives + package.json.
|
|
6
|
+
* lock Write apm.lock.yaml with a sha256 for every primitive.
|
|
7
|
+
* verify-lock Recompute hashes and diff against apm.lock.yaml.
|
|
8
|
+
* policy Enforce apm-policy.yml (MCP allowlist, hooks, tool isolation).
|
|
9
|
+
* audit Run the primitive frontmatter audit.
|
|
10
|
+
* sbom Emit a CycloneDX SBOM of the packaged primitives.
|
|
11
|
+
*/
|
|
12
|
+
import { writeFileSync } from "node:fs";
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
14
|
+
import { resolve } from "node:path";
|
|
15
|
+
import { packageRoot } from "../lib/paths.js";
|
|
16
|
+
import { validateManifest, loadManifest } from "../lib/apm/manifest.js";
|
|
17
|
+
import { generateLock, serializeLock, lockPath, verifyLock, } from "../lib/apm/lock.js";
|
|
18
|
+
import { checkPolicy } from "../lib/apm/policy.js";
|
|
19
|
+
function print(result) {
|
|
20
|
+
for (const w of result.warnings)
|
|
21
|
+
console.warn(` ⚠️ ${w}`);
|
|
22
|
+
for (const e of result.errors)
|
|
23
|
+
console.error(` ❌ ${e}`);
|
|
24
|
+
}
|
|
25
|
+
function runValidate(pkgRoot) {
|
|
26
|
+
const result = validateManifest(pkgRoot);
|
|
27
|
+
print(result);
|
|
28
|
+
if (result.ok) {
|
|
29
|
+
const m = loadManifest(pkgRoot);
|
|
30
|
+
console.log(`✅ apm.yml valid — ${m.name}@${m.version}, targets: ${m.targets.join(", ")}`);
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
return 2;
|
|
34
|
+
}
|
|
35
|
+
function runLock(pkgRoot, dryRun) {
|
|
36
|
+
const lock = generateLock(pkgRoot);
|
|
37
|
+
const count = Object.keys(lock.primitives).length;
|
|
38
|
+
if (dryRun) {
|
|
39
|
+
console.log(`ℹ️ apm lock (dry-run): ${count} primitives would be hashed`);
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
writeFileSync(lockPath(pkgRoot), serializeLock(lock), "utf8");
|
|
43
|
+
console.log(`✅ Wrote apm.lock.yaml — ${count} primitives (${lock.package.name}@${lock.package.version})`);
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
function runVerifyLock(pkgRoot) {
|
|
47
|
+
const result = verifyLock(pkgRoot);
|
|
48
|
+
if (result.error) {
|
|
49
|
+
console.error(` ❌ ${result.error}`);
|
|
50
|
+
return 2;
|
|
51
|
+
}
|
|
52
|
+
if (result.ok) {
|
|
53
|
+
console.log("✅ apm.lock.yaml matches the primitive source");
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
for (const f of result.changed)
|
|
57
|
+
console.error(` ✏️ changed: ${f}`);
|
|
58
|
+
for (const f of result.missing)
|
|
59
|
+
console.error(` ➖ missing: ${f}`);
|
|
60
|
+
for (const f of result.extra)
|
|
61
|
+
console.error(` ➕ untracked: ${f}`);
|
|
62
|
+
console.error("❌ Lock verification failed — run `specky apm lock` to update");
|
|
63
|
+
return 2;
|
|
64
|
+
}
|
|
65
|
+
function runPolicy(pkgRoot) {
|
|
66
|
+
const result = checkPolicy(pkgRoot);
|
|
67
|
+
print(result);
|
|
68
|
+
if (result.ok) {
|
|
69
|
+
console.log("✅ apm-policy.yml checks passed");
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
return 2;
|
|
73
|
+
}
|
|
74
|
+
function runAudit(pkgRoot) {
|
|
75
|
+
const res = spawnSync(process.execPath, [resolve(pkgRoot, "scripts/audit-agent-frontmatter.mjs")], { stdio: "inherit", cwd: pkgRoot });
|
|
76
|
+
return res.status ?? 1;
|
|
77
|
+
}
|
|
78
|
+
function runSbom(pkgRoot) {
|
|
79
|
+
const lock = generateLock(pkgRoot);
|
|
80
|
+
const sbom = {
|
|
81
|
+
bomFormat: "CycloneDX",
|
|
82
|
+
specVersion: "1.5",
|
|
83
|
+
version: 1,
|
|
84
|
+
metadata: {
|
|
85
|
+
timestamp: new Date().toISOString(),
|
|
86
|
+
component: {
|
|
87
|
+
type: "application",
|
|
88
|
+
name: lock.package.name,
|
|
89
|
+
version: lock.package.version,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
components: Object.entries(lock.primitives).map(([path, hash]) => ({
|
|
93
|
+
type: "file",
|
|
94
|
+
name: path,
|
|
95
|
+
hashes: [{ alg: "SHA-256", content: hash.replace(/^sha256:/, "") }],
|
|
96
|
+
})),
|
|
97
|
+
};
|
|
98
|
+
console.log(JSON.stringify(sbom, null, 2));
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
export function apmCommand(argv) {
|
|
102
|
+
const pkgRoot = packageRoot();
|
|
103
|
+
const sub = argv[0];
|
|
104
|
+
const rest = argv.slice(1);
|
|
105
|
+
const dryRun = rest.includes("--dry-run");
|
|
106
|
+
switch (sub) {
|
|
107
|
+
case "validate":
|
|
108
|
+
return runValidate(pkgRoot);
|
|
109
|
+
case "lock":
|
|
110
|
+
return runLock(pkgRoot, dryRun);
|
|
111
|
+
case "verify-lock":
|
|
112
|
+
return runVerifyLock(pkgRoot);
|
|
113
|
+
case "policy":
|
|
114
|
+
// `specky apm policy` or `specky apm policy check`
|
|
115
|
+
return runPolicy(pkgRoot);
|
|
116
|
+
case "audit":
|
|
117
|
+
return runAudit(pkgRoot);
|
|
118
|
+
case "sbom":
|
|
119
|
+
return runSbom(pkgRoot);
|
|
120
|
+
case "help":
|
|
121
|
+
case undefined:
|
|
122
|
+
console.log([
|
|
123
|
+
"specky apm <subcommand>",
|
|
124
|
+
"",
|
|
125
|
+
" validate Validate apm.yml against primitives + package.json",
|
|
126
|
+
" lock Write apm.lock.yaml (sha256 per primitive)",
|
|
127
|
+
" verify-lock Diff the primitive source against apm.lock.yaml",
|
|
128
|
+
" policy Enforce apm-policy.yml (MCP, hooks, tool isolation)",
|
|
129
|
+
" audit Run the primitive frontmatter audit",
|
|
130
|
+
" sbom Emit a CycloneDX SBOM of packaged primitives",
|
|
131
|
+
].join("\n"));
|
|
132
|
+
return 0;
|
|
133
|
+
default:
|
|
134
|
+
console.error(`Unknown apm subcommand: ${sub}`);
|
|
135
|
+
console.error("Run `specky apm help` for usage.");
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=apm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apm.js","sourceRoot":"","sources":["../../../src/cli/commands/apm.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* specky status
|
|
9
9
|
* specky upgrade
|
|
10
10
|
* specky hooks <list|test|run NAME>
|
|
11
|
+
* specky apm <validate|lock|verify-lock|policy|audit|sbom>
|
|
11
12
|
* specky serve [--http] [--port=N] [--profile=enterprise]
|
|
12
13
|
* specky --version | -v
|
|
13
14
|
* specky --help | -h
|
|
@@ -65,6 +66,10 @@ Commands:
|
|
|
65
66
|
hooks <list|test|run NAME>
|
|
66
67
|
Manage installed hooks
|
|
67
68
|
|
|
69
|
+
apm <validate|lock|verify-lock|policy|audit|sbom>
|
|
70
|
+
Validate APM manifest, lock primitives, enforce
|
|
71
|
+
governance policy, and export primitive SBOM
|
|
72
|
+
|
|
68
73
|
serve Start the MCP server (stdio by default)
|
|
69
74
|
--http HTTP streaming transport
|
|
70
75
|
--port=<N> HTTP port (default 3200)
|
|
@@ -113,6 +118,10 @@ async function dispatch(command, rest) {
|
|
|
113
118
|
const action = (positional[0] ?? "list");
|
|
114
119
|
return runHooks({ action, name: positional[1] });
|
|
115
120
|
}
|
|
121
|
+
case "apm": {
|
|
122
|
+
const { apmCommand } = await import("./commands/apm.js");
|
|
123
|
+
return apmCommand(positional);
|
|
124
|
+
}
|
|
116
125
|
case "serve": {
|
|
117
126
|
const { runServe } = await import("./commands/serve.js");
|
|
118
127
|
const portFlag = flags["port"];
|
|
@@ -176,7 +185,7 @@ async function main() {
|
|
|
176
185
|
const isLegacyBin = binName === "specky-sdd" || binName.endsWith("specky-sdd");
|
|
177
186
|
// Legacy back-compat: `specky-sdd` with no subcommand OR with --http maps to serve
|
|
178
187
|
const knownCommands = new Set([
|
|
179
|
-
"install", "init", "doctor", "status", "upgrade", "hooks", "serve",
|
|
188
|
+
"install", "init", "doctor", "status", "upgrade", "hooks", "apm", "serve",
|
|
180
189
|
"help", "--help", "-h", "--version", "-v",
|
|
181
190
|
]);
|
|
182
191
|
const firstArg = args[0];
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const LOCK_SCHEMA_VERSION = 1;
|
|
2
|
+
export interface ApmLock {
|
|
3
|
+
schemaVersion: number;
|
|
4
|
+
package: {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
};
|
|
8
|
+
primitives: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
/** Compute the sorted `.apm` + governance manifest hash map for a package root. */
|
|
11
|
+
export declare function hashPrimitives(pkgRoot: string): Record<string, string>;
|
|
12
|
+
export declare function generateLock(pkgRoot: string): ApmLock;
|
|
13
|
+
export declare function serializeLock(lock: ApmLock): string;
|
|
14
|
+
export declare function lockPath(pkgRoot: string): string;
|
|
15
|
+
export interface VerifyResult {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
missing: string[];
|
|
18
|
+
changed: string[];
|
|
19
|
+
extra: string[];
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function verifyLock(pkgRoot: string): VerifyResult;
|
|
23
|
+
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/apm/lock.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,WAAW,OAAO;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAiBD,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWtE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CASrD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA8BxD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* apm/lock.ts — reproducible lockfile for the canonical primitive source.
|
|
3
|
+
*
|
|
4
|
+
* `apm lock` records a sha256 for every file under `.apm/`, plus apm.yml and
|
|
5
|
+
* apm-policy.yml, into apm.lock.yaml. `apm verify-lock` recomputes and diffs,
|
|
6
|
+
* so any drift between the committed primitives/governance files and the
|
|
7
|
+
* lockfile — a hand-edit, a partial upgrade, a corrupted install — is caught
|
|
8
|
+
* deterministically.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { readFileSync, readdirSync, statSync, existsSync } from "node:fs";
|
|
12
|
+
import { relative, resolve } from "node:path";
|
|
13
|
+
import { parse, stringify } from "yaml";
|
|
14
|
+
import { sourcePaths } from "../paths.js";
|
|
15
|
+
export const LOCK_SCHEMA_VERSION = 1;
|
|
16
|
+
function walkFiles(dir) {
|
|
17
|
+
if (!existsSync(dir))
|
|
18
|
+
return [];
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const name of readdirSync(dir)) {
|
|
21
|
+
const full = resolve(dir, name);
|
|
22
|
+
if (statSync(full).isDirectory())
|
|
23
|
+
out.push(...walkFiles(full));
|
|
24
|
+
else
|
|
25
|
+
out.push(full);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
function sha256(file) {
|
|
30
|
+
return `sha256:${createHash("sha256").update(readFileSync(file)).digest("hex")}`;
|
|
31
|
+
}
|
|
32
|
+
/** Compute the sorted `.apm` + governance manifest hash map for a package root. */
|
|
33
|
+
export function hashPrimitives(pkgRoot) {
|
|
34
|
+
const { apmDir, apmYml, apmPolicyYml } = sourcePaths(pkgRoot);
|
|
35
|
+
const files = [...walkFiles(apmDir)];
|
|
36
|
+
if (existsSync(apmYml))
|
|
37
|
+
files.push(apmYml);
|
|
38
|
+
if (existsSync(apmPolicyYml))
|
|
39
|
+
files.push(apmPolicyYml);
|
|
40
|
+
const map = {};
|
|
41
|
+
for (const file of files.sort((a, b) => a.localeCompare(b))) {
|
|
42
|
+
map[relative(pkgRoot, file)] = sha256(file);
|
|
43
|
+
}
|
|
44
|
+
return map;
|
|
45
|
+
}
|
|
46
|
+
export function generateLock(pkgRoot) {
|
|
47
|
+
const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf8"));
|
|
48
|
+
return {
|
|
49
|
+
schemaVersion: LOCK_SCHEMA_VERSION,
|
|
50
|
+
package: { name: pkg.name, version: pkg.version },
|
|
51
|
+
primitives: hashPrimitives(pkgRoot),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function serializeLock(lock) {
|
|
55
|
+
return `# Generated by \`specky apm lock\`. Do not edit by hand.\n${stringify(lock)}`;
|
|
56
|
+
}
|
|
57
|
+
export function lockPath(pkgRoot) {
|
|
58
|
+
return resolve(pkgRoot, "apm.lock.yaml");
|
|
59
|
+
}
|
|
60
|
+
export function verifyLock(pkgRoot) {
|
|
61
|
+
const path = lockPath(pkgRoot);
|
|
62
|
+
if (!existsSync(path)) {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
missing: [],
|
|
66
|
+
changed: [],
|
|
67
|
+
extra: [],
|
|
68
|
+
error: "apm.lock.yaml not found — run `specky apm lock`",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const locked = parse(readFileSync(path, "utf8"));
|
|
72
|
+
const current = hashPrimitives(pkgRoot);
|
|
73
|
+
const lockedPrimitives = locked.primitives ?? {};
|
|
74
|
+
const missing = [];
|
|
75
|
+
const changed = [];
|
|
76
|
+
for (const [file, hash] of Object.entries(lockedPrimitives)) {
|
|
77
|
+
if (!(file in current))
|
|
78
|
+
missing.push(file);
|
|
79
|
+
else if (current[file] !== hash)
|
|
80
|
+
changed.push(file);
|
|
81
|
+
}
|
|
82
|
+
const extra = Object.keys(current).filter((f) => !(f in lockedPrimitives));
|
|
83
|
+
return {
|
|
84
|
+
ok: missing.length === 0 && changed.length === 0 && extra.length === 0,
|
|
85
|
+
missing: missing.sort(),
|
|
86
|
+
changed: changed.sort(),
|
|
87
|
+
extra: extra.sort(),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../../src/cli/lib/apm/lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAQrC,SAAS,SAAS,CAAC,GAAW;IAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;;YAC1D,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IACxB,OAAO,UAAU,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACrF,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,OAAe;IAC1C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACrC,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,UAAU,CAAC,YAAY,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEvD,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAClB,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACpB,CAAC;IACvC,OAAO;QACH,aAAa,EAAE,mBAAmB;QAClC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;QACjD,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC;KACtC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAa;IACvC,OAAO,6DAA6D,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACpC,OAAO,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AAC7C,CAAC;AAUD,MAAM,UAAU,UAAU,CAAC,OAAe;IACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO;YACH,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,iDAAiD;SAC3D,CAAC;IACN,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAC;IAC5D,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IAEjD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACtC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAE3E,OAAO;QACH,EAAE,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACtE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;QACvB,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;QACvB,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;KACtB,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ApmMcpServer {
|
|
2
|
+
name: string;
|
|
3
|
+
transport?: string;
|
|
4
|
+
command?: string;
|
|
5
|
+
args?: string[];
|
|
6
|
+
tools?: string[];
|
|
7
|
+
registry?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ApmManifest {
|
|
10
|
+
name: string;
|
|
11
|
+
version: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
targets: string[];
|
|
14
|
+
primitives: Record<string, string>;
|
|
15
|
+
mcp?: {
|
|
16
|
+
servers?: ApmMcpServer[];
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function loadManifest(pkgRoot: string): ApmManifest;
|
|
20
|
+
export interface ValidationResult {
|
|
21
|
+
ok: boolean;
|
|
22
|
+
errors: string[];
|
|
23
|
+
warnings: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validate the APM manifest: required fields, version parity with
|
|
27
|
+
* package.json, declared primitive paths exist, targets are non-empty, and at
|
|
28
|
+
* least one MCP server is declared.
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateManifest(pkgRoot: string): ValidationResult;
|
|
31
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/apm/manifest.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,GAAG,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;CACtC;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAMzD;AAED,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAmDlE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* apm/manifest.ts — load and validate the APM manifest (apm.yml).
|
|
3
|
+
*
|
|
4
|
+
* The manifest is the enterprise contract for the package: it declares the
|
|
5
|
+
* canonical primitive source, the harness targets the package compiles to, and
|
|
6
|
+
* the MCP servers that back the primitives' tool ids. `apm validate` checks the
|
|
7
|
+
* manifest against the on-disk primitives and the npm manifest (package.json).
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
10
|
+
import { resolve } from "node:path";
|
|
11
|
+
import { parse } from "yaml";
|
|
12
|
+
import { sourcePaths } from "../paths.js";
|
|
13
|
+
export function loadManifest(pkgRoot) {
|
|
14
|
+
const { apmYml } = sourcePaths(pkgRoot);
|
|
15
|
+
if (!existsSync(apmYml)) {
|
|
16
|
+
throw new Error(`[specky] apm.yml not found at ${apmYml}`);
|
|
17
|
+
}
|
|
18
|
+
return parse(readFileSync(apmYml, "utf8"));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate the APM manifest: required fields, version parity with
|
|
22
|
+
* package.json, declared primitive paths exist, targets are non-empty, and at
|
|
23
|
+
* least one MCP server is declared.
|
|
24
|
+
*/
|
|
25
|
+
export function validateManifest(pkgRoot) {
|
|
26
|
+
const errors = [];
|
|
27
|
+
const warnings = [];
|
|
28
|
+
let manifest;
|
|
29
|
+
try {
|
|
30
|
+
manifest = loadManifest(pkgRoot);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
return { ok: false, errors: [err.message], warnings };
|
|
34
|
+
}
|
|
35
|
+
const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf8"));
|
|
36
|
+
if (!manifest.name)
|
|
37
|
+
errors.push("apm.yml: missing 'name'");
|
|
38
|
+
else if (manifest.name !== pkg.name) {
|
|
39
|
+
errors.push(`apm.yml name "${manifest.name}" != package.json name "${pkg.name}"`);
|
|
40
|
+
}
|
|
41
|
+
if (!manifest.version)
|
|
42
|
+
errors.push("apm.yml: missing 'version'");
|
|
43
|
+
else if (manifest.version !== pkg.version) {
|
|
44
|
+
errors.push(`apm.yml version "${manifest.version}" != package.json version "${pkg.version}"`);
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(manifest.targets) || manifest.targets.length === 0) {
|
|
47
|
+
errors.push("apm.yml: 'targets' must list at least one harness target");
|
|
48
|
+
}
|
|
49
|
+
if (!manifest.primitives || typeof manifest.primitives !== "object") {
|
|
50
|
+
errors.push("apm.yml: missing 'primitives' map");
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
for (const [kind, relPath] of Object.entries(manifest.primitives)) {
|
|
54
|
+
if (!existsSync(resolve(pkgRoot, relPath))) {
|
|
55
|
+
errors.push(`apm.yml: primitive '${kind}' path does not exist: ${relPath}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const servers = manifest.mcp?.servers ?? [];
|
|
60
|
+
if (servers.length === 0) {
|
|
61
|
+
warnings.push("apm.yml: no MCP servers declared under 'mcp.servers'");
|
|
62
|
+
}
|
|
63
|
+
return { ok: errors.length === 0, errors, warnings };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../src/cli/lib/apm/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ApmPolicy {
|
|
2
|
+
schemaVersion?: number;
|
|
3
|
+
allowedSources?: string[];
|
|
4
|
+
mcp?: {
|
|
5
|
+
allowTransitive?: boolean;
|
|
6
|
+
allowedServers?: string[];
|
|
7
|
+
};
|
|
8
|
+
hooks?: {
|
|
9
|
+
allowedEvents?: string[];
|
|
10
|
+
};
|
|
11
|
+
targets?: Record<string, {
|
|
12
|
+
forbidToolTokens?: string[];
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
export declare function policyPath(pkgRoot: string): string;
|
|
16
|
+
export declare function loadPolicy(pkgRoot: string): ApmPolicy;
|
|
17
|
+
export interface PolicyResult {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
errors: string[];
|
|
20
|
+
warnings: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function checkPolicy(pkgRoot: string): PolicyResult;
|
|
23
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/apm/policy.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,SAAS;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,GAAG,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC/D,KAAK,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7D;AASD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAIrD;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAgEzD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* apm/policy.ts — enforce the enterprise governance policy (apm-policy.yml).
|
|
3
|
+
*
|
|
4
|
+
* Checks that: declared MCP servers are allow-listed, hook manifests only
|
|
5
|
+
* register allowed events, and each harness target's compiled tool tokens stay
|
|
6
|
+
* isolated (no foreign harness tokens leak across targets).
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
|
9
|
+
import { resolve } from "node:path";
|
|
10
|
+
import { parse } from "yaml";
|
|
11
|
+
import { sourcePaths } from "../paths.js";
|
|
12
|
+
import { loadManifest } from "./manifest.js";
|
|
13
|
+
import { getCompiler } from "../harness/index.js";
|
|
14
|
+
const TARGET_ALIASES = {
|
|
15
|
+
"github-copilot": "copilot",
|
|
16
|
+
copilot: "copilot",
|
|
17
|
+
"claude-code": "claude",
|
|
18
|
+
claude: "claude",
|
|
19
|
+
};
|
|
20
|
+
export function policyPath(pkgRoot) {
|
|
21
|
+
return resolve(pkgRoot, "apm-policy.yml");
|
|
22
|
+
}
|
|
23
|
+
export function loadPolicy(pkgRoot) {
|
|
24
|
+
const path = policyPath(pkgRoot);
|
|
25
|
+
if (!existsSync(path))
|
|
26
|
+
return {};
|
|
27
|
+
return parse(readFileSync(path, "utf8")) ?? {};
|
|
28
|
+
}
|
|
29
|
+
function toolsLine(content) {
|
|
30
|
+
return content.split("\n").find((line) => line.startsWith("tools:")) ?? "";
|
|
31
|
+
}
|
|
32
|
+
export function checkPolicy(pkgRoot) {
|
|
33
|
+
const errors = [];
|
|
34
|
+
const warnings = [];
|
|
35
|
+
const policy = loadPolicy(pkgRoot);
|
|
36
|
+
if (!existsSync(policyPath(pkgRoot))) {
|
|
37
|
+
warnings.push("apm-policy.yml not found — governance checks are skipped");
|
|
38
|
+
return { ok: true, errors, warnings };
|
|
39
|
+
}
|
|
40
|
+
const { agentsDir, hooksManifest } = sourcePaths(pkgRoot);
|
|
41
|
+
// 1. MCP allowlist.
|
|
42
|
+
const allowedServers = policy.mcp?.allowedServers ?? [];
|
|
43
|
+
const manifest = loadManifest(pkgRoot);
|
|
44
|
+
for (const server of manifest.mcp?.servers ?? []) {
|
|
45
|
+
if (!allowedServers.includes(server.name)) {
|
|
46
|
+
errors.push(`MCP server "${server.name}" is not in policy allowedServers`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 2. Hook event allowlist.
|
|
50
|
+
const allowedEvents = policy.hooks?.allowedEvents;
|
|
51
|
+
if (allowedEvents && existsSync(hooksManifest)) {
|
|
52
|
+
const manifestJson = JSON.parse(readFileSync(hooksManifest, "utf8"));
|
|
53
|
+
for (const event of Object.keys(manifestJson)) {
|
|
54
|
+
if (!allowedEvents.includes(event)) {
|
|
55
|
+
errors.push(`Hook manifest registers disallowed event "${event}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// 3. Per-target tool-name isolation.
|
|
60
|
+
const agentFiles = existsSync(agentsDir)
|
|
61
|
+
? readdirSync(agentsDir).filter((f) => f.endsWith(".agent.md"))
|
|
62
|
+
: [];
|
|
63
|
+
for (const [targetName, rules] of Object.entries(policy.targets ?? {})) {
|
|
64
|
+
const target = TARGET_ALIASES[targetName];
|
|
65
|
+
if (!target) {
|
|
66
|
+
warnings.push(`policy targets: unknown target "${targetName}"`);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const forbidden = rules.forbidToolTokens ?? [];
|
|
70
|
+
if (forbidden.length === 0)
|
|
71
|
+
continue;
|
|
72
|
+
const compiler = getCompiler(target);
|
|
73
|
+
for (const file of agentFiles) {
|
|
74
|
+
const source = readFileSync(resolve(agentsDir, file), "utf8");
|
|
75
|
+
const line = toolsLine(compiler.compileAgent(source));
|
|
76
|
+
for (const token of forbidden) {
|
|
77
|
+
if (line.includes(token)) {
|
|
78
|
+
errors.push(`${targetName}: agent "${file}" compiles to a forbidden tool token "${token}"`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { ok: errors.length === 0, errors, warnings };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../../src/cli/lib/apm/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-copier.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/asset-copier.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,QAAQ,EAAqB,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"asset-copier.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/asset-copier.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,QAAQ,EAAqB,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAmFD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,GAChB,UAAU,CA2CZ;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,GAChB,UAAU,CAoDZ;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,WAAW,GAChB,MAAM,CAwBR;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAEjE;AAGD,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|