@jeger-ai/opengantry 3.3.0 → 3.5.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 +7 -2
- package/dist/cli/commands/arch.js +3 -3
- package/dist/cli/commands/arch.js.map +1 -1
- package/dist/cli/commands/audit-rigor.js +2 -2
- package/dist/cli/commands/audit-rigor.js.map +1 -1
- package/dist/cli/commands/contract.d.ts +28 -0
- package/dist/cli/commands/contract.d.ts.map +1 -0
- package/dist/cli/commands/contract.js +134 -0
- package/dist/cli/commands/contract.js.map +1 -0
- package/dist/cli/commands/interrogate.js +2 -2
- package/dist/cli/commands/interrogate.js.map +1 -1
- package/dist/cli/commands/status.js +2 -2
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/tmvc-guard.d.ts.map +1 -1
- package/dist/cli/commands/tmvc-guard.js +1 -0
- package/dist/cli/commands/tmvc-guard.js.map +1 -1
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +44 -24
- package/dist/cli/commands/verify.js.map +1 -1
- package/dist/cli/lib/cli-io.d.ts +2 -0
- package/dist/cli/lib/cli-io.d.ts.map +1 -1
- package/dist/cli/lib/cli-io.js +9 -1
- package/dist/cli/lib/cli-io.js.map +1 -1
- package/dist/cli/lib/command-boundary.js +2 -2
- package/dist/cli/lib/command-boundary.js.map +1 -1
- package/dist/cli/lib/command-reporter.d.ts +0 -2
- package/dist/cli/lib/command-reporter.d.ts.map +1 -1
- package/dist/cli/lib/command-reporter.js +0 -5
- package/dist/cli/lib/command-reporter.js.map +1 -1
- package/dist/cli/lib/contract/approve-prompt.d.ts +22 -0
- package/dist/cli/lib/contract/approve-prompt.d.ts.map +1 -0
- package/dist/cli/lib/contract/approve-prompt.js +71 -0
- package/dist/cli/lib/contract/approve-prompt.js.map +1 -0
- package/dist/cli/lib/contract/contract-hash.d.ts +19 -0
- package/dist/cli/lib/contract/contract-hash.d.ts.map +1 -0
- package/dist/cli/lib/contract/contract-hash.js +67 -0
- package/dist/cli/lib/contract/contract-hash.js.map +1 -0
- package/dist/cli/lib/contract/contract-scan.d.ts +27 -0
- package/dist/cli/lib/contract/contract-scan.d.ts.map +1 -0
- package/dist/cli/lib/contract/contract-scan.js +167 -0
- package/dist/cli/lib/contract/contract-scan.js.map +1 -0
- package/dist/cli/lib/contract/contract-types.d.ts +38 -0
- package/dist/cli/lib/contract/contract-types.d.ts.map +1 -0
- package/dist/cli/lib/contract/contract-types.js +11 -0
- package/dist/cli/lib/contract/contract-types.js.map +1 -0
- package/dist/cli/lib/contract/effective-scope.d.ts +21 -0
- package/dist/cli/lib/contract/effective-scope.d.ts.map +1 -0
- package/dist/cli/lib/contract/effective-scope.js +77 -0
- package/dist/cli/lib/contract/effective-scope.js.map +1 -0
- package/dist/cli/lib/contract/format.d.ts +20 -0
- package/dist/cli/lib/contract/format.d.ts.map +1 -0
- package/dist/cli/lib/contract/format.js +48 -0
- package/dist/cli/lib/contract/format.js.map +1 -0
- package/dist/cli/lib/contract/intent-path-tokens.d.ts +7 -0
- package/dist/cli/lib/contract/intent-path-tokens.d.ts.map +1 -0
- package/dist/cli/lib/contract/intent-path-tokens.js +30 -0
- package/dist/cli/lib/contract/intent-path-tokens.js.map +1 -0
- package/dist/cli/lib/contract/preflight-heuristic.d.ts +11 -0
- package/dist/cli/lib/contract/preflight-heuristic.d.ts.map +1 -0
- package/dist/cli/lib/contract/preflight-heuristic.js +38 -0
- package/dist/cli/lib/contract/preflight-heuristic.js.map +1 -0
- package/dist/cli/lib/contract/preflight-jev.d.ts +54 -0
- package/dist/cli/lib/contract/preflight-jev.d.ts.map +1 -0
- package/dist/cli/lib/contract/preflight-jev.js +247 -0
- package/dist/cli/lib/contract/preflight-jev.js.map +1 -0
- package/dist/cli/lib/contract/preflight-types.d.ts +19 -0
- package/dist/cli/lib/contract/preflight-types.d.ts.map +1 -0
- package/dist/cli/lib/contract/preflight-types.js +9 -0
- package/dist/cli/lib/contract/preflight-types.js.map +1 -0
- package/dist/cli/lib/contract/preflight.d.ts +16 -0
- package/dist/cli/lib/contract/preflight.d.ts.map +1 -0
- package/dist/cli/lib/contract/preflight.js +34 -0
- package/dist/cli/lib/contract/preflight.js.map +1 -0
- package/dist/cli/lib/contract/propose-gate.d.ts +21 -0
- package/dist/cli/lib/contract/propose-gate.d.ts.map +1 -0
- package/dist/cli/lib/contract/propose-gate.js +57 -0
- package/dist/cli/lib/contract/propose-gate.js.map +1 -0
- package/dist/cli/lib/contract/propose-imports.d.ts +26 -0
- package/dist/cli/lib/contract/propose-imports.d.ts.map +1 -0
- package/dist/cli/lib/contract/propose-imports.js +128 -0
- package/dist/cli/lib/contract/propose-imports.js.map +1 -0
- package/dist/cli/lib/contract/propose.d.ts +25 -0
- package/dist/cli/lib/contract/propose.d.ts.map +1 -0
- package/dist/cli/lib/contract/propose.js +79 -0
- package/dist/cli/lib/contract/propose.js.map +1 -0
- package/dist/cli/lib/contract/resolve-specifier.d.ts +34 -0
- package/dist/cli/lib/contract/resolve-specifier.d.ts.map +1 -0
- package/dist/cli/lib/contract/resolve-specifier.js +93 -0
- package/dist/cli/lib/contract/resolve-specifier.js.map +1 -0
- package/dist/cli/lib/draft-token.d.ts +5 -2
- package/dist/cli/lib/draft-token.d.ts.map +1 -1
- package/dist/cli/lib/draft-token.js +18 -3
- package/dist/cli/lib/draft-token.js.map +1 -1
- package/dist/cli/lib/errors.d.ts +2 -0
- package/dist/cli/lib/errors.d.ts.map +1 -1
- package/dist/cli/lib/errors.js +15 -2
- package/dist/cli/lib/errors.js.map +1 -1
- package/dist/cli/lib/git.d.ts +6 -0
- package/dist/cli/lib/git.d.ts.map +1 -1
- package/dist/cli/lib/git.js +10 -2
- package/dist/cli/lib/git.js.map +1 -1
- package/dist/cli/lib/gxt-error-codes.d.ts +5 -0
- package/dist/cli/lib/gxt-error-codes.d.ts.map +1 -1
- package/dist/cli/lib/gxt-error-codes.js +6 -0
- package/dist/cli/lib/gxt-error-codes.js.map +1 -1
- package/dist/cli/lib/import-scanner.d.ts +13 -3
- package/dist/cli/lib/import-scanner.d.ts.map +1 -1
- package/dist/cli/lib/import-scanner.js +185 -23
- package/dist/cli/lib/import-scanner.js.map +1 -1
- package/dist/cli/lib/interrogate/gaps.d.ts +2 -0
- package/dist/cli/lib/interrogate/gaps.d.ts.map +1 -1
- package/dist/cli/lib/interrogate/gaps.js +3 -4
- package/dist/cli/lib/interrogate/gaps.js.map +1 -1
- package/dist/cli/lib/interrogate/run.d.ts +1 -0
- package/dist/cli/lib/interrogate/run.d.ts.map +1 -1
- package/dist/cli/lib/interrogate/run.js +1 -0
- package/dist/cli/lib/interrogate/run.js.map +1 -1
- package/dist/cli/lib/legislate-from-intent.d.ts +9 -0
- package/dist/cli/lib/legislate-from-intent.d.ts.map +1 -0
- package/dist/cli/lib/legislate-from-intent.js +59 -0
- package/dist/cli/lib/legislate-from-intent.js.map +1 -0
- package/dist/cli/lib/legislate.d.ts +3 -1
- package/dist/cli/lib/legislate.d.ts.map +1 -1
- package/dist/cli/lib/legislate.js +24 -0
- package/dist/cli/lib/legislate.js.map +1 -1
- package/dist/cli/lib/mcp-draft-legislation.d.ts.map +1 -1
- package/dist/cli/lib/mcp-draft-legislation.js +28 -10
- package/dist/cli/lib/mcp-draft-legislation.js.map +1 -1
- package/dist/cli/lib/mcp-execute-legislation.d.ts.map +1 -1
- package/dist/cli/lib/mcp-execute-legislation.js +1 -0
- package/dist/cli/lib/mcp-execute-legislation.js.map +1 -1
- package/dist/cli/lib/mcp-governance-shared.d.ts +2 -1
- package/dist/cli/lib/mcp-governance-shared.d.ts.map +1 -1
- package/dist/cli/lib/mcp-governance-shared.js.map +1 -1
- package/dist/cli/lib/mcp-preflight-contract.d.ts +19 -0
- package/dist/cli/lib/mcp-preflight-contract.d.ts.map +1 -0
- package/dist/cli/lib/mcp-preflight-contract.js +31 -0
- package/dist/cli/lib/mcp-preflight-contract.js.map +1 -0
- package/dist/cli/lib/mcp-propose-contract.d.ts +22 -0
- package/dist/cli/lib/mcp-propose-contract.d.ts.map +1 -0
- package/dist/cli/lib/mcp-propose-contract.js +51 -0
- package/dist/cli/lib/mcp-propose-contract.js.map +1 -0
- package/dist/cli/lib/mcp-tools-register.d.ts.map +1 -1
- package/dist/cli/lib/mcp-tools-register.js +29 -0
- package/dist/cli/lib/mcp-tools-register.js.map +1 -1
- package/dist/cli/lib/missions/formatter.d.ts.map +1 -1
- package/dist/cli/lib/missions/formatter.js +2 -0
- package/dist/cli/lib/missions/formatter.js.map +1 -1
- package/dist/cli/lib/missions/parser.d.ts.map +1 -1
- package/dist/cli/lib/missions/parser.js +14 -0
- package/dist/cli/lib/missions/parser.js.map +1 -1
- package/dist/cli/lib/output-context.d.ts +7 -2
- package/dist/cli/lib/output-context.d.ts.map +1 -1
- package/dist/cli/lib/output-context.js +17 -9
- package/dist/cli/lib/output-context.js.map +1 -1
- package/dist/cli/lib/runtime-env.d.ts +3 -0
- package/dist/cli/lib/runtime-env.d.ts.map +1 -1
- package/dist/cli/lib/runtime-env.js +12 -2
- package/dist/cli/lib/runtime-env.js.map +1 -1
- package/dist/cli/lib/runtime-exec.d.ts +5 -1
- package/dist/cli/lib/runtime-exec.d.ts.map +1 -1
- package/dist/cli/lib/runtime-exec.js +18 -1
- package/dist/cli/lib/runtime-exec.js.map +1 -1
- package/dist/cli/lib/sarif-uri.d.ts +3 -0
- package/dist/cli/lib/sarif-uri.d.ts.map +1 -0
- package/dist/cli/lib/sarif-uri.js +15 -0
- package/dist/cli/lib/sarif-uri.js.map +1 -0
- package/dist/cli/lib/staged-tmvc-guard.d.ts +3 -0
- package/dist/cli/lib/staged-tmvc-guard.d.ts.map +1 -1
- package/dist/cli/lib/staged-tmvc-guard.js +4 -2
- package/dist/cli/lib/staged-tmvc-guard.js.map +1 -1
- package/dist/cli/lib/types.d.ts +7 -0
- package/dist/cli/lib/types.d.ts.map +1 -1
- package/dist/cli/lib/types.js.map +1 -1
- package/dist/cli/lib/verify-contract.d.ts +22 -0
- package/dist/cli/lib/verify-contract.d.ts.map +1 -0
- package/dist/cli/lib/verify-contract.js +110 -0
- package/dist/cli/lib/verify-contract.js.map +1 -0
- package/dist/cli/lib/verify-engine.d.ts.map +1 -1
- package/dist/cli/lib/verify-engine.js +6 -0
- package/dist/cli/lib/verify-engine.js.map +1 -1
- package/dist/cli/lib/verify-export.d.ts +19 -3
- package/dist/cli/lib/verify-export.d.ts.map +1 -1
- package/dist/cli/lib/verify-export.js +47 -24
- package/dist/cli/lib/verify-export.js.map +1 -1
- package/dist/cli/lib/verify-failure-normalize.d.ts.map +1 -1
- package/dist/cli/lib/verify-failure-normalize.js +10 -0
- package/dist/cli/lib/verify-failure-normalize.js.map +1 -1
- package/dist/cli/lib/verify-failure.d.ts +7 -2
- package/dist/cli/lib/verify-failure.d.ts.map +1 -1
- package/dist/cli/lib/verify-finding.d.ts +1 -1
- package/dist/cli/lib/verify-finding.d.ts.map +1 -1
- package/dist/cli/lib/verify-finding.js.map +1 -1
- package/dist/cli/lib/verify-hints.d.ts.map +1 -1
- package/dist/cli/lib/verify-hints.js +13 -0
- package/dist/cli/lib/verify-hints.js.map +1 -1
- package/dist/cli/lib/verify-interrogation.d.ts +2 -0
- package/dist/cli/lib/verify-interrogation.d.ts.map +1 -1
- package/dist/cli/lib/verify-interrogation.js +2 -2
- package/dist/cli/lib/verify-interrogation.js.map +1 -1
- package/dist/cli/lib/verify-payload.d.ts.map +1 -1
- package/dist/cli/lib/verify-payload.js +1 -0
- package/dist/cli/lib/verify-payload.js.map +1 -1
- package/dist/cli/lib/verify-phase-clock.d.ts +1 -1
- package/dist/cli/lib/verify-phase-clock.d.ts.map +1 -1
- package/dist/cli/lib/verify-phase-clock.js +1 -0
- package/dist/cli/lib/verify-phase-clock.js.map +1 -1
- package/dist/cli/lib/verify-presenters.d.ts +6 -2
- package/dist/cli/lib/verify-presenters.d.ts.map +1 -1
- package/dist/cli/lib/verify-presenters.js +34 -12
- package/dist/cli/lib/verify-presenters.js.map +1 -1
- package/dist/cli/lib/version.gen.d.ts +1 -1
- package/dist/cli/lib/version.gen.js +1 -1
- package/dist/cli/program-audience-hook.d.ts +4 -0
- package/dist/cli/program-audience-hook.d.ts.map +1 -0
- package/dist/cli/program-audience-hook.js +85 -0
- package/dist/cli/program-audience-hook.js.map +1 -0
- package/dist/cli/program-mission.d.ts.map +1 -1
- package/dist/cli/program-mission.js +53 -0
- package/dist/cli/program-mission.js.map +1 -1
- package/dist/cli/program-workflow.d.ts +4 -1
- package/dist/cli/program-workflow.d.ts.map +1 -1
- package/dist/cli/program-workflow.js +27 -6
- package/dist/cli/program-workflow.js.map +1 -1
- package/dist/cli/program.js +1 -1
- package/dist/cli/program.js.map +1 -1
- package/package.json +1 -1
- package/templates/.cursor/mcp.json +1 -2
- package/templates/.cursor/rules/opengantry-gxt-substrate.mdc +1 -1
- package/templates/.gitagent/foreman/SUBSTRATE.version.json +1 -1
- package/templates/.gitagent/planner/MISSION-ARCHITECT.md +28 -5
- package/templates/.gitagent/planner/MISSION.schema.yaml +52 -0
- package/templates/.gitagent/planner/RULES.md +55 -36
- package/templates/.githooks/pre-commit +12 -0
- package/templates/integrations/asset-catalog.json +1 -0
- package/templates/integrations/compatibility.json +1 -1
- package/templates/integrations/recipes/cursor.md +1 -1
- package/templates/scripts/mcp-launcher.sh +11 -0
- package/templates/scripts/validate-mcp-dogfood.mjs +7 -2
- package/dist/cli/lib/program-audience-hook.d.ts +0 -4
- package/dist/cli/lib/program-audience-hook.d.ts.map +0 -1
- package/dist/cli/lib/program-audience-hook.js +0 -35
- package/dist/cli/lib/program-audience-hook.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-reporter.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/command-reporter.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"command-reporter.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/command-reporter.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;gBAElC,OAAO,GAAE,sBAA2B;IAKhD,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,eAAe;IAU1G,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK/B,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKhC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/B,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IA4CxE,uBAAuB,CAAC,YAAY,EAAE,yBAAyB,GAAG,IAAI;IAatE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,kBAAkB,EAAE,GAAG,IAAI;CAiBpE"}
|
|
@@ -38,11 +38,6 @@ export class CommandReporter {
|
|
|
38
38
|
return;
|
|
39
39
|
logFixHint(hint);
|
|
40
40
|
}
|
|
41
|
-
emitJsonPayload(payload) {
|
|
42
|
-
if (this.channel === "silent")
|
|
43
|
-
return;
|
|
44
|
-
logInfo(JSON.stringify(payload, null, 2));
|
|
45
|
-
}
|
|
46
41
|
emitVerifySuccess(result, _missionArg) {
|
|
47
42
|
if (this.channel === "silent" || this.channel === "json")
|
|
48
43
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-reporter.js","sourceRoot":"","sources":["../../../src/cli/lib/command-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"command-reporter.js","sourceRoot":"","sources":["../../../src/cli/lib/command-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MissionContract } from "./contract-types.js";
|
|
2
|
+
import type { ProposedGate } from "./propose-gate.js";
|
|
3
|
+
export type ContractApproval = {
|
|
4
|
+
action: "approve";
|
|
5
|
+
contract: MissionContract;
|
|
6
|
+
} | {
|
|
7
|
+
action: "quit";
|
|
8
|
+
};
|
|
9
|
+
export interface ApproveContractInput {
|
|
10
|
+
contract: MissionContract;
|
|
11
|
+
gate?: ProposedGate;
|
|
12
|
+
rationale?: string[];
|
|
13
|
+
yes?: boolean;
|
|
14
|
+
stdin?: NodeJS.ReadStream;
|
|
15
|
+
stdout?: NodeJS.WriteStream;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* TTY [a]pprove / [e]dit in $EDITOR / [q]uit. `--yes` skips the prompt. Non-TTY without `--yes`
|
|
19
|
+
* exits 2 — CI must pass `--yes` or `--contract-file`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function approveContractPrompt(input: ApproveContractInput): Promise<ContractApproval>;
|
|
22
|
+
//# sourceMappingURL=approve-prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approve-prompt.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/contract/approve-prompt.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;CAC7B;AAyBD;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsClG"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import readline from "node:readline/promises";
|
|
6
|
+
import YAML from "yaml";
|
|
7
|
+
import { GantryUserError } from "../errors.js";
|
|
8
|
+
import { formatContractBlock } from "./format.js";
|
|
9
|
+
import { normalizeContract, parseContractYaml } from "./contract-hash.js";
|
|
10
|
+
function parseEditedContract(body) {
|
|
11
|
+
return parseContractYaml(body);
|
|
12
|
+
}
|
|
13
|
+
function editInEditor(contract) {
|
|
14
|
+
const editor = process.env.VISUAL?.trim() || process.env.EDITOR?.trim() || "vi";
|
|
15
|
+
const tmp = path.join(os.tmpdir(), `gantry-contract-${process.pid}.yaml`);
|
|
16
|
+
fs.writeFileSync(tmp, YAML.stringify({ contract }), "utf8");
|
|
17
|
+
try {
|
|
18
|
+
const r = spawnSync(editor, [tmp], { stdio: "inherit" });
|
|
19
|
+
if (r.status !== 0) {
|
|
20
|
+
throw new GantryUserError("INVALID_ARGUMENT", `editor ${editor} exited ${String(r.status ?? "null")}`, undefined, 2);
|
|
21
|
+
}
|
|
22
|
+
return parseEditedContract(fs.readFileSync(tmp, "utf8"));
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
try {
|
|
26
|
+
fs.unlinkSync(tmp);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
/* tmp cleanup is best-effort */
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* TTY [a]pprove / [e]dit in $EDITOR / [q]uit. `--yes` skips the prompt. Non-TTY without `--yes`
|
|
35
|
+
* exits 2 — CI must pass `--yes` or `--contract-file`.
|
|
36
|
+
*/
|
|
37
|
+
export async function approveContractPrompt(input) {
|
|
38
|
+
if (input.yes === true)
|
|
39
|
+
return { action: "approve", contract: normalizeContract(input.contract) };
|
|
40
|
+
const stdin = input.stdin ?? process.stdin;
|
|
41
|
+
const stdout = input.stdout ?? process.stdout;
|
|
42
|
+
if (!stdin.isTTY || !stdout.isTTY) {
|
|
43
|
+
throw new GantryUserError("INVALID_ARGUMENT", "gantry legislate --from-intent requires a TTY, or pass --yes / --contract-file", "Re-run in an interactive terminal, or gantry legislate --from-intent --yes …", 2);
|
|
44
|
+
}
|
|
45
|
+
let current = normalizeContract(input.contract);
|
|
46
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
47
|
+
try {
|
|
48
|
+
for (;;) {
|
|
49
|
+
stdout.write(`${formatContractBlock(current, input.gate)}\n`);
|
|
50
|
+
if (input.rationale && input.rationale.length > 0) {
|
|
51
|
+
stdout.write(`Rationale:\n${input.rationale.map((r) => ` - ${r}`).join("\n")}\n`);
|
|
52
|
+
}
|
|
53
|
+
const answer = (await rl.question("[a]pprove / [e]dit in $EDITOR / [q]uit: ")).trim().toLowerCase();
|
|
54
|
+
if (answer === "a" || answer === "approve" || answer === "yes" || answer === "y") {
|
|
55
|
+
return { action: "approve", contract: current };
|
|
56
|
+
}
|
|
57
|
+
if (answer === "q" || answer === "quit" || answer === "n" || answer === "no") {
|
|
58
|
+
return { action: "quit" };
|
|
59
|
+
}
|
|
60
|
+
if (answer === "e" || answer === "edit") {
|
|
61
|
+
current = editInEditor(current);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
stdout.write("Enter a, e, or q.\n");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
rl.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=approve-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approve-prompt.js","sourceRoot":"","sources":["../../../../src/cli/lib/contract/approve-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type MissionContract } from "./contract-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* POSIX separators, no leading `./`, collapsed slashes. Directory-like segments get a single
|
|
4
|
+
* trailing `/` so `src/ui` and `src/ui/` hash alike; last-segment file names (contain `.`) do not.
|
|
5
|
+
*/
|
|
6
|
+
export declare function normalizeContractPath(raw: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Canonical contract form: path lists normalized + sorted + deduped, import lists trimmed +
|
|
9
|
+
* sorted + deduped, empty lists and false booleans omitted. This is the only form written to
|
|
10
|
+
* mission YAML and the only form hashed, so key or array order can never produce a false
|
|
11
|
+
* GXT_CONTRACT_TAMPERED.
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeContract(contract: MissionContract): MissionContract;
|
|
14
|
+
export declare function contractSha256(contract: MissionContract): string;
|
|
15
|
+
/** True when the contract has no effective constraint at all. */
|
|
16
|
+
export declare function isEmptyContract(contract: MissionContract): boolean;
|
|
17
|
+
/** Accept a bare contract object or `{ contract: … }` YAML document. */
|
|
18
|
+
export declare function parseContractYaml(body: string): MissionContract;
|
|
19
|
+
//# sourceMappingURL=contract-hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-hash.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/contract/contract-hash.ts"],"names":[],"mappings":"AAIA,OAAO,EAA8C,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEvG;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQzD;AAUD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,eAAe,CAa5E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAEhE;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAElE;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAO/D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import YAML from "yaml";
|
|
3
|
+
import { canonicalJson } from "../canonical-json.js";
|
|
4
|
+
import { GantryUserError } from "../errors.js";
|
|
5
|
+
import { CONTRACT_ARRAY_KEYS, CONTRACT_BOOLEAN_KEYS } from "./contract-types.js";
|
|
6
|
+
/**
|
|
7
|
+
* POSIX separators, no leading `./`, collapsed slashes. Directory-like segments get a single
|
|
8
|
+
* trailing `/` so `src/ui` and `src/ui/` hash alike; last-segment file names (contain `.`) do not.
|
|
9
|
+
*/
|
|
10
|
+
export function normalizeContractPath(raw) {
|
|
11
|
+
let p = raw.trim().replace(/\\/g, "/").replace(/\/{2,}/g, "/");
|
|
12
|
+
while (p.startsWith("./"))
|
|
13
|
+
p = p.slice(2);
|
|
14
|
+
if (p.length > 1)
|
|
15
|
+
p = p.replace(/\/+$/, "");
|
|
16
|
+
if (p.length === 0)
|
|
17
|
+
return p;
|
|
18
|
+
const last = p.split("/").pop() ?? p;
|
|
19
|
+
const looksLikeFile = last.includes(".") && last !== "." && last !== "..";
|
|
20
|
+
return looksLikeFile || p.endsWith("/") ? p : `${p}/`;
|
|
21
|
+
}
|
|
22
|
+
function normalizeSpecifier(raw) {
|
|
23
|
+
return raw.trim();
|
|
24
|
+
}
|
|
25
|
+
function sortedUnique(values) {
|
|
26
|
+
return [...new Set(values.filter((v) => v.length > 0))].sort();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Canonical contract form: path lists normalized + sorted + deduped, import lists trimmed +
|
|
30
|
+
* sorted + deduped, empty lists and false booleans omitted. This is the only form written to
|
|
31
|
+
* mission YAML and the only form hashed, so key or array order can never produce a false
|
|
32
|
+
* GXT_CONTRACT_TAMPERED.
|
|
33
|
+
*/
|
|
34
|
+
export function normalizeContract(contract) {
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const key of CONTRACT_ARRAY_KEYS) {
|
|
37
|
+
const raw = contract[key];
|
|
38
|
+
if (!Array.isArray(raw) || raw.length === 0)
|
|
39
|
+
continue;
|
|
40
|
+
const isPathList = key === "tmvc_roots" || key === "forbidden_zones";
|
|
41
|
+
const values = sortedUnique(raw.map((v) => (isPathList ? normalizeContractPath(v) : normalizeSpecifier(v))));
|
|
42
|
+
if (values.length > 0)
|
|
43
|
+
out[key] = values;
|
|
44
|
+
}
|
|
45
|
+
for (const key of CONTRACT_BOOLEAN_KEYS) {
|
|
46
|
+
if (contract[key] === true)
|
|
47
|
+
out[key] = true;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
export function contractSha256(contract) {
|
|
52
|
+
return crypto.createHash("sha256").update(canonicalJson(normalizeContract(contract)), "utf8").digest("hex");
|
|
53
|
+
}
|
|
54
|
+
/** True when the contract has no effective constraint at all. */
|
|
55
|
+
export function isEmptyContract(contract) {
|
|
56
|
+
return Object.keys(normalizeContract(contract)).length === 0;
|
|
57
|
+
}
|
|
58
|
+
/** Accept a bare contract object or `{ contract: … }` YAML document. */
|
|
59
|
+
export function parseContractYaml(body) {
|
|
60
|
+
const doc = YAML.parse(body);
|
|
61
|
+
if (!doc || typeof doc !== "object") {
|
|
62
|
+
throw new GantryUserError("INVALID_ARGUMENT", "contract YAML is not an object", undefined, 2);
|
|
63
|
+
}
|
|
64
|
+
const block = "contract" in doc && doc.contract ? doc.contract : doc;
|
|
65
|
+
return normalizeContract(block);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=contract-hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-hash.js","sourceRoot":"","sources":["../../../../src/cli/lib/contract/contract-hash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type GxtErrorCode } from "../gxt-error-codes.js";
|
|
2
|
+
import type { ContractImportViolation, ContractViolationKind, EffectiveScope } from "./contract-types.js";
|
|
3
|
+
import { type TsconfigPaths } from "./resolve-specifier.js";
|
|
4
|
+
export declare function isScannableSource(fileRel: string): boolean;
|
|
5
|
+
/** Repo-relative source files under the effective TMVC roots (sorted, deduped). */
|
|
6
|
+
export declare function listSourcesUnderRoots(repoRoot: string, roots: readonly string[]): string[];
|
|
7
|
+
/**
|
|
8
|
+
* Dirty sources: `git diff --name-only HEAD` ∪ untracked. On an unborn branch (no HEAD) the
|
|
9
|
+
* index (`ls-files --cached`) stands in for the diff. Every argv ends with `--` so a path that
|
|
10
|
+
* looks like a flag is never parsed as one. Missing/deleted paths are dropped.
|
|
11
|
+
*/
|
|
12
|
+
export declare function listChangedSourceFiles(repoRoot: string): string[];
|
|
13
|
+
export declare function contractViolationCode(kind: ContractViolationKind): GxtErrorCode;
|
|
14
|
+
/** Scan a single source file's import sites against the effective scope. */
|
|
15
|
+
export declare function scanFileImports(repoRoot: string, fileRel: string, scope: EffectiveScope, ts?: TsconfigPaths | null): ContractImportViolation[];
|
|
16
|
+
export interface ScanContractImportsOptions {
|
|
17
|
+
/** Explicit repo-relative files; defaults to every source file under the effective TMVC roots. */
|
|
18
|
+
files?: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Import-site scan for the effective cage: banned / unlisted bare specifiers, non-literal dynamic
|
|
22
|
+
* specifiers, and relative or alias imports resolving into forbidden zones (or outside TMVC when
|
|
23
|
+
* `strict_relative_imports`). Deterministic ordering by file, line, column.
|
|
24
|
+
*/
|
|
25
|
+
export declare function scanContractImports(repoRoot: string, scope: EffectiveScope, options?: ScanContractImportsOptions): ContractImportViolation[];
|
|
26
|
+
export declare function formatContractViolation(v: ContractImportViolation): string;
|
|
27
|
+
//# sourceMappingURL=contract-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-scan.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/contract/contract-scan.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1G,OAAO,EAAwC,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAKlG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAG1D;AAqBD,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAI1F;AASD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CASjE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,GAAG,YAAY,CAe/E;AAgED,4EAA4E;AAC5E,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,cAAc,EACrB,EAAE,GAAE,aAAa,GAAG,IAAkC,GACrD,uBAAuB,EAAE,CAU3B;AAED,MAAM,WAAW,0BAA0B;IACzC,kGAAkG;IAClG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,0BAA+B,GACvC,uBAAuB,EAAE,CAU3B;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAE1E"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { importMatchesBan } from "../ast-discovery.js";
|
|
4
|
+
import { toPosixRel } from "../cli-io.js";
|
|
5
|
+
import { gitRunOk } from "../git.js";
|
|
6
|
+
import { GXT_ERROR } from "../gxt-error-codes.js";
|
|
7
|
+
import { extractImportSites } from "../import-scanner.js";
|
|
8
|
+
import { isPathUnderRoot, normalizeRepoRelativePath } from "../tmvc-path.js";
|
|
9
|
+
import { classifySpecifier, loadTsconfigPaths } from "./resolve-specifier.js";
|
|
10
|
+
const SOURCE_EXT = new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
11
|
+
const SKIP_DIRS = new Set(["node_modules", "dist", "build", "coverage"]);
|
|
12
|
+
export function isScannableSource(fileRel) {
|
|
13
|
+
const ext = path.extname(fileRel).toLowerCase();
|
|
14
|
+
return SOURCE_EXT.has(ext) && !fileRel.endsWith(".d.ts");
|
|
15
|
+
}
|
|
16
|
+
function walkSources(repoRoot, absRoot, out) {
|
|
17
|
+
if (!fs.existsSync(absRoot))
|
|
18
|
+
return;
|
|
19
|
+
const stat = fs.statSync(absRoot);
|
|
20
|
+
if (stat.isFile()) {
|
|
21
|
+
if (isScannableSource(absRoot))
|
|
22
|
+
out.push(toPosixRel(repoRoot, absRoot));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!stat.isDirectory())
|
|
26
|
+
return;
|
|
27
|
+
for (const ent of fs.readdirSync(absRoot, { withFileTypes: true })) {
|
|
28
|
+
const child = path.join(absRoot, ent.name);
|
|
29
|
+
if (ent.isDirectory()) {
|
|
30
|
+
if (SKIP_DIRS.has(ent.name) || ent.name.startsWith("."))
|
|
31
|
+
continue;
|
|
32
|
+
walkSources(repoRoot, child, out);
|
|
33
|
+
}
|
|
34
|
+
else if (ent.isFile() && isScannableSource(ent.name)) {
|
|
35
|
+
out.push(toPosixRel(repoRoot, child));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Repo-relative source files under the effective TMVC roots (sorted, deduped). */
|
|
40
|
+
export function listSourcesUnderRoots(repoRoot, roots) {
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const root of roots)
|
|
43
|
+
walkSources(repoRoot, path.join(repoRoot, root), out);
|
|
44
|
+
return [...new Set(out)].sort();
|
|
45
|
+
}
|
|
46
|
+
function addGitNames(repoRoot, args, out) {
|
|
47
|
+
const r = gitRunOk(repoRoot, [...args, "--"]);
|
|
48
|
+
if (!r.ok)
|
|
49
|
+
return false;
|
|
50
|
+
for (const line of r.stdout.split(/\r?\n/))
|
|
51
|
+
if (line.trim())
|
|
52
|
+
out.add(line.trim());
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Dirty sources: `git diff --name-only HEAD` ∪ untracked. On an unborn branch (no HEAD) the
|
|
57
|
+
* index (`ls-files --cached`) stands in for the diff. Every argv ends with `--` so a path that
|
|
58
|
+
* looks like a flag is never parsed as one. Missing/deleted paths are dropped.
|
|
59
|
+
*/
|
|
60
|
+
export function listChangedSourceFiles(repoRoot) {
|
|
61
|
+
const out = new Set();
|
|
62
|
+
if (!addGitNames(repoRoot, ["diff", "--name-only", "HEAD"], out)) {
|
|
63
|
+
addGitNames(repoRoot, ["ls-files", "--cached"], out);
|
|
64
|
+
}
|
|
65
|
+
addGitNames(repoRoot, ["ls-files", "--others", "--exclude-standard"], out);
|
|
66
|
+
return [...out]
|
|
67
|
+
.filter((rel) => isScannableSource(rel) && fs.existsSync(path.join(repoRoot, rel)))
|
|
68
|
+
.sort();
|
|
69
|
+
}
|
|
70
|
+
export function contractViolationCode(kind) {
|
|
71
|
+
switch (kind) {
|
|
72
|
+
case "banned":
|
|
73
|
+
return GXT_ERROR.CONTRACT_IMPORT_BANNED;
|
|
74
|
+
case "unlisted":
|
|
75
|
+
return GXT_ERROR.CONTRACT_IMPORT_UNLISTED;
|
|
76
|
+
case "dynamic":
|
|
77
|
+
return GXT_ERROR.CONTRACT_IMPORT_DYNAMIC;
|
|
78
|
+
case "scope_escape":
|
|
79
|
+
return GXT_ERROR.CONTRACT_SCOPE_ESCAPE;
|
|
80
|
+
default: {
|
|
81
|
+
const _exhaustive = kind;
|
|
82
|
+
return _exhaustive;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function violation(kind, file, site, specifier, detail) {
|
|
87
|
+
return { kind, file, line: site.line, column: site.column, specifier, detail };
|
|
88
|
+
}
|
|
89
|
+
function checkBareSpecifier(scope, file, site, spec) {
|
|
90
|
+
const banned = scope.bannedImports.find((b) => importMatchesBan(spec, b));
|
|
91
|
+
if (banned) {
|
|
92
|
+
return violation("banned", file, site, spec, `import of banned specifier "${spec}" (banned: ${banned})`);
|
|
93
|
+
}
|
|
94
|
+
if (scope.allowedImports.length > 0 && !scope.allowedImports.some((a) => importMatchesBan(spec, a))) {
|
|
95
|
+
return violation("unlisted", file, site, spec, `import "${spec}" is not in contract.allowed_imports`);
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
function checkResolvedPath(scope, file, site, spec, resolvedRepoRel) {
|
|
100
|
+
const forbidden = scope.forbiddenZones.find((fz) => isPathUnderRoot(resolvedRepoRel, fz));
|
|
101
|
+
if (forbidden) {
|
|
102
|
+
return violation("scope_escape", file, site, spec, `import resolves into forbidden zone ${forbidden} (${resolvedRepoRel})`);
|
|
103
|
+
}
|
|
104
|
+
if (scope.strictRelativeImports && scope.tmvcRoots.length > 0) {
|
|
105
|
+
const inside = scope.tmvcRoots.some((r) => isPathUnderRoot(resolvedRepoRel, r));
|
|
106
|
+
if (!inside) {
|
|
107
|
+
return violation("scope_escape", file, site, spec, `import resolves outside effective TMVC roots (${resolvedRepoRel})`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
function checkSite(scope, file, site, ts) {
|
|
113
|
+
if (site.spec === null) {
|
|
114
|
+
if (scope.allowDynamicSpecifiers)
|
|
115
|
+
return null;
|
|
116
|
+
return violation("dynamic", file, site, site.expression ?? "", `non-literal ${site.kind === "require_expr" ? "require" : "import"}(${site.expression ?? ""}) is not allowed (contract.allow_dynamic_specifiers=false)`);
|
|
117
|
+
}
|
|
118
|
+
const cls = classifySpecifier(site.spec, file, ts);
|
|
119
|
+
switch (cls.kind) {
|
|
120
|
+
case "builtin":
|
|
121
|
+
return null;
|
|
122
|
+
case "bare":
|
|
123
|
+
return checkBareSpecifier(scope, file, site, cls.specifier);
|
|
124
|
+
case "relative":
|
|
125
|
+
case "alias":
|
|
126
|
+
return checkResolvedPath(scope, file, site, cls.specifier, cls.resolvedRepoRel);
|
|
127
|
+
default: {
|
|
128
|
+
const _exhaustive = cls;
|
|
129
|
+
return _exhaustive;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Scan a single source file's import sites against the effective scope. */
|
|
134
|
+
export function scanFileImports(repoRoot, fileRel, scope, ts = loadTsconfigPaths(repoRoot)) {
|
|
135
|
+
const abs = path.join(repoRoot, fileRel);
|
|
136
|
+
if (!fs.existsSync(abs) || !fs.statSync(abs).isFile())
|
|
137
|
+
return [];
|
|
138
|
+
const norm = normalizeRepoRelativePath(fileRel);
|
|
139
|
+
const out = [];
|
|
140
|
+
for (const site of extractImportSites(fs.readFileSync(abs, "utf8"))) {
|
|
141
|
+
const v = checkSite(scope, norm, site, ts);
|
|
142
|
+
if (v)
|
|
143
|
+
out.push(v);
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Import-site scan for the effective cage: banned / unlisted bare specifiers, non-literal dynamic
|
|
149
|
+
* specifiers, and relative or alias imports resolving into forbidden zones (or outside TMVC when
|
|
150
|
+
* `strict_relative_imports`). Deterministic ordering by file, line, column.
|
|
151
|
+
*/
|
|
152
|
+
export function scanContractImports(repoRoot, scope, options = {}) {
|
|
153
|
+
const files = options.files
|
|
154
|
+
? [...new Set(options.files.map(normalizeRepoRelativePath))].filter(isScannableSource).sort()
|
|
155
|
+
: scope.tmvcRoots.length > 0
|
|
156
|
+
? listSourcesUnderRoots(repoRoot, scope.tmvcRoots)
|
|
157
|
+
: listChangedSourceFiles(repoRoot);
|
|
158
|
+
const ts = loadTsconfigPaths(repoRoot);
|
|
159
|
+
const out = [];
|
|
160
|
+
for (const file of files)
|
|
161
|
+
out.push(...scanFileImports(repoRoot, file, scope, ts));
|
|
162
|
+
return out.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.column - b.column);
|
|
163
|
+
}
|
|
164
|
+
export function formatContractViolation(v) {
|
|
165
|
+
return `[${contractViolationCode(v.kind)}] ${v.file}:${v.line}:${v.column} ${v.detail}`;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=contract-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-scan.js","sourceRoot":"","sources":["../../../../src/cli/lib/contract/contract-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Planner-sealed mission cage (ADR-0045). All fields optional; absent = inherit skill/policy. */
|
|
2
|
+
export interface MissionContract {
|
|
3
|
+
tmvc_roots?: string[];
|
|
4
|
+
forbidden_zones?: string[];
|
|
5
|
+
allowed_imports?: string[];
|
|
6
|
+
banned_imports?: string[];
|
|
7
|
+
allow_dynamic_specifiers?: boolean;
|
|
8
|
+
strict_relative_imports?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Effective cage after merging skill roots, mission contract, and org policy (tighten-only). */
|
|
11
|
+
export interface EffectiveScope {
|
|
12
|
+
/** Repo-relative TMVC roots (contract narrowing when present, else skill roots). */
|
|
13
|
+
tmvcRoots: string[];
|
|
14
|
+
/** Union of skill, contract, and policy forbidden zones. */
|
|
15
|
+
forbiddenZones: string[];
|
|
16
|
+
/** Bare-specifier allowlist; empty = no allowlist enforced. */
|
|
17
|
+
allowedImports: string[];
|
|
18
|
+
/** Union of contract and policy banned bare specifiers (exact or prefix match). */
|
|
19
|
+
bannedImports: string[];
|
|
20
|
+
allowDynamicSpecifiers: boolean;
|
|
21
|
+
strictRelativeImports: boolean;
|
|
22
|
+
/** True when the mission declared a contract block. */
|
|
23
|
+
hasContract: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type ContractViolationKind = "banned" | "unlisted" | "dynamic" | "scope_escape";
|
|
26
|
+
export interface ContractImportViolation {
|
|
27
|
+
kind: ContractViolationKind;
|
|
28
|
+
/** Repo-relative importing file. */
|
|
29
|
+
file: string;
|
|
30
|
+
line: number;
|
|
31
|
+
column: number;
|
|
32
|
+
/** Specifier text, or the raw expression for dynamic sites. */
|
|
33
|
+
specifier: string;
|
|
34
|
+
detail: string;
|
|
35
|
+
}
|
|
36
|
+
export declare const CONTRACT_ARRAY_KEYS: readonly ["tmvc_roots", "forbidden_zones", "allowed_imports", "banned_imports"];
|
|
37
|
+
export declare const CONTRACT_BOOLEAN_KEYS: readonly ["allow_dynamic_specifiers", "strict_relative_imports"];
|
|
38
|
+
//# sourceMappingURL=contract-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-types.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/contract/contract-types.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,oFAAoF;IACpF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,4DAA4D;IAC5D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,mFAAmF;IACnF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,sBAAsB,EAAE,OAAO,CAAC;IAChC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uDAAuD;IACvD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,cAAc,CAAC;AAEvF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,mBAAmB,iFAKuB,CAAC;AAExD,eAAO,MAAM,qBAAqB,kEAGqB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const CONTRACT_ARRAY_KEYS = [
|
|
2
|
+
"tmvc_roots",
|
|
3
|
+
"forbidden_zones",
|
|
4
|
+
"allowed_imports",
|
|
5
|
+
"banned_imports",
|
|
6
|
+
];
|
|
7
|
+
export const CONTRACT_BOOLEAN_KEYS = [
|
|
8
|
+
"allow_dynamic_specifiers",
|
|
9
|
+
"strict_relative_imports",
|
|
10
|
+
];
|
|
11
|
+
//# sourceMappingURL=contract-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-types.js","sourceRoot":"","sources":["../../../../src/cli/lib/contract/contract-types.ts"],"names":[],"mappings":"AAuCA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,YAAY;IACZ,iBAAiB;IACjB,iBAAiB;IACjB,gBAAgB;CACqC,CAAC;AAExD,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,0BAA0B;IAC1B,yBAAyB;CAC4B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OrgPolicyBundle } from "../policy/policy-types.js";
|
|
2
|
+
import type { Manifest, ParsedMission } from "../types.js";
|
|
3
|
+
import type { EffectiveScope, MissionContract } from "./contract-types.js";
|
|
4
|
+
export interface ResolveEffectiveScopeInput {
|
|
5
|
+
manifest: Manifest;
|
|
6
|
+
skillKey: string;
|
|
7
|
+
contract: MissionContract | null;
|
|
8
|
+
/** Cached org policy bundle (ADR-0042); null when absent or unreadable. */
|
|
9
|
+
policy?: OrgPolicyBundle | null;
|
|
10
|
+
}
|
|
11
|
+
/** Best-effort offline policy bundle; verify's policy phase owns failure reporting. */
|
|
12
|
+
export declare function loadPolicyBundleQuiet(root: string): OrgPolicyBundle | null;
|
|
13
|
+
/**
|
|
14
|
+
* Tighten-only merge (RULES §4, §8): TMVC = contract narrowing or skill roots; forbidden zones and
|
|
15
|
+
* banned imports are unions of skill, contract, and policy. Throws GXT_CONTRACT_SCOPE_ESCAPE when the
|
|
16
|
+
* contract tries to widen scope.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveEffectiveScope(input: ResolveEffectiveScopeInput): EffectiveScope;
|
|
19
|
+
/** Convenience for callers holding a parsed mission and repo root (loads policy quietly). */
|
|
20
|
+
export declare function resolveEffectiveScopeForMission(root: string, manifest: Manifest, mission: ParsedMission): EffectiveScope;
|
|
21
|
+
//# sourceMappingURL=effective-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effective-scope.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/contract/effective-scope.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAIjE,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3E,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CACjC;AAED,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAI1E;AA+BD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,GAAG,cAAc,CAyBvF;AAED,6FAA6F;AAC7F,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,GAAG,cAAc,CAWxH"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { GantryUserError } from "../errors.js";
|
|
2
|
+
import { GXT_ERROR } from "../gxt-error-codes.js";
|
|
3
|
+
import { resolveOrgPolicy } from "../policy/policy-resolve.js";
|
|
4
|
+
import { resolveManifestSkillKey } from "../skill-key.js";
|
|
5
|
+
import { isPathUnderRoot } from "../tmvc-path.js";
|
|
6
|
+
import { normalizeContract, normalizeContractPath } from "./contract-hash.js";
|
|
7
|
+
/** Best-effort offline policy bundle; verify's policy phase owns failure reporting. */
|
|
8
|
+
export function loadPolicyBundleQuiet(root) {
|
|
9
|
+
const resolved = resolveOrgPolicy(root);
|
|
10
|
+
if (!resolved.ok || !resolved.present)
|
|
11
|
+
return null;
|
|
12
|
+
return resolved.bundle;
|
|
13
|
+
}
|
|
14
|
+
function unionSorted(...lists) {
|
|
15
|
+
const out = new Set();
|
|
16
|
+
for (const list of lists)
|
|
17
|
+
for (const v of list)
|
|
18
|
+
if (v.trim())
|
|
19
|
+
out.add(v);
|
|
20
|
+
return [...out].sort();
|
|
21
|
+
}
|
|
22
|
+
function assertSubsetOfSkillRoots(contractRoots, skillRoots, skillKey) {
|
|
23
|
+
if (skillRoots.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
const escaped = contractRoots.filter((r) => !skillRoots.some((s) => isPathUnderRoot(r, s)));
|
|
26
|
+
if (escaped.length === 0)
|
|
27
|
+
return;
|
|
28
|
+
throw new GantryUserError(GXT_ERROR.CONTRACT_SCOPE_ESCAPE, `${GXT_ERROR.CONTRACT_SCOPE_ESCAPE}: contract.tmvc_roots must stay inside skill ${skillKey} roots (${skillRoots.join(", ")}); escaped: ${escaped.join(", ")}`, "Narrow contract.tmvc_roots to a subset of the manifest skill tmvc_roots, or legislate under a skill that owns those roots.", 2);
|
|
29
|
+
}
|
|
30
|
+
function assertRootsOutsideForbidden(contractRoots, forbidden) {
|
|
31
|
+
const hits = contractRoots.filter((r) => forbidden.some((fz) => isPathUnderRoot(r, fz)));
|
|
32
|
+
if (hits.length === 0)
|
|
33
|
+
return;
|
|
34
|
+
throw new GantryUserError(GXT_ERROR.CONTRACT_SCOPE_ESCAPE, `${GXT_ERROR.CONTRACT_SCOPE_ESCAPE}: contract.tmvc_roots overlap forbidden zones: ${hits.join(", ")}`, "Remove the forbidden path from contract.tmvc_roots; forbidden zones are tighten-only and cannot be re-opened by a mission.", 2);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Tighten-only merge (RULES §4, §8): TMVC = contract narrowing or skill roots; forbidden zones and
|
|
38
|
+
* banned imports are unions of skill, contract, and policy. Throws GXT_CONTRACT_SCOPE_ESCAPE when the
|
|
39
|
+
* contract tries to widen scope.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveEffectiveScope(input) {
|
|
42
|
+
const skillKey = resolveManifestSkillKey(input.manifest, input.skillKey);
|
|
43
|
+
const skill = input.manifest.skills[skillKey];
|
|
44
|
+
const skillRoots = (skill?.tmvc_roots ?? []).map(normalizeContractPath);
|
|
45
|
+
const skillForbidden = (skill?.forbidden_zones ?? []).map(normalizeContractPath);
|
|
46
|
+
const contract = input.contract ? normalizeContract(input.contract) : {};
|
|
47
|
+
const policy = input.policy ?? null;
|
|
48
|
+
const policyForbidden = (policy?.manifest_constraints?.forbidden_zones_add ?? []).map(normalizeContractPath);
|
|
49
|
+
const policyBanned = (policy?.banned_imports ?? []).map((b) => b.specifier.trim());
|
|
50
|
+
const forbiddenZones = unionSorted(skillForbidden, contract.forbidden_zones ?? [], policyForbidden);
|
|
51
|
+
const contractRoots = contract.tmvc_roots ?? [];
|
|
52
|
+
assertSubsetOfSkillRoots(contractRoots, skillRoots, skillKey);
|
|
53
|
+
assertRootsOutsideForbidden(contractRoots, forbiddenZones);
|
|
54
|
+
return {
|
|
55
|
+
tmvcRoots: contractRoots.length > 0 ? contractRoots : skillRoots,
|
|
56
|
+
forbiddenZones,
|
|
57
|
+
allowedImports: [...(contract.allowed_imports ?? [])],
|
|
58
|
+
bannedImports: unionSorted(contract.banned_imports ?? [], policyBanned),
|
|
59
|
+
allowDynamicSpecifiers: contract.allow_dynamic_specifiers === true,
|
|
60
|
+
strictRelativeImports: contract.strict_relative_imports === true,
|
|
61
|
+
hasContract: input.contract !== null,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Convenience for callers holding a parsed mission and repo root (loads policy quietly). */
|
|
65
|
+
export function resolveEffectiveScopeForMission(root, manifest, mission) {
|
|
66
|
+
const skillKey = mission.skillKey?.trim();
|
|
67
|
+
if (!skillKey) {
|
|
68
|
+
throw new GantryUserError("MISSION_SCHEMA_INVALID", `mission missing skill_key (${mission.rawPath})`, undefined, 2);
|
|
69
|
+
}
|
|
70
|
+
return resolveEffectiveScope({
|
|
71
|
+
manifest,
|
|
72
|
+
skillKey,
|
|
73
|
+
contract: mission.contract,
|
|
74
|
+
policy: loadPolicyBundleQuiet(root),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=effective-scope.js.map
|