feat: gate factory with cyber receipts
This commit is contained in:
parent
2fadb8a428
commit
93e5e06a9f
|
|
@ -172,6 +172,9 @@ fable-agent plinius godmode "improve explanation quality"
|
|||
- `--file <path>`
|
||||
- `factory gate <task>`
|
||||
- `--repo <path>`
|
||||
- `--host <host>`
|
||||
- `--port <n>`
|
||||
- `--capabilities <path>`
|
||||
- `--diagnostic-only`
|
||||
|
||||
### `forgejo`
|
||||
|
|
|
|||
35
src/index.ts
35
src/index.ts
|
|
@ -1456,8 +1456,11 @@ factory
|
|||
.command("gate <task>")
|
||||
.description("Run factory check plus local ZTE/repo verification gate")
|
||||
.option("--repo <path>", "Repo path to verify", ".")
|
||||
.option("--host <host>", "Factory SSH host for cyber preflight", "77.42.112.29")
|
||||
.option("--port <n>", "Factory SSH port for cyber preflight", (v) => Number(v), 2222)
|
||||
.option("--capabilities <path>", "Capability registry path", "factory-capabilities.yaml")
|
||||
.option("--diagnostic-only", "Bypass live factory/deploy readiness failures for non-deploy diagnostics")
|
||||
.action(async (task: string, opts: { repo?: string; diagnosticOnly?: boolean }) => {
|
||||
.action(async (task: string, opts: { repo?: string; host?: string; port?: number; capabilities?: string; diagnosticOnly?: boolean }) => {
|
||||
const { spawnSync } = await import("node:child_process");
|
||||
const repo = path.resolve(opts.repo ?? ".");
|
||||
const status = await printFactoryCheck();
|
||||
|
|
@ -1469,6 +1472,36 @@ factory
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const { formatCapabilityReport, loadFactoryCapabilities, probeFactoryCapabilities } = await import("./fable5/factory-capabilities.js");
|
||||
const capabilitiesPath = path.resolve(opts.capabilities ?? "factory-capabilities.yaml");
|
||||
const capabilities = await probeFactoryCapabilities(loadFactoryCapabilities(capabilitiesPath));
|
||||
console.log(formatCapabilityReport(capabilities));
|
||||
if (!capabilities.requiredOk && !opts.diagnosticOnly) {
|
||||
const { appendZteReceipt, createZteReceipt } = await import("./fable5/zte-protocol.js");
|
||||
const reason = "required factory capabilities are missing";
|
||||
appendZteReceipt(repo, createZteReceipt(task, repo, "blocked", ["factory capabilities"], reason));
|
||||
console.error(` ✗ Factory gate failed: ${reason}; use --diagnostic-only for non-deploy diagnostics.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { runCyberPreflight } = await import("./fable5/cyber-preflight.js");
|
||||
const { reconcileCyberPreflight, writeCyberReconcileReceipt } = await import("./fable5/cyber-reconcile.js");
|
||||
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
||||
const preflightPath = path.join(repo, ".fable", "cyber-preflight", `factory-gate-${stamp}.json`);
|
||||
const reconcilePath = path.join(repo, ".fable", "cyber-preflight", `factory-gate-${stamp}-reconcile.json`);
|
||||
const preflight = runCyberPreflight({ host: opts.host ?? "77.42.112.29", port: opts.port, out: preflightPath });
|
||||
const reconcile = reconcileCyberPreflight(preflightPath, capabilitiesPath);
|
||||
writeCyberReconcileReceipt(reconcilePath, reconcile);
|
||||
console.log(` Cyber preflight: ${preflight.decision} (${preflightPath})`);
|
||||
console.log(` Cyber reconcile: ${reconcile.decision} (${reconcilePath})`);
|
||||
if ((preflight.decision !== "allow_read_only" || reconcile.decision !== "allow_read_only") && !opts.diagnosticOnly) {
|
||||
const { appendZteReceipt, createZteReceipt } = await import("./fable5/zte-protocol.js");
|
||||
const reason = "cyber preflight/reconcile did not pass";
|
||||
appendZteReceipt(repo, createZteReceipt(task, repo, "blocked", ["cyber preflight", "cyber reconcile"], reason));
|
||||
console.error(` ✗ Factory gate failed: ${reason}; use --diagnostic-only for non-deploy diagnostics.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(` ZTE Gate: ${task}`);
|
||||
console.log(` Repo: ${repo}`);
|
||||
console.log(``);
|
||||
|
|
|
|||
Loading…
Reference in New Issue