@agent-teams/engineering-foundation 0.4.0 → 0.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 +22 -0
- package/dist/capabilities/public-api-compatibility/adapters/outbound/api-extractor/microsoft-public-api-extractor.d.ts.map +1 -1
- package/dist/capabilities/public-api-compatibility/adapters/outbound/api-extractor/microsoft-public-api-extractor.js +12 -2
- package/dist/capabilities/public-api-compatibility/adapters/outbound/api-extractor/microsoft-public-api-extractor.js.map +1 -1
- package/dist/capabilities/repository-agent-workflow/adapters/inbound/cli/report-renderer.d.ts +3 -0
- package/dist/capabilities/repository-agent-workflow/adapters/inbound/cli/report-renderer.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/inbound/cli/report-renderer.js +26 -0
- package/dist/capabilities/repository-agent-workflow/adapters/inbound/cli/report-renderer.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/filesystem/filesystem-repository-agent-workflow-reader.d.ts +6 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/filesystem/filesystem-repository-agent-workflow-reader.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/filesystem/filesystem-repository-agent-workflow-reader.js +81 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/filesystem/filesystem-repository-agent-workflow-reader.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/git/git-repository-changes-reader.d.ts +15 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/git/git-repository-changes-reader.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/git/git-repository-changes-reader.js +153 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/git/git-repository-changes-reader.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/pnpm/pnpm-package-script-runner.d.ts +17 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/pnpm/pnpm-package-script-runner.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/pnpm/pnpm-package-script-runner.js +70 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/pnpm/pnpm-package-script-runner.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/process/process-execution.d.ts +10 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/process/process-execution.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/process/process-execution.js +30 -0
- package/dist/capabilities/repository-agent-workflow/adapters/outbound/process/process-execution.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/model/changed-workflow.d.ts +36 -0
- package/dist/capabilities/repository-agent-workflow/application/model/changed-workflow.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/model/changed-workflow.js +2 -0
- package/dist/capabilities/repository-agent-workflow/application/model/changed-workflow.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/model/repository-agent-workflow.d.ts +34 -0
- package/dist/capabilities/repository-agent-workflow/application/model/repository-agent-workflow.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/model/repository-agent-workflow.js +2 -0
- package/dist/capabilities/repository-agent-workflow/application/model/repository-agent-workflow.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/policies/evaluate-repository-agent-workflow.d.ts +4 -0
- package/dist/capabilities/repository-agent-workflow/application/policies/evaluate-repository-agent-workflow.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/policies/evaluate-repository-agent-workflow.js +131 -0
- package/dist/capabilities/repository-agent-workflow/application/policies/evaluate-repository-agent-workflow.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/changed-workflow.d.ts +17 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/changed-workflow.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/changed-workflow.js +2 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/changed-workflow.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/repository-agent-workflow-reader.d.ts +5 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/repository-agent-workflow-reader.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/repository-agent-workflow-reader.js +2 -0
- package/dist/capabilities/repository-agent-workflow/application/ports/repository-agent-workflow-reader.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/rules.d.ts +8 -0
- package/dist/capabilities/repository-agent-workflow/application/rules.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/rules.js +35 -0
- package/dist/capabilities/repository-agent-workflow/application/rules.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/analyze-repository-agent-workflow.d.ts +9 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/analyze-repository-agent-workflow.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/analyze-repository-agent-workflow.js +7 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/analyze-repository-agent-workflow.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/run-changed-agent-workflow.d.ts +4 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/run-changed-agent-workflow.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/run-changed-agent-workflow.js +79 -0
- package/dist/capabilities/repository-agent-workflow/application/use-cases/run-changed-agent-workflow.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/changed-command.d.ts +9 -0
- package/dist/capabilities/repository-agent-workflow/changed-command.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/changed-command.js +28 -0
- package/dist/capabilities/repository-agent-workflow/changed-command.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/contract/config.d.ts +5 -0
- package/dist/capabilities/repository-agent-workflow/contract/config.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/contract/config.js +121 -0
- package/dist/capabilities/repository-agent-workflow/contract/config.js.map +1 -0
- package/dist/capabilities/repository-agent-workflow/module.d.ts +5 -0
- package/dist/capabilities/repository-agent-workflow/module.d.ts.map +1 -0
- package/dist/capabilities/repository-agent-workflow/module.js +49 -0
- package/dist/capabilities/repository-agent-workflow/module.js.map +1 -0
- package/dist/capabilities/repository-security-baseline/application/policies/evaluate-repository-security.d.ts.map +1 -1
- package/dist/capabilities/repository-security-baseline/application/policies/evaluate-repository-security.js +150 -125
- package/dist/capabilities/repository-security-baseline/application/policies/evaluate-repository-security.js.map +1 -1
- package/dist/capabilities/workspace-dependency-declarations/application/policies/evaluate-workspace-dependencies.d.ts.map +1 -1
- package/dist/capabilities/workspace-dependency-declarations/application/policies/evaluate-workspace-dependencies.js +9 -1
- package/dist/capabilities/workspace-dependency-declarations/application/policies/evaluate-workspace-dependencies.js.map +1 -1
- package/dist/cli-arguments.d.ts +12 -0
- package/dist/cli-arguments.d.ts.map +1 -0
- package/dist/cli-arguments.js +114 -0
- package/dist/cli-arguments.js.map +1 -0
- package/dist/cli.js +131 -125
- package/dist/cli.js.map +1 -1
- package/dist/composition/capability-registry.d.ts.map +1 -1
- package/dist/composition/capability-registry.js +2 -0
- package/dist/composition/capability-registry.js.map +1 -1
- package/dist/composition/rule-registry.d.ts.map +1 -1
- package/dist/composition/rule-registry.js +2 -0
- package/dist/composition/rule-registry.js.map +1 -1
- package/dist/foundation-config.d.ts +1 -1
- package/dist/foundation-config.d.ts.map +1 -1
- package/dist/foundation-config.js +2 -0
- package/dist/foundation-config.js.map +1 -1
- package/dist/local-mode/attach-transaction.d.ts +11 -0
- package/dist/local-mode/attach-transaction.d.ts.map +1 -0
- package/dist/local-mode/attach-transaction.js +176 -0
- package/dist/local-mode/attach-transaction.js.map +1 -0
- package/dist/local-mode/consumer-policy.d.ts +2 -3
- package/dist/local-mode/consumer-policy.d.ts.map +1 -1
- package/dist/local-mode/consumer-policy.js +130 -88
- package/dist/local-mode/consumer-policy.js.map +1 -1
- package/dist/local-mode/index.d.ts +1 -0
- package/dist/local-mode/index.d.ts.map +1 -1
- package/dist/local-mode/index.js.map +1 -1
- package/dist/local-mode/inspection.d.ts.map +1 -1
- package/dist/local-mode/inspection.js +126 -118
- package/dist/local-mode/inspection.js.map +1 -1
- package/dist/local-mode/local-state-store.d.ts +6 -0
- package/dist/local-mode/local-state-store.d.ts.map +1 -0
- package/dist/local-mode/local-state-store.js +138 -0
- package/dist/local-mode/local-state-store.js.map +1 -0
- package/dist/local-mode/registry-recovery.d.ts +5 -0
- package/dist/local-mode/registry-recovery.d.ts.map +1 -0
- package/dist/local-mode/registry-recovery.js +112 -0
- package/dist/local-mode/registry-recovery.js.map +1 -0
- package/dist/local-mode/service.d.ts +1 -1
- package/dist/local-mode/service.d.ts.map +1 -1
- package/dist/local-mode/service.js +14 -398
- package/dist/local-mode/service.js.map +1 -1
- package/dist/package-self-check.d.ts +1 -1
- package/dist/package-self-check.d.ts.map +1 -1
- package/dist/package-self-check.js +13 -1
- package/dist/package-self-check.js.map +1 -1
- package/dist/public-api-surface.d.ts +4 -0
- package/dist/public-api-surface.d.ts.map +1 -0
- package/dist/public-api-surface.js +4 -0
- package/dist/public-api-surface.js.map +1 -0
- package/dist/scaffolding/adapters/memory/memory-workspace.d.ts +9 -0
- package/dist/scaffolding/adapters/memory/memory-workspace.d.ts.map +1 -0
- package/dist/scaffolding/adapters/memory/memory-workspace.js +93 -0
- package/dist/scaffolding/adapters/memory/memory-workspace.js.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-journal.d.ts +6 -0
- package/dist/scaffolding/adapters/node/filesystem-journal.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-journal.js +79 -0
- package/dist/scaffolding/adapters/node/filesystem-journal.js.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-path-guard.d.ts +7 -0
- package/dist/scaffolding/adapters/node/filesystem-path-guard.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-path-guard.js +144 -0
- package/dist/scaffolding/adapters/node/filesystem-path-guard.js.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-workspace.d.ts +13 -0
- package/dist/scaffolding/adapters/node/filesystem-workspace.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-workspace.js +336 -0
- package/dist/scaffolding/adapters/node/filesystem-workspace.js.map +1 -0
- package/dist/scaffolding/adapters/node/installed-foundation-version.d.ts +2 -0
- package/dist/scaffolding/adapters/node/installed-foundation-version.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/installed-foundation-version.js +10 -0
- package/dist/scaffolding/adapters/node/installed-foundation-version.js.map +1 -0
- package/dist/scaffolding/adapters/node/node-input-loader.d.ts +17 -0
- package/dist/scaffolding/adapters/node/node-input-loader.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/node-input-loader.js +157 -0
- package/dist/scaffolding/adapters/node/node-input-loader.js.map +1 -0
- package/dist/scaffolding/adapters/node/node-plan-authority.d.ts +3 -0
- package/dist/scaffolding/adapters/node/node-plan-authority.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/node-plan-authority.js +18 -0
- package/dist/scaffolding/adapters/node/node-plan-authority.js.map +1 -0
- package/dist/scaffolding/adapters/node/node-receipt-validator.d.ts +4 -0
- package/dist/scaffolding/adapters/node/node-receipt-validator.d.ts.map +1 -0
- package/dist/scaffolding/adapters/node/node-receipt-validator.js +10 -0
- package/dist/scaffolding/adapters/node/node-receipt-validator.js.map +1 -0
- package/dist/scaffolding/cli-command.d.ts +8 -0
- package/dist/scaffolding/cli-command.d.ts.map +1 -0
- package/dist/scaffolding/cli-command.js +60 -0
- package/dist/scaffolding/cli-command.js.map +1 -0
- package/dist/scaffolding/contract/types.d.ts +296 -0
- package/dist/scaffolding/contract/types.d.ts.map +1 -0
- package/dist/scaffolding/contract/types.js +2 -0
- package/dist/scaffolding/contract/types.js.map +1 -0
- package/dist/scaffolding/definitions/conformance-fixture.d.ts +3 -0
- package/dist/scaffolding/definitions/conformance-fixture.d.ts.map +1 -0
- package/dist/scaffolding/definitions/conformance-fixture.js +217 -0
- package/dist/scaffolding/definitions/conformance-fixture.js.map +1 -0
- package/dist/scaffolding/definitions/registry.d.ts +3 -0
- package/dist/scaffolding/definitions/registry.d.ts.map +1 -0
- package/dist/scaffolding/definitions/registry.js +6 -0
- package/dist/scaffolding/definitions/registry.js.map +1 -0
- package/dist/scaffolding/index.d.ts +11 -0
- package/dist/scaffolding/index.d.ts.map +1 -0
- package/dist/scaffolding/index.js +9 -0
- package/dist/scaffolding/index.js.map +1 -0
- package/dist/scaffolding/kernel/canonical-json.d.ts +6 -0
- package/dist/scaffolding/kernel/canonical-json.d.ts.map +1 -0
- package/dist/scaffolding/kernel/canonical-json.js +55 -0
- package/dist/scaffolding/kernel/canonical-json.js.map +1 -0
- package/dist/scaffolding/kernel/compiler.d.ts +4 -0
- package/dist/scaffolding/kernel/compiler.d.ts.map +1 -0
- package/dist/scaffolding/kernel/compiler.js +297 -0
- package/dist/scaffolding/kernel/compiler.js.map +1 -0
- package/dist/scaffolding/kernel/definition-registry.d.ts +50 -0
- package/dist/scaffolding/kernel/definition-registry.d.ts.map +1 -0
- package/dist/scaffolding/kernel/definition-registry.js +92 -0
- package/dist/scaffolding/kernel/definition-registry.js.map +1 -0
- package/dist/scaffolding/kernel/limits.d.ts +5 -0
- package/dist/scaffolding/kernel/limits.d.ts.map +1 -0
- package/dist/scaffolding/kernel/limits.js +5 -0
- package/dist/scaffolding/kernel/limits.js.map +1 -0
- package/dist/scaffolding/kernel/plan-validation.d.ts +3 -0
- package/dist/scaffolding/kernel/plan-validation.d.ts.map +1 -0
- package/dist/scaffolding/kernel/plan-validation.js +44 -0
- package/dist/scaffolding/kernel/plan-validation.js.map +1 -0
- package/dist/scaffolding/kernel/receipt.d.ts +35 -0
- package/dist/scaffolding/kernel/receipt.d.ts.map +1 -0
- package/dist/scaffolding/kernel/receipt.js +206 -0
- package/dist/scaffolding/kernel/receipt.js.map +1 -0
- package/dist/scaffolding/scaffold-error.d.ts +8 -0
- package/dist/scaffolding/scaffold-error.d.ts.map +1 -0
- package/dist/scaffolding/scaffold-error.js +11 -0
- package/dist/scaffolding/scaffold-error.js.map +1 -0
- package/dist/scaffolding/service.d.ts +8 -0
- package/dist/scaffolding/service.d.ts.map +1 -0
- package/dist/scaffolding/service.js +15 -0
- package/dist/scaffolding/service.js.map +1 -0
- package/dist/schema-ids.d.ts +1 -1
- package/dist/schema-ids.d.ts.map +1 -1
- package/dist/schema-ids.js +6 -0
- package/dist/schema-ids.js.map +1 -1
- package/dist/source-inventory/adapters/outbound/filesystem/filesystem-source-tree-reader.d.ts.map +1 -1
- package/dist/source-inventory/adapters/outbound/filesystem/filesystem-source-tree-reader.js +17 -12
- package/dist/source-inventory/adapters/outbound/filesystem/filesystem-source-tree-reader.js.map +1 -1
- package/package.json +5 -1
- package/presets/oxlint/maintainability-tests.json +23 -0
- package/presets/oxlint/maintainability.json +23 -0
- package/schemas/foundation-config/v1.schema.json +10 -0
- package/schemas/repository-agent-workflow/v1.schema.json +92 -0
- package/schemas/scaffold-intent/v1.schema.json +60 -0
- package/schemas/scaffold-plan/v1.schema.json +250 -0
- package/schemas/scaffold-receipt/v1.schema.json +299 -0
- package/schemas/scaffold-target-catalog/v1.schema.json +52 -0
- package/schemas/scaffolding-config/v1.schema.json +99 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { sha256Bytes } from "../../kernel/canonical-json.js";
|
|
2
|
+
import { assertScaffoldPlanDigest } from "../../kernel/plan-validation.js";
|
|
3
|
+
import { createScaffoldReceipt } from "../../kernel/receipt.js";
|
|
4
|
+
import { assertSchema } from "../../../schema-catalog.js";
|
|
5
|
+
export class MemoryScaffoldWorkspace {
|
|
6
|
+
#files;
|
|
7
|
+
constructor(files = {}) {
|
|
8
|
+
this.#files = new Map(Object.entries(files).map(([path, content]) => [
|
|
9
|
+
path,
|
|
10
|
+
typeof content === "string"
|
|
11
|
+
? Buffer.from(content, "utf8")
|
|
12
|
+
: Uint8Array.from(content)
|
|
13
|
+
]));
|
|
14
|
+
}
|
|
15
|
+
read(path) {
|
|
16
|
+
const value = this.#files.get(path);
|
|
17
|
+
return value === undefined ? undefined : Uint8Array.from(value);
|
|
18
|
+
}
|
|
19
|
+
entries() {
|
|
20
|
+
return Object.fromEntries([...this.#files.entries()]
|
|
21
|
+
.toSorted(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
22
|
+
.map(([path, content]) => [path, Uint8Array.from(content)]));
|
|
23
|
+
}
|
|
24
|
+
async apply(plan) {
|
|
25
|
+
await assertSchema("scaffold-plan/v1", plan, "scaffold-memory-apply-plan");
|
|
26
|
+
assertScaffoldPlanDigest(plan);
|
|
27
|
+
const diagnostics = [];
|
|
28
|
+
const classifications = plan.operations.map((operation) => {
|
|
29
|
+
const current = this.#files.get(operation.path);
|
|
30
|
+
if (current === undefined) {
|
|
31
|
+
return { operation, state: "absent" };
|
|
32
|
+
}
|
|
33
|
+
if (sha256Bytes(current) === operation.after.digest) {
|
|
34
|
+
return { operation, state: "after" };
|
|
35
|
+
}
|
|
36
|
+
diagnostics.push({
|
|
37
|
+
ruleId: "scaffolding.apply.precondition-conflict",
|
|
38
|
+
severity: "error",
|
|
39
|
+
phase: "apply",
|
|
40
|
+
subject: operation.path,
|
|
41
|
+
message: "Workspace content matches neither the Plan precondition nor its desired result.",
|
|
42
|
+
remediation: "Create a new Intent and Plan from the current workspace state."
|
|
43
|
+
});
|
|
44
|
+
return { operation, state: "conflict" };
|
|
45
|
+
});
|
|
46
|
+
if (classifications.some(({ state }) => state === "conflict")) {
|
|
47
|
+
return createScaffoldReceipt({
|
|
48
|
+
plan,
|
|
49
|
+
adapterId: "foundation.memory/v1",
|
|
50
|
+
outcome: "rejected",
|
|
51
|
+
commitState: "rejected",
|
|
52
|
+
atomicity: "memory-atomic",
|
|
53
|
+
operations: classifications.map(({ operation, state }) => ({
|
|
54
|
+
operationId: operation.id,
|
|
55
|
+
path: operation.path,
|
|
56
|
+
outcome: state === "conflict"
|
|
57
|
+
? "conflict"
|
|
58
|
+
: state === "after"
|
|
59
|
+
? "already-satisfied"
|
|
60
|
+
: "not-applied",
|
|
61
|
+
...(state === "after" ? { resultDigest: operation.after.digest } : {})
|
|
62
|
+
})),
|
|
63
|
+
diagnostics
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const next = new Map(this.#files);
|
|
67
|
+
const receipts = classifications.map(({ operation, state }) => {
|
|
68
|
+
if (state === "absent") {
|
|
69
|
+
next.set(operation.path, Buffer.from(operation.after.contentBase64, "base64"));
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
operationId: operation.id,
|
|
73
|
+
path: operation.path,
|
|
74
|
+
outcome: state === "absent" ? "applied" : "already-satisfied",
|
|
75
|
+
resultDigest: operation.after.digest
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
this.#files.clear();
|
|
79
|
+
for (const [path, content] of next) {
|
|
80
|
+
this.#files.set(path, content);
|
|
81
|
+
}
|
|
82
|
+
const changed = classifications.some(({ state }) => state === "absent");
|
|
83
|
+
return createScaffoldReceipt({
|
|
84
|
+
plan,
|
|
85
|
+
adapterId: "foundation.memory/v1",
|
|
86
|
+
outcome: changed ? "applied" : "already-applied",
|
|
87
|
+
commitState: "committed",
|
|
88
|
+
atomicity: "memory-atomic",
|
|
89
|
+
operations: receipts
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=memory-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-workspace.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/memory/memory-workspace.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,MAAM,OAAO,uBAAuB;IACzB,MAAM,CAA0B;IAEzC,YAAY,KAAK,GAAkD,EAAE;QACnE,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,CACnB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;YAC7C,IAAI;YACJ,OAAO,OAAO,KAAK,QAAQ;gBACzB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;gBAC9B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;SAC7B,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAY;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,OAAO,MAAM,CAAC,WAAW,CACvB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;aACvB,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACzE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAC9D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAoB;QAC9B,MAAM,YAAY,CAAC,kBAAkB,EAAE,IAAI,EAAE,4BAA4B,CAAC,CAAC;QAC3E,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,WAAW,GAA2B,EAAE,CAAC;QAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YACxD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAiB,EAAE,CAAC;YACjD,CAAC;YACD,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACpD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAgB,EAAE,CAAC;YAChD,CAAC;YACD,WAAW,CAAC,IAAI,CAAC;gBACf,MAAM,EAAE,yCAAyC;gBACjD,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,SAAS,CAAC,IAAI;gBACvB,OAAO,EAAE,iFAAiF;gBAC1F,WAAW,EAAE,gEAAgE;aAC9E,CAAC,CAAC;YACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAmB,EAAE,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,KAAK,UAAU,CAAC,EAAE,CAAC;YAC9D,OAAO,qBAAqB,CAAC;gBAC3B,IAAI;gBACJ,SAAS,EAAE,sBAAsB;gBACjC,OAAO,EAAE,UAAU;gBACnB,WAAW,EAAE,UAAU;gBACvB,SAAS,EAAE,eAAe;gBAC1B,UAAU,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;oBACzD,WAAW,EAAE,SAAS,CAAC,EAAE;oBACzB,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,OAAO,EACL,KAAK,KAAK,UAAU;wBAClB,CAAC,CAAC,UAAU;wBACZ,CAAC,CAAC,KAAK,KAAK,OAAO;4BACjB,CAAC,CAAC,mBAAmB;4BACrB,CAAC,CAAC,aAAa;oBACrB,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvE,CAAC,CAAC;gBACH,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAiC,eAAe,CAAC,GAAG,CAChE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;YACvB,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CACN,SAAS,CAAC,IAAI,EACd,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,EAAE,QAAQ,CAAC,CACrD,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB;gBAC7D,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM;aACrC,CAAC;QACJ,CAAC,CACF,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;QACxE,OAAO,qBAAqB,CAAC;YAC3B,IAAI;YACJ,SAAS,EAAE,sBAAsB;YACjC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB;YAChD,WAAW,EAAE,WAAW;YACxB,SAAS,EAAE,eAAe;YAC1B,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ScaffoldPlanV1 } from "../../contract/types.js";
|
|
2
|
+
export declare const SCAFFOLD_JOURNAL_FILE = "scaffolding-transaction.json";
|
|
3
|
+
export declare function writeScaffoldJournal(path: string, plan: ScaffoldPlanV1): Promise<void>;
|
|
4
|
+
export declare function readScaffoldJournal(path: string): Promise<ScaffoldPlanV1 | undefined>;
|
|
5
|
+
export declare function removeScaffoldJournal(path: string): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=filesystem-journal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-journal.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-journal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQ9D,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAUpE,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CA0CrC;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { lstat, mkdir, open, readFile, rename, rm } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { assertScaffoldPlanDigest } from "../../kernel/plan-validation.js";
|
|
4
|
+
import { ScaffoldError } from "../../scaffold-error.js";
|
|
5
|
+
import { assertSchema } from "../../../schema-catalog.js";
|
|
6
|
+
import { parseStrictYamlSource } from "../../../strict-yaml.js";
|
|
7
|
+
import { syncDirectory } from "./filesystem-path-guard.js";
|
|
8
|
+
import { MAX_SCAFFOLD_PLAN_BYTES } from "./node-input-loader.js";
|
|
9
|
+
export const SCAFFOLD_JOURNAL_FILE = "scaffolding-transaction.json";
|
|
10
|
+
function isMissing(error) {
|
|
11
|
+
return (error instanceof Error &&
|
|
12
|
+
"code" in error &&
|
|
13
|
+
error.code === "ENOENT");
|
|
14
|
+
}
|
|
15
|
+
export async function writeScaffoldJournal(path, plan) {
|
|
16
|
+
const parent = dirname(path);
|
|
17
|
+
await mkdir(parent, { recursive: true });
|
|
18
|
+
const temporary = `${path}.tmp`;
|
|
19
|
+
await rm(temporary, { force: true });
|
|
20
|
+
let renamed = false;
|
|
21
|
+
try {
|
|
22
|
+
const handle = await open(temporary, "wx", 0o600);
|
|
23
|
+
try {
|
|
24
|
+
const journal = { schemaVersion: 1, state: "PREPARED", plan };
|
|
25
|
+
await handle.writeFile(`${JSON.stringify(journal, null, 2)}\n`, "utf8");
|
|
26
|
+
await handle.sync();
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await handle.close();
|
|
30
|
+
}
|
|
31
|
+
await rename(temporary, path);
|
|
32
|
+
renamed = true;
|
|
33
|
+
await syncDirectory(parent);
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
if (!renamed) {
|
|
37
|
+
await rm(temporary, { force: true });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function readScaffoldJournal(path) {
|
|
42
|
+
let source;
|
|
43
|
+
try {
|
|
44
|
+
const metadata = await lstat(path);
|
|
45
|
+
if (metadata.isSymbolicLink() ||
|
|
46
|
+
!metadata.isFile() ||
|
|
47
|
+
metadata.size > MAX_SCAFFOLD_PLAN_BYTES) {
|
|
48
|
+
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", "Scaffolding recovery journal is not a bounded regular file.");
|
|
49
|
+
}
|
|
50
|
+
source = await readFile(path, "utf8");
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (isMissing(error)) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
const value = parseStrictYamlSource(source, "scaffold-recovery-journal");
|
|
59
|
+
if (typeof value !== "object" ||
|
|
60
|
+
value === null ||
|
|
61
|
+
Array.isArray(value) ||
|
|
62
|
+
Object.keys(value).length !== 3 ||
|
|
63
|
+
!("schemaVersion" in value) ||
|
|
64
|
+
value.schemaVersion !== 1 ||
|
|
65
|
+
!("state" in value) ||
|
|
66
|
+
value.state !== "PREPARED" ||
|
|
67
|
+
!("plan" in value)) {
|
|
68
|
+
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", "Scaffolding recovery journal is invalid.");
|
|
69
|
+
}
|
|
70
|
+
await assertSchema("scaffold-plan/v1", value.plan, "scaffold-recovery-journal");
|
|
71
|
+
const plan = value.plan;
|
|
72
|
+
assertScaffoldPlanDigest(plan);
|
|
73
|
+
return plan;
|
|
74
|
+
}
|
|
75
|
+
export async function removeScaffoldJournal(path) {
|
|
76
|
+
await rm(path, { force: true });
|
|
77
|
+
await syncDirectory(dirname(path));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=filesystem-journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-journal.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-journal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ScaffoldPlanV1 } from "../../contract/types.js";
|
|
2
|
+
export declare function isContainedPath(root: string, candidate: string): boolean;
|
|
3
|
+
export declare function assertSafeOperationPaths(plan: ScaffoldPlanV1): void;
|
|
4
|
+
export declare function syncDirectory(path: string): Promise<void>;
|
|
5
|
+
export declare function ensureSafeParent(root: string, repositoryPath: string): Promise<string>;
|
|
6
|
+
export declare function assertSafeExistingAncestors(root: string, repositoryPath: string): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=filesystem-path-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-path-guard.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-path-guard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAqB9D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAMxE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAkDnE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/D;AAwBD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { lstat, mkdir, open, readdir, realpath } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, join, relative, sep } from "node:path";
|
|
3
|
+
import { ScaffoldError } from "../../scaffold-error.js";
|
|
4
|
+
const PROTECTED_ROOTS = new Set([".agent-teams-local", ".git", "node_modules"]);
|
|
5
|
+
const WINDOWS_RESERVED_NAMES = new Set([
|
|
6
|
+
"AUX",
|
|
7
|
+
"CON",
|
|
8
|
+
"NUL",
|
|
9
|
+
"PRN",
|
|
10
|
+
...Array.from({ length: 9 }, (_unused, index) => `COM${index + 1}`),
|
|
11
|
+
...Array.from({ length: 9 }, (_unused, index) => `LPT${index + 1}`)
|
|
12
|
+
]);
|
|
13
|
+
function isMissing(error) {
|
|
14
|
+
return (error instanceof Error &&
|
|
15
|
+
"code" in error &&
|
|
16
|
+
error.code === "ENOENT");
|
|
17
|
+
}
|
|
18
|
+
export function isContainedPath(root, candidate) {
|
|
19
|
+
const relation = relative(root, candidate);
|
|
20
|
+
return (relation === "" ||
|
|
21
|
+
(!relation.startsWith(`..${sep}`) && relation !== ".." && !isAbsolute(relation)));
|
|
22
|
+
}
|
|
23
|
+
export function assertSafeOperationPaths(plan) {
|
|
24
|
+
const folded = new Map();
|
|
25
|
+
const operationIds = new Set();
|
|
26
|
+
const targetPrefix = `${plan.target.path}/`;
|
|
27
|
+
for (const operation of plan.operations) {
|
|
28
|
+
const segments = operation.path.split("/");
|
|
29
|
+
if (!operation.path.startsWith(targetPrefix) ||
|
|
30
|
+
operation.path.length === 0 ||
|
|
31
|
+
operation.path.length > 512 ||
|
|
32
|
+
operation.path.includes("\\") ||
|
|
33
|
+
isAbsolute(operation.path) ||
|
|
34
|
+
segments.some((segment) => segment.length === 0 ||
|
|
35
|
+
segment === "." ||
|
|
36
|
+
segment === ".." ||
|
|
37
|
+
segment.length > 255 ||
|
|
38
|
+
segment.endsWith(".") ||
|
|
39
|
+
Array.from(segment).some((character) => (character.codePointAt(0) ?? 0) < 32) ||
|
|
40
|
+
WINDOWS_RESERVED_NAMES.has((segment.split(".")[0] ?? "").toUpperCase())) ||
|
|
41
|
+
segments.some((segment) => PROTECTED_ROOTS.has(segment.toLowerCase()))) {
|
|
42
|
+
throw new ScaffoldError("SCAFFOLD_PLAN_INVALID", `Scaffolding operation path is unsafe: ${operation.path}.`);
|
|
43
|
+
}
|
|
44
|
+
const key = operation.path.toLowerCase();
|
|
45
|
+
const existing = folded.get(key);
|
|
46
|
+
if (existing !== undefined) {
|
|
47
|
+
throw new ScaffoldError("SCAFFOLD_PLAN_INVALID", existing === operation.path
|
|
48
|
+
? `Duplicate scaffolding operation path: ${operation.path}.`
|
|
49
|
+
: `Scaffolding operation paths collide under case folding: ${existing}, ${operation.path}.`);
|
|
50
|
+
}
|
|
51
|
+
if (operationIds.has(operation.id)) {
|
|
52
|
+
throw new ScaffoldError("SCAFFOLD_PLAN_INVALID", `Duplicate scaffolding operation ID: ${operation.id}.`);
|
|
53
|
+
}
|
|
54
|
+
folded.set(key, operation.path);
|
|
55
|
+
operationIds.add(operation.id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function syncDirectory(path) {
|
|
59
|
+
try {
|
|
60
|
+
const handle = await open(path, "r");
|
|
61
|
+
try {
|
|
62
|
+
await handle.sync();
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await handle.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (process.platform === "win32" &&
|
|
70
|
+
error instanceof Error &&
|
|
71
|
+
"code" in error &&
|
|
72
|
+
["EACCES", "EINVAL", "EISDIR", "EPERM"].includes(error.code ?? "")) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function assertNoCaseCollision(parent, requestedName) {
|
|
79
|
+
const entries = await readdir(parent).catch((error) => {
|
|
80
|
+
if (isMissing(error)) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
});
|
|
85
|
+
const collision = entries.find((entry) => entry !== requestedName && entry.toLowerCase() === requestedName.toLowerCase());
|
|
86
|
+
if (collision !== undefined) {
|
|
87
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Path collides under case folding: ${collision}, ${requestedName}.`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export async function ensureSafeParent(root, repositoryPath) {
|
|
91
|
+
const segments = repositoryPath.split("/");
|
|
92
|
+
let current = root;
|
|
93
|
+
for (const segment of segments.slice(0, -1)) {
|
|
94
|
+
await assertNoCaseCollision(current, segment);
|
|
95
|
+
const next = join(current, segment);
|
|
96
|
+
try {
|
|
97
|
+
const metadata = await lstat(next);
|
|
98
|
+
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
99
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding parent is not a real directory: ${repositoryPath}.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (!isMissing(error)) {
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
await mkdir(next);
|
|
107
|
+
await syncDirectory(current);
|
|
108
|
+
}
|
|
109
|
+
const canonical = await realpath(next);
|
|
110
|
+
if (!isContainedPath(root, canonical)) {
|
|
111
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding parent escapes the repository: ${repositoryPath}.`);
|
|
112
|
+
}
|
|
113
|
+
current = canonical;
|
|
114
|
+
}
|
|
115
|
+
await assertNoCaseCollision(current, segments.at(-1) ?? "");
|
|
116
|
+
return current;
|
|
117
|
+
}
|
|
118
|
+
export async function assertSafeExistingAncestors(root, repositoryPath) {
|
|
119
|
+
const segments = repositoryPath.split("/");
|
|
120
|
+
let current = root;
|
|
121
|
+
for (const segment of segments.slice(0, -1)) {
|
|
122
|
+
await assertNoCaseCollision(current, segment);
|
|
123
|
+
const next = join(current, segment);
|
|
124
|
+
const metadata = await lstat(next).catch((error) => {
|
|
125
|
+
if (isMissing(error)) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
throw error;
|
|
129
|
+
});
|
|
130
|
+
if (metadata === null) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
134
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding parent is not a real directory: ${repositoryPath}.`);
|
|
135
|
+
}
|
|
136
|
+
const canonical = await realpath(next);
|
|
137
|
+
if (!isContainedPath(root, canonical)) {
|
|
138
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding parent escapes the repository: ${repositoryPath}.`);
|
|
139
|
+
}
|
|
140
|
+
current = canonical;
|
|
141
|
+
}
|
|
142
|
+
await assertNoCaseCollision(current, segments.at(-1) ?? "");
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=filesystem-path-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-path-guard.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-path-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ScaffoldPlanV1, ScaffoldReceiptV1 } from "../../contract/types.js";
|
|
2
|
+
export declare function recoverFilesystemScaffold(consumerRoot: string): Promise<ScaffoldReceiptV1 | undefined>;
|
|
3
|
+
export declare function applyFilesystemScaffold(consumerRoot: string, plan: ScaffoldPlanV1): Promise<ScaffoldReceiptV1>;
|
|
4
|
+
interface ScaffoldFilesystemFaultPoint {
|
|
5
|
+
readonly phase: "after-journal-prepared" | "after-hard-link" | "after-operation-published" | "after-temporary-synced" | "after-temporary-written" | "before-journal-removed";
|
|
6
|
+
readonly operationIndex?: number;
|
|
7
|
+
readonly operationPath?: string;
|
|
8
|
+
}
|
|
9
|
+
type ScaffoldFilesystemFaultInjector = (point: ScaffoldFilesystemFaultPoint) => Promise<void> | void;
|
|
10
|
+
/** Internal conformance seam. It is intentionally absent from package exports. */
|
|
11
|
+
export declare function applyFilesystemScaffoldWithFaultInjection(consumerRoot: string, plan: ScaffoldPlanV1, faultInjector?: ScaffoldFilesystemFaultInjector): Promise<ScaffoldReceiptV1>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=filesystem-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-workspace.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-workspace.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAIV,cAAc,EACd,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AA+UjC,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAyBxC;AAED,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAE5B;AAED,UAAU,4BAA4B;IACpC,QAAQ,CAAC,KAAK,EACV,wBAAwB,GACxB,iBAAiB,GACjB,2BAA2B,GAC3B,wBAAwB,GACxB,yBAAyB,GACzB,wBAAwB,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,KAAK,+BAA+B,GAAG,CACrC,KAAK,EAAE,4BAA4B,KAChC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,kFAAkF;AAClF,wBAAsB,yCAAyC,CAC7D,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,cAAc,EACpB,aAAa,CAAC,EAAE,+BAA+B,GAC9C,OAAO,CAAC,iBAAiB,CAAC,CAiG5B"}
|