mirror of
https://github.com/affaan-m/ECC.git
synced 2026-08-17 21:15:40 +02:00
fix(ito): harden canonical workload bridge
This commit is contained in:
+12
-12
@@ -15,11 +15,9 @@ const SUPPORTED_COMMANDS = Object.freeze([
|
||||
"serve", "train", "workload-status", "workload-cancel", "workload-cleanup",
|
||||
]);
|
||||
const CANONICAL_PACKAGE_PATH = "cli/ito-compute-cli";
|
||||
const CANONICAL_ENTRY_SEGMENTS = Object.freeze([
|
||||
...CANONICAL_PACKAGE_PATH.split("/"),
|
||||
"dist",
|
||||
"bin",
|
||||
"ito.js",
|
||||
const CANONICAL_ENTRY_TAILS = Object.freeze([
|
||||
Object.freeze([...CANONICAL_PACKAGE_PATH.split("/"), "dist", "bin", "ito.js"]),
|
||||
Object.freeze(["ito-compute-cli", "dist", "bin", "ito.js"]),
|
||||
]);
|
||||
const EXECUTABLE_OVERRIDE = "ECC_ITO_CLI_EXECUTABLE";
|
||||
const MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
|
||||
@@ -213,6 +211,9 @@ function parseArgs(argv, environment = process.env) {
|
||||
"--entitlement", "--artifact-ref", "--image-digest",
|
||||
"--max-runtime-seconds", "--max-incremental-cost-usd", "--idempotency-key",
|
||||
], ["--checkpoint-ref"]);
|
||||
if (requiredOptionValue(withoutJson, "--max-incremental-cost-usd") !== "0") {
|
||||
throw new Error("--max-incremental-cost-usd must be exactly 0 until workload accounting is enabled.");
|
||||
}
|
||||
}
|
||||
if (command === "workload-status" || command === "workload-cancel" || command === "workload-cleanup") {
|
||||
validateRunLifecycleArgs(withoutJson);
|
||||
@@ -275,13 +276,12 @@ function isCanonicalItoEntry(candidate) {
|
||||
.normalize(candidate)
|
||||
.split(path.sep)
|
||||
.filter(Boolean);
|
||||
if (pathSegments.length < CANONICAL_ENTRY_SEGMENTS.length) return false;
|
||||
const candidateTail = pathSegments.slice(-CANONICAL_ENTRY_SEGMENTS.length);
|
||||
return candidateTail.every((segment, index) => {
|
||||
const expected = CANONICAL_ENTRY_SEGMENTS[index];
|
||||
return process.platform === "win32"
|
||||
? segment.toLowerCase() === expected.toLowerCase()
|
||||
: segment === expected;
|
||||
return CANONICAL_ENTRY_TAILS.some((expectedTail) => {
|
||||
if (pathSegments.length < expectedTail.length) return false;
|
||||
const candidateTail = pathSegments.slice(-expectedTail.length);
|
||||
return candidateTail.every((segment, index) => process.platform === "win32"
|
||||
? segment.toLowerCase() === expectedTail[index].toLowerCase()
|
||||
: segment === expectedTail[index]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ ecc ito serve \
|
||||
--artifact-ref <immutable-model-ref> \
|
||||
--image-digest <sha256:image-digest> \
|
||||
--max-runtime-seconds <ceiling> \
|
||||
--max-incremental-cost-usd <ceiling> \
|
||||
--max-incremental-cost-usd 0 \
|
||||
--idempotency-key <opaque-id>
|
||||
```
|
||||
|
||||
@@ -65,7 +65,8 @@ addresses, and do not claim endpoint readiness without functional evidence.
|
||||
|
||||
## What the backend does (Layer 0.2)
|
||||
|
||||
The desk backend, not ECC, runs the stages, and this skill only reports them:
|
||||
These stages are target acceptance contracts for the future reviewed provider
|
||||
adapter; they are not evidence that a live adapter exists today:
|
||||
|
||||
1. Fabric gate — never launch on unverified metal. Blocks below 80% of
|
||||
fabric-expected bus bandwidth; advisory between 80% and 92%; fails loud on
|
||||
|
||||
@@ -29,7 +29,7 @@ ecc ito train \
|
||||
--artifact-ref <immutable-training-manifest-ref> \
|
||||
--image-digest <sha256:image-digest> \
|
||||
--max-runtime-seconds <ceiling> \
|
||||
--max-incremental-cost-usd <ceiling> \
|
||||
--max-incremental-cost-usd 0 \
|
||||
--idempotency-key <opaque-id> \
|
||||
[--checkpoint-ref <server-managed-ref>]
|
||||
```
|
||||
@@ -77,8 +77,9 @@ cancel/cleanup lifecycle.
|
||||
|
||||
## What the backend does (Layer 0.3)
|
||||
|
||||
The desk backend runs a staged, eval-gated pipeline; this skill reports stage
|
||||
gates and never overrides one:
|
||||
These stages are target acceptance contracts for the future reviewed provider
|
||||
adapter; they are not evidence that a live adapter exists today. ECC reports
|
||||
stage gates and never overrides one:
|
||||
|
||||
1. Data prep — manifest, dedup, decontamination against the eval suite;
|
||||
150M-ladder decision job as the cheap pre-check for custom data.
|
||||
|
||||
@@ -63,18 +63,12 @@ function runCliAndObserveFirstOutput(args, environment = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
function makeItoProbe(exitCode = 0) {
|
||||
function makeItoProbe(exitCode = 0, layout = "source") {
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-ito-cli-"));
|
||||
const log = path.join(directory, "invocation.json");
|
||||
const script = path.join(
|
||||
directory,
|
||||
"ito-cloud-runtime",
|
||||
"cli",
|
||||
"ito-compute-cli",
|
||||
"dist",
|
||||
"bin",
|
||||
"ito.js"
|
||||
);
|
||||
const script = layout === "global"
|
||||
? path.join(directory, "lib", "node_modules", "ito-compute-cli", "dist", "bin", "ito.js")
|
||||
: path.join(directory, "ito-cloud-runtime", "cli", "ito-compute-cli", "dist", "bin", "ito.js");
|
||||
const executable = script;
|
||||
fs.mkdirSync(path.dirname(script), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
@@ -183,6 +177,31 @@ async function main() {
|
||||
fs.rmSync(allowed.directory, { recursive: true, force: true });
|
||||
}
|
||||
}],
|
||||
["accepts the verified global npm package entry without PATH discovery", () => {
|
||||
const probe = makeItoProbe(0, "global");
|
||||
try {
|
||||
const result = runCli(["ito", "status"], { ECC_ITO_CLI_EXECUTABLE: probe.executable });
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
assert.deepStrictEqual(readInvocation(probe).argv, ["status"]);
|
||||
} finally {
|
||||
fs.rmSync(probe.directory, { recursive: true, force: true });
|
||||
}
|
||||
}],
|
||||
["rejects nonzero incremental workload cost before spawning", () => {
|
||||
const probe = makeItoProbe();
|
||||
try {
|
||||
const result = runCli([
|
||||
"ito", "serve", "--entitlement", "ent_001", "--artifact-ref", "model:rev",
|
||||
"--image-digest", `sha256:${"d".repeat(64)}`, "--max-runtime-seconds", "300",
|
||||
"--max-incremental-cost-usd", "1", "--idempotency-key", "idem_001",
|
||||
], { ECC_ITO_CLI_EXECUTABLE: probe.executable });
|
||||
assert.notStrictEqual(result.status, 0);
|
||||
assert.match(result.stderr, /must be exactly 0/i);
|
||||
assert.ok(!fs.existsSync(probe.log));
|
||||
} finally {
|
||||
fs.rmSync(probe.directory, { recursive: true, force: true });
|
||||
}
|
||||
}],
|
||||
["rejects untyped workload, node-access, and secret arguments before spawning", () => {
|
||||
const base = [
|
||||
"ito", "train",
|
||||
|
||||
Reference in New Issue
Block a user