@ornexus/neocortex 4.60.63 → 4.60.65
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/dist/release-source.json +1 -1
- package/dist/sbom.cdx.json +31 -38
- package/install.js +1 -0
- package/install.ps1 +34 -3
- package/install.sh +35 -3
- package/package.json +5 -3
- package/packages/client/dist/cli.js +8 -3
- package/packages/client/dist/commands/activate.js +8 -8
- package/packages/client/dist/commands/architecture-memory-terminal.js +4 -2
- package/packages/client/dist/commands/architecture-non-ui-continuation.d.ts +3 -0
- package/packages/client/dist/commands/architecture-non-ui-continuation.js +1 -0
- package/packages/client/dist/commands/invoke.d.ts +19 -16
- package/packages/client/dist/commands/invoke.js +80 -75
- package/packages/client/dist/commands/mutation-qa-run.js +2 -2
- package/packages/client/dist/commands/planning-generation.js +1 -1
- package/packages/client/dist/commands/planning-memory.d.ts +1 -0
- package/packages/client/dist/commands/planning-memory.js +1 -0
- package/packages/client/dist/commands/private-session.d.ts +1 -0
- package/packages/client/dist/commands/private-session.js +1 -0
- package/packages/client/dist/commands/qa-control.d.ts +4 -0
- package/packages/client/dist/commands/qa-control.js +1 -0
- package/packages/client/dist/commands/qa-scan-browser-launch.d.ts +8 -0
- package/packages/client/dist/commands/qa-scan-browser-launch.js +1 -0
- package/packages/client/dist/commands/qa-scan-browser-route.d.ts +3 -0
- package/packages/client/dist/commands/qa-scan-browser-route.js +1 -0
- package/packages/client/dist/commands/qa-scan-capture.d.ts +43 -0
- package/packages/client/dist/commands/qa-scan-capture.js +5 -5
- package/packages/client/dist/commands/qa-scan-discovery.d.ts +7 -0
- package/packages/client/dist/commands/qa-scan-discovery.js +3 -3
- package/packages/client/dist/commands/qa-scan-review.d.ts +8 -1
- package/packages/client/dist/commands/qa-scan-review.js +5 -5
- package/packages/client/dist/commands/qa-synthetic-backend-capture.d.ts +62 -0
- package/packages/client/dist/commands/qa-synthetic-backend-capture.js +1 -0
- package/packages/client/dist/commands/qa-synthetic-backend-review.d.ts +104 -0
- package/packages/client/dist/commands/qa-synthetic-backend-review.js +1 -0
- package/packages/client/dist/commands/qa-synthetic-backend.d.ts +52 -0
- package/packages/client/dist/commands/qa-synthetic-backend.js +7 -0
- package/packages/client/dist/commands/qa-synthetic-broker-port.d.ts +30 -0
- package/packages/client/dist/commands/qa-synthetic-broker-port.js +1 -0
- package/packages/client/dist/commands/qa-synthetic-browser.d.ts +1 -0
- package/packages/client/dist/commands/qa-synthetic-browser.js +1 -0
- package/packages/client/dist/commands/refactor-characterization.d.ts +4 -2
- package/packages/client/dist/commands/refactor-characterization.js +21 -12
- package/packages/client/dist/commands/refactor-control.d.ts +9 -0
- package/packages/client/dist/commands/refactor-control.js +3 -0
- package/packages/client/dist/commands/refactor-cpp-assertions.d.ts +4 -0
- package/packages/client/dist/commands/refactor-cpp-assertions.js +3 -0
- package/packages/client/dist/commands/refactor-review.js +5 -5
- package/packages/client/dist/commands/refactor-root.d.ts +8 -1
- package/packages/client/dist/commands/refactor-root.js +7 -7
- package/packages/client/dist/commands/refresh-memory.d.ts +1 -0
- package/packages/client/dist/commands/refresh-memory.js +3 -3
- package/packages/client/dist/commands/shared-architecture-non-ui.d.ts +18 -0
- package/packages/client/dist/commands/shared-architecture-non-ui.js +1 -0
- package/packages/client/dist/errors/error-messages.js +1 -1
- package/packages/client/dist/git/direct-yolo-checkpoint.d.ts +5 -1
- package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -4
- package/packages/client/dist/git/git-lifecycle-store.d.ts +2 -0
- package/packages/client/dist/git/git-lifecycle-store.js +9 -8
- package/packages/client/dist/license/license-client.d.ts +3 -1
- package/packages/client/dist/license/license-client.js +1 -1
- package/packages/client/dist/memory/project-memory-path-scope.d.ts +4 -0
- package/packages/client/dist/memory/project-memory-path-scope.js +1 -0
- package/packages/client/dist/memory/project-memory-writer.d.ts +4 -1
- package/packages/client/dist/memory/project-memory-writer.js +16 -16
- package/packages/client/dist/private-execution/codex-executor.d.ts +24 -4
- package/packages/client/dist/private-execution/codex-executor.js +4 -2
- package/packages/client/dist/private-execution/codex-host-runtime.d.ts +10 -0
- package/packages/client/dist/private-execution/codex-host-runtime.js +1 -0
- package/packages/client/dist/private-execution/codex-lifecycle-guard.d.ts +4 -0
- package/packages/client/dist/private-execution/codex-lifecycle-guard.js +1 -0
- package/packages/client/dist/private-execution/codex-scoped-permissions.d.ts +8 -0
- package/packages/client/dist/private-execution/codex-scoped-permissions.js +1 -0
- package/packages/client/dist/private-execution/delivery.d.ts +17 -1
- package/packages/client/dist/private-execution/delivery.js +11 -3
- package/packages/client/dist/private-execution/diagnosis-root-review.d.ts +112 -0
- package/packages/client/dist/private-execution/diagnosis-root-review.js +2 -0
- package/packages/client/dist/private-execution/frozen-handoff.d.ts +2 -0
- package/packages/client/dist/private-execution/frozen-handoff.js +6 -0
- package/packages/client/dist/private-execution/implementation-validation.d.ts +15 -0
- package/packages/client/dist/private-execution/implementation-validation.js +2 -0
- package/packages/client/dist/private-execution/isolated-admission.d.ts +11 -7
- package/packages/client/dist/private-execution/isolated-admission.js +17 -10
- package/packages/client/dist/private-execution/isolated-session.d.ts +68 -0
- package/packages/client/dist/private-execution/isolated-session.js +5 -2
- package/packages/client/dist/private-execution/pact-test-source.d.ts +1 -1
- package/packages/client/dist/private-execution/pact-test-source.js +1 -1
- package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.d.ts +2 -0
- package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +5 -5
- package/packages/client/dist/private-execution/planning-generation-checkpoint.d.ts +13 -0
- package/packages/client/dist/private-execution/planning-generation-checkpoint.js +4 -3
- package/packages/client/dist/private-execution/planning-memory-checkpoint.d.ts +32 -0
- package/packages/client/dist/private-execution/planning-memory-checkpoint.js +3 -0
- package/packages/client/dist/private-execution/planning-research-checkpoint.js +4 -4
- package/packages/client/dist/private-execution/root-checkpoint.js +1 -1
- package/packages/client/dist/private-execution/root-memory-git-evidence.d.ts +30 -0
- package/packages/client/dist/private-execution/root-memory-git-evidence.js +3 -0
- package/packages/client/dist/private-execution/root-memory-recovery.d.ts +16 -0
- package/packages/client/dist/private-execution/root-memory-recovery.js +1 -0
- package/packages/client/dist/private-execution/root-memory-request.d.ts +28 -0
- package/packages/client/dist/private-execution/root-memory-request.js +1 -0
- package/packages/client/dist/private-execution/root-memory-scope.d.ts +28 -0
- package/packages/client/dist/private-execution/root-memory-scope.js +1 -0
- package/packages/client/dist/private-execution/root-memory-writer.d.ts +22 -0
- package/packages/client/dist/private-execution/root-memory-writer.js +1 -0
- package/packages/client/dist/private-execution/session-lease.d.ts +19 -0
- package/packages/client/dist/private-execution/session-lease.js +1 -0
- package/packages/client/dist/private-execution/shared-private-admission-types.d.ts +34 -0
- package/packages/client/dist/private-execution/shared-private-admission-types.js +1 -0
- package/packages/client/dist/private-execution/shared-project-validation.d.ts +17 -0
- package/packages/client/dist/private-execution/shared-project-validation.js +1 -0
- package/packages/client/dist/private-execution/shared-root-memory-types.d.ts +37 -0
- package/packages/client/dist/private-execution/shared-root-memory-types.js +1 -0
- package/packages/client/dist/runner/binary.d.ts +1 -1
- package/packages/client/dist/runner/binary.js +1 -1
- package/packages/client/dist/runner/headless/opencode-adapter.js +2 -2
- package/packages/client/dist/yolo/change-evidence-collector.d.ts +2 -2
- package/packages/client/dist/yolo/change-evidence-collector.js +1 -1
- package/packages/client/dist/yolo/spec-envelope-collector.js +2 -2
- package/packages/shared/dist/planning/diagnosis-state.js +5 -2
- package/packages/shared/dist/project-memory-targets.js +243 -0
- package/packages/shared/dist/yolo/change-evidence.js +35 -0
- package/packages/shared/dist/yoloop/branch-unit.js +10 -1
- package/packages/shared/dist/yoloop/root-memory-effect.js +57 -0
- package/targets-stubs/antigravity/gemini.md +1 -1
- package/targets-stubs/antigravity/skill/SKILL.md +1 -1
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex-root.md +2 -2
- package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex.md +2 -2
- package/targets-stubs/codex/AGENTS.md +1 -1
- package/targets-stubs/cursor/agent.md +2 -2
- package/targets-stubs/deepseek-harness/SKILL.md +64 -0
- package/targets-stubs/gemini-cli/agent.md +2 -2
- package/targets-stubs/opencode/neocortex-root.md +1 -1
- package/targets-stubs/vscode/neocortex.agent.md +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as re,randomUUID as ce}from"node:crypto";import{closeSync as N,constants as c,fsyncSync as B,openSync as D,writeFileSync as ne}from"node:fs";import{join as oe}from"node:path";import le from"axe-core";import{launchSyntheticBackendBrowser as de}from"./qa-synthetic-browser.js";import{scenarioRequirementDigest as V,validateRootQaScanScenario as he}from"./qa-scan-capture.js";import{planRootQaScan as U,rootQaScanEvidenceDirectory as fe}from"./qa-scan-review.js";import{openSyntheticBackendSession as we}from"./qa-synthetic-backend.js";const F=a=>re("sha256").update(a).digest("hex");async function Se(a,w,i){const d=he(a.scenario),g=F(JSON.stringify(d)),y=U(a.projectRoot,a.surface,a.targetUrl),q=V(a.projectRoot,d);if(w&&(Object.keys(w).sort().join(",")!=="contractSha256,observations,request,scopeSha256,verify"||!["observations","request","verify"].every(n=>typeof w[n]=="function")||!/^[a-f0-9]{64}$/.test(w.contractSha256)||w.scopeSha256!==F(JSON.stringify([y.sourceHead,a.surface,a.targetUrl,a.generation,g,a.grantId]))))throw new Error("qa-synthetic-backend-broker-port-unverified");const u=w??await we({...a,scenarioSha256:g});if(i&&(!w||Object.keys(i).sort().join(",")!=="containerId,imageId,jobBindingSha256,kind,launch"||i.kind!=="operator-docker-job"||!/^sha256:[a-f0-9]{64}$/.test(i.imageId)||!/^[a-f0-9]{64}$/.test(i.containerId)||!/^[a-f0-9]{64}$/.test(i.jobBindingSha256)||typeof i.launch!="function"))throw new Error("qa-synthetic-backend-docker-context-invalid");const E=i?await i.launch():await de();let O,W=!1,b="context",R="";try{const n=await E.newContext({serviceWorkers:"block",acceptDownloads:!1,permissions:[],ignoreHTTPSErrors:!1,viewport:{width:1280,height:900}});let l=0,h=0,j=!1,k=0,x=0,H=0,J=0,I=0,M=0;const p=new Set,$=new URL(a.targetUrl);await n.route("**/*",async e=>{try{const t=e.request();j?k++:x++;const s=u.request(t.url(),t.method(),t.postData(),await t.allHeaders());p.add(s);let o;try{o=await s}finally{p.delete(s)}await e.fulfill({status:o.status,body:o.body,headers:{"content-type":o.contentType,"cache-control":"no-store"}})}catch(t){t instanceof Error&&/^qa-[a-z-]+$/.test(t.message)&&(R=t.message),l++,await e.abort("blockedbyclient").catch(()=>{})}}),await n.routeWebSocket(/.*/,async e=>{l++,await e.close({code:1008,reason:"blocked"})});const r=await n.newPage();n.on("page",e=>{e!==r&&(h++,e.close())}),r.on("framenavigated",()=>{j&&h++}),r.on("download",()=>{h++}),r.on("pageerror",()=>{h++,J++}),r.on("console",e=>{e.type()==="error"&&(h++,H++)}),r.on("request",()=>{M++}),r.on("requestfailed",()=>{I++}),r.on("response",e=>{e.status()>=400&&(I++,h++)}),O=setTimeout(()=>{W=!0,n.close().catch(()=>{})},15e3),b="navigation";const z=await r.goto($.href,{waitUntil:"load",timeout:5e3});if(!z||z.status()>=400||r.url()!==$.href||l||h)throw new Error("qa-synthetic-backend-target-unavailable");j=!0;const f=()=>{if(l)throw new Error("qa-synthetic-backend-effects-denied-network");if(h)throw new Error("qa-synthetic-backend-effects-denied-page");if(W)throw new Error("qa-synthetic-backend-effects-denied-budget");if(r.url()!==$.href)throw new Error("qa-synthetic-backend-effects-denied-navigation")},C=async e=>{const t=r.locator(e);if(await t.count()!==1)throw new Error("qa-synthetic-backend-target-ambiguous");return t};b="scenario";for(const e of d.actions){const t=await C(e.selector);if(!await t.isVisible()||!await t.isEnabled())throw new Error("qa-synthetic-backend-action-unavailable");e.kind==="click"?await t.click({timeout:2e3}):e.kind==="fill"?await t.fill(e.value,{timeout:2e3}):e.kind==="select"?await t.selectOption(e.value,{timeout:2e3}):e.kind==="press"&&await t.press(e.key,{timeout:2e3}),f()}const A=[];for(const e of d.checks){const t=await C(e.selector),s=Date.now()+2e3;for(;f(),(e.kind==="text"?(await t.textContent({timeout:1e3}))?.trim():e.kind==="value"?await t.inputValue({timeout:1e3}):e.kind==="visible"?await t.isVisible():e.kind==="enabled"?await t.isEnabled():await t.isChecked({timeout:1e3}))!==e.expected;){if(Date.now()>=s)throw new Error("qa-synthetic-backend-check-failed");await r.waitForTimeout(25)}A.push({id:`functional-${e.id}`,passed:!0})}if(await r.waitForTimeout(250),f(),await Promise.allSettled([...p]),f(),await u.verify(),!k||!u.observations().length)throw new Error("qa-synthetic-backend-no-backend-observation");if(U(a.projectRoot,a.surface,a.targetUrl).planSha256!==y.planSha256)throw new Error("qa-synthetic-backend-source-drift");if(V(a.projectRoot,d)!==q)throw new Error("qa-synthetic-backend-source-drift");b="artifacts";const T=fe(a.projectRoot),Y=[],Q=new Date().toISOString(),m=(e,t,s,o,ie)=>{if(s.length<8||s.length>8*1024*1024)throw new Error("qa-synthetic-backend-artifact-limit");const se=re("sha256").update(s).digest("hex"),ae=`backend-${e}-${ce().replaceAll("-","").slice(0,20)}.${o}`,L=D(oe(T,ae),c.O_WRONLY|c.O_CREAT|c.O_EXCL|c.O_NOFOLLOW,384);try{ne(L,s),B(L)}finally{N(L)}Y.push({kind:e,artifactId:ae,sha256:se,captureMethod:t,capturedAt:Q,rationale:ie})},v=e=>Buffer.from(JSON.stringify(e));await r.addScriptTag({content:le.source});let X=0,Z=0,G=0;for(const[e,t,s]of[["visual",1440,900],["responsive",375,812],["responsive-tablet",768,1024],["responsive-desktop",1024,768]]){await r.setViewportSize({width:t,height:s}),f(),m(e,"browser-screenshot",await r.screenshot({type:"png",animations:"disabled",timeout:2e3}),"png",`Isolated network-namespace browser screenshot at ${t}x${s} after the source-bound synthetic scenario.`);const o=await r.evaluate("window.axe.run(document)");if(!o||!Array.isArray(o.violations)||!Array.isArray(o.incomplete)||!Array.isArray(o.passes))throw new Error("qa-synthetic-backend-accessibility-unavailable");X+=o.violations.length,Z+=o.incomplete.length,G+=o.passes.length,f()}m("accessibility","axe-scan",v({schemaVersion:1,engine:"axe-core",violationCount:X,incompleteCount:Z,passCount:G}),"json","Independent-review input: axe observations across all four declared viewport widths after the synthetic scenario.");const S=await r.evaluate("performance.getEntriesByType('navigation')[0]?.duration");if(typeof S!="number"||!Number.isFinite(S)||S<0)throw new Error("qa-synthetic-backend-performance-unavailable");if(m("performance","performance-trace",v({schemaVersion:1,metric:"load",observedMs:Math.ceil(S),budgetMs:1e4}),"json","Physical navigation load observation in the isolated browser with a predeclared ten-second load budget."),await Promise.allSettled([...p]),f(),await n.close(),await Promise.allSettled([...p]),f(),await u.verify(),m("interaction","browser-interaction",v({schemaVersion:3,syntheticTarget:!0,allowedActionRequests:k,deniedRequests:l,generation:a.generation,scenarioSha256:g,checks:A,backend:u.observations()}),"json","Source-bound synthetic backend interaction with exact declared transport and physical browser/backend observations."),m("console-network","console-capture",v({schemaVersion:1,initialCapture:!0,consoleErrors:H,pageErrors:J,failedRequests:I,requestsObserved:M}),"json","Console and request listeners were installed before navigation in a fresh network-isolated browser context."),U(a.projectRoot,a.surface,a.targetUrl).planSha256!==y.planSha256||V(a.projectRoot,d)!==q)throw new Error("qa-synthetic-backend-source-drift");const K={schemaVersion:3,kind:"root-qa-synthetic-backend-observation",sourceHead:y.sourceHead,planSha256:y.planSha256,surface:a.surface,targetSha256:y.targetSha256,generation:a.generation,scenarioSha256:g,backendContractSha256:u.contractSha256,requirementSourceSha256:q,requirementIds:d.requirementIds,capturedAt:Q,checks:A,scenario:d,grantId:a.grantId,evidenceCount:8,observations:Y,initialRequests:x,allowedActionRequests:k,deniedRequests:l,backend:u.observations(),sandboxNetwork:"none",browserNetwork:i?"docker-none":"unshared",browserHostWorkspaceMounted:!1,browserVersion:E.version(),...i?{producerJob:{imageId:i.imageId,containerId:i.containerId,jobBindingSha256:i.jobBindingSha256}}:{},qaAccepted:!1,checkpointAccepted:!1,workflowContinuationAuthorized:!1},P=JSON.stringify(K),ee=F(P),_=D(oe(T,`synthetic-backend-${ee}.json`),c.O_WRONLY|c.O_CREAT|c.O_EXCL|c.O_NOFOLLOW,384);try{ne(_,P),B(_)}finally{N(_)}const te=D(T,c.O_RDONLY|c.O_DIRECTORY|c.O_NOFOLLOW);try{B(te)}finally{N(te)}return{...K,observationSha256:ee}}catch(n){if(R)throw new Error(R);if(n instanceof Error&&/^qa-(synthetic-backend|scan-review)-[a-z-]+$/.test(n.message))throw n;if(n instanceof Error){const l=n.message.match(/net::(ERR_[A-Z_]+)/)?.[1];if(l)throw new Error(`qa-synthetic-backend-${b}-${l.toLowerCase().replaceAll("_","-")}`);if(/Target.*closed|browser has been closed/i.test(n.message))throw new Error(`qa-synthetic-backend-${b}-browser-closed`);if(/Timeout/i.test(n.message))throw new Error(`qa-synthetic-backend-${b}-timeout`)}throw new Error(`qa-synthetic-backend-${b}-unavailable`)}finally{O&&clearTimeout(O),await E.close().catch(()=>{})}}export{Se as captureSyntheticBackendScenario};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { captureSyntheticBackendScenario } from './qa-synthetic-backend-capture.js';
|
|
2
|
+
type Observation = Omit<Awaited<ReturnType<typeof captureSyntheticBackendScenario>>, 'observationSha256'>;
|
|
3
|
+
/** Source and all artifacts are recomputed; an arbitrary JSON/200 response is no proof. */
|
|
4
|
+
export declare function readSyntheticBackendObservation(root: string, surface: string, targetUrl: string, digest: string): {
|
|
5
|
+
receipt: Observation;
|
|
6
|
+
observationSha256: string;
|
|
7
|
+
rejectedKinds: ("performance" | "accessibility" | "responsive" | "visual" | "responsive-tablet" | "responsive-desktop" | "interaction" | "console-network")[];
|
|
8
|
+
};
|
|
9
|
+
export interface SyntheticBackendRootReport {
|
|
10
|
+
readonly schemaVersion: 3;
|
|
11
|
+
readonly kind: 'root-qa-synthetic-backend-report';
|
|
12
|
+
readonly observationSha256: string;
|
|
13
|
+
readonly verdict: 'approved' | 'issues-found';
|
|
14
|
+
readonly issues: readonly {
|
|
15
|
+
readonly severity: 'critical' | 'high' | 'medium' | 'low';
|
|
16
|
+
readonly evidenceArtifactId: string;
|
|
17
|
+
readonly summary: string;
|
|
18
|
+
}[];
|
|
19
|
+
}
|
|
20
|
+
export declare function acceptSyntheticBackendRootReview(options: {
|
|
21
|
+
readonly projectRoot: string;
|
|
22
|
+
readonly surface: string;
|
|
23
|
+
readonly targetUrl: string;
|
|
24
|
+
readonly report: unknown;
|
|
25
|
+
readonly authorizeRootReview: boolean;
|
|
26
|
+
}): {
|
|
27
|
+
schemaVersion: 3;
|
|
28
|
+
kind: "root-qa-synthetic-backend-review";
|
|
29
|
+
sourceHead: string;
|
|
30
|
+
planSha256: string;
|
|
31
|
+
observationSha256: string;
|
|
32
|
+
reviewSha256: string;
|
|
33
|
+
verdict: "approved" | "issues-found";
|
|
34
|
+
evidenceCount: 8;
|
|
35
|
+
issueCount: number;
|
|
36
|
+
qaAccepted: boolean;
|
|
37
|
+
checkpointAccepted: false;
|
|
38
|
+
workflowContinuationAuthorized: false;
|
|
39
|
+
};
|
|
40
|
+
export declare function readSyntheticBackendReviewedObservation(root: string, surface: string, targetUrl: string, observationSha256: string): {
|
|
41
|
+
report: SyntheticBackendRootReport;
|
|
42
|
+
receipt: {
|
|
43
|
+
schemaVersion: 3;
|
|
44
|
+
kind: "root-qa-synthetic-backend-review";
|
|
45
|
+
sourceHead: string;
|
|
46
|
+
planSha256: string;
|
|
47
|
+
observationSha256: string;
|
|
48
|
+
reviewSha256: string;
|
|
49
|
+
verdict: "approved" | "issues-found";
|
|
50
|
+
evidenceCount: 8;
|
|
51
|
+
issueCount: number;
|
|
52
|
+
qaAccepted: boolean;
|
|
53
|
+
checkpointAccepted: false;
|
|
54
|
+
workflowContinuationAuthorized: false;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export declare function readSyntheticBackendRootReview(root: string, surface: string, targetUrl: string, digest: string): {
|
|
58
|
+
report: SyntheticBackendRootReport;
|
|
59
|
+
receipt: {
|
|
60
|
+
schemaVersion: 3;
|
|
61
|
+
kind: "root-qa-synthetic-backend-review";
|
|
62
|
+
sourceHead: string;
|
|
63
|
+
planSha256: string;
|
|
64
|
+
observationSha256: string;
|
|
65
|
+
reviewSha256: string;
|
|
66
|
+
verdict: "approved" | "issues-found";
|
|
67
|
+
evidenceCount: 8;
|
|
68
|
+
issueCount: number;
|
|
69
|
+
qaAccepted: boolean;
|
|
70
|
+
checkpointAccepted: false;
|
|
71
|
+
workflowContinuationAuthorized: false;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
export interface SyntheticBackendPhaseTarget {
|
|
75
|
+
readonly surface: string;
|
|
76
|
+
readonly targetUrl: string;
|
|
77
|
+
readonly observationSha256: string;
|
|
78
|
+
readonly reviewSha256: string;
|
|
79
|
+
}
|
|
80
|
+
export declare function acceptSyntheticBackendDiscoveredPhase(root: string, discoverySha256: string, targets: readonly SyntheticBackendPhaseTarget[]): {
|
|
81
|
+
schemaVersion: 3;
|
|
82
|
+
kind: "root-qa-synthetic-backend-discovered-phase";
|
|
83
|
+
sourceHead: string;
|
|
84
|
+
discoverySha256: string;
|
|
85
|
+
aggregateSha256: string;
|
|
86
|
+
surfaceCount: number;
|
|
87
|
+
qaAccepted: boolean;
|
|
88
|
+
issueCount: number;
|
|
89
|
+
workflowContinuationAuthorized: false;
|
|
90
|
+
checkpointAccepted: false;
|
|
91
|
+
};
|
|
92
|
+
export declare function readSyntheticBackendDiscoveredPhase(root: string, discoverySha256: string, targets: readonly SyntheticBackendPhaseTarget[]): {
|
|
93
|
+
schemaVersion: 3;
|
|
94
|
+
kind: "root-qa-synthetic-backend-discovered-phase";
|
|
95
|
+
sourceHead: string;
|
|
96
|
+
discoverySha256: string;
|
|
97
|
+
aggregateSha256: string;
|
|
98
|
+
surfaceCount: number;
|
|
99
|
+
qaAccepted: boolean;
|
|
100
|
+
issueCount: number;
|
|
101
|
+
workflowContinuationAuthorized: false;
|
|
102
|
+
checkpointAccepted: false;
|
|
103
|
+
};
|
|
104
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as B}from"node:crypto";import{closeSync as v,constants as l,fstatSync as R,fsyncSync as I,openSync as w,readFileSync as C,writeFileSync as $}from"node:fs";import{join as q}from"node:path";import{planRootQaScan as j,rootQaScanEvidenceDirectory as J,validateRootQaScanArtifact as M}from"./qa-scan-review.js";import{validateRootQaScanScenario as z,scenarioRequirementDigest as L}from"./qa-scan-capture.js";import{validateSyntheticBackendContract as _}from"./qa-synthetic-backend.js";import{readRootQaScanDiscovery as E,readRootQaScanDiscoveryTargets as F}from"./qa-scan-discovery.js";const p=/^[a-f0-9]{64}$/,x=["visual","responsive","responsive-tablet","responsive-desktop","accessibility","interaction","console-network","performance"],T={visual:"browser-screenshot",responsive:"browser-screenshot","responsive-tablet":"browser-screenshot","responsive-desktop":"browser-screenshot",accessibility:"axe-scan",interaction:"browser-interaction","console-network":"console-capture",performance:"performance-trace"},m=t=>B("sha256").update(t).digest("hex");function s(){throw new Error("qa-synthetic-backend-review-unverified")}function h(t,i){return!!t&&typeof t=="object"&&!Array.isArray(t)&&Object.keys(t).sort().join(",")===[...i].sort().join(",")}function g(t,i,o){const n=w(q(J(t),i),l.O_RDONLY|l.O_NOFOLLOW);try{const a=R(n);(!a.isFile()||a.nlink!==1||a.uid!==process.getuid?.()||a.mode&63||a.size<1||a.size>o)&&s();const d=C(n),e=R(n);return(d.length!==a.size||e.size!==a.size||e.mtimeMs!==a.mtimeMs||e.ctimeMs!==a.ctimeMs)&&s(),d}finally{v(n)}}function y(t){const i=new TextDecoder("utf-8",{fatal:!0}).decode(t),o=JSON.parse(i);return(!o||typeof o!="object"||Array.isArray(o)||JSON.stringify(o)!==i)&&s(),o}function A(t,i,o){const n=J(t);let a;try{a=w(q(n,i),l.O_WRONLY|l.O_CREAT|l.O_EXCL|l.O_NOFOLLOW,384)}catch(e){(e.code!=="EEXIST"||g(t,i,131072).toString("utf8")!==o)&&s();return}try{$(a,o),I(a)}finally{v(a)}const d=w(n,l.O_RDONLY|l.O_DIRECTORY|l.O_NOFOLLOW);try{I(d)}finally{v(d)}}function W(t,i,o,n){try{p.test(n)||s();const a=j(t,i,o),d=g(t,`synthetic-backend-${n}.json`,131072);m(d)!==n&&s();const e=y(d);if((!h(e,["schemaVersion","kind","sourceHead","planSha256","surface","targetSha256","generation","scenarioSha256","backendContractSha256","requirementSourceSha256","requirementIds","capturedAt","checks","scenario","grantId","evidenceCount","observations","initialRequests","allowedActionRequests","deniedRequests","backend","sandboxNetwork","browserNetwork","browserHostWorkspaceMounted","browserVersion","qaAccepted","checkpointAccepted","workflowContinuationAuthorized",..."producerJob"in e?["producerJob"]:[]])||e.schemaVersion!==3||e.kind!=="root-qa-synthetic-backend-observation"||e.sourceHead!==a.sourceHead||e.planSha256!==a.planSha256||e.surface!==i||e.targetSha256!==a.targetSha256||typeof e.generation!="string"||!p.test(e.generation)||typeof e.scenarioSha256!="string"||!p.test(e.scenarioSha256)||typeof e.grantId!="string"||!/^[a-f0-9]{8}-[a-f0-9-]{27}$/.test(e.grantId)||typeof e.capturedAt!="string"||!Number.isFinite(Date.parse(e.capturedAt))||new Date(e.capturedAt).toISOString()!==e.capturedAt||Date.parse(e.capturedAt)>Date.now()||Date.now()-Date.parse(e.capturedAt)>36e5||e.evidenceCount!==8||!Array.isArray(e.observations)||e.observations.length!==8||e.sandboxNetwork!=="none"||!["unshared","docker-none"].includes(String(e.browserNetwork))||e.browserHostWorkspaceMounted!==!1||typeof e.browserVersion!="string"||!/^[0-9]+(?:\.[0-9]+){2,3}$/.test(e.browserVersion)||!Number.isSafeInteger(e.allowedActionRequests)||Number(e.allowedActionRequests)<1||Number(e.allowedActionRequests)>64||!Number.isSafeInteger(e.initialRequests)||Number(e.initialRequests)<1||Number(e.initialRequests)>64||e.deniedRequests!==0||e.qaAccepted!==!1||e.checkpointAccepted!==!1||e.workflowContinuationAuthorized!==!1)&&s(),e.browserNetwork==="docker-none"){const r=e.producerJob;(!h(r,["imageId","containerId","jobBindingSha256"])||typeof r.imageId!="string"||!/^sha256:[a-f0-9]{64}$/.test(r.imageId)||typeof r.containerId!="string"||!p.test(r.containerId)||typeof r.jobBindingSha256!="string"||!p.test(r.jobBindingSha256))&&s();const f=y(g(t,`producer-job-${r.jobBindingSha256}-${r.containerId}.json`,4096));(!h(f,["schemaVersion","kind","containerId","imageId","jobBindingSha256","sourceHead","requestSha256","phase","bindingSha256","network","producerDockerSocketMounted","createdVerified","completedVerified"])||f.schemaVersion!==1||f.kind!=="root-synthetic-producer-job-attestation"||f.containerId!==r.containerId||f.imageId!==r.imageId||f.jobBindingSha256!==r.jobBindingSha256||f.sourceHead!==a.sourceHead||typeof f.requestSha256!="string"||!p.test(f.requestSha256)||typeof f.bindingSha256!="string"||!p.test(f.bindingSha256)||f.phase!=="completed"||f.network!=="none"||f.producerDockerSocketMounted!==!1||f.createdVerified!==!0||f.completedVerified!==!0)&&s()}else"producerJob"in e&&s();const c=z(e.scenario);(m(JSON.stringify(c))!==e.scenarioSha256||L(t,c)!==e.requirementSourceSha256||JSON.stringify(c.requirementIds)!==JSON.stringify(e.requirementIds)||JSON.stringify(e.checks)!==JSON.stringify(c.checks.map(r=>({id:`functional-${r.id}`,passed:!0}))))&&s();const u=y(g(t,`backend-grant-${e.grantId}.json`,32768));(!h(u,["schemaVersion","contract","planSha256","sourceHead","surface","targetUrl","expiresAt"])||u.schemaVersion!==1||u.planSha256!==a.planSha256||u.sourceHead!==a.sourceHead||u.surface!==i||u.targetUrl!==o||typeof u.expiresAt!="string"||!Number.isFinite(Date.parse(u.expiresAt)))&&s();const b=_(u.contract);(b.generation!==e.generation||b.scenarioSha256!==e.scenarioSha256||m(JSON.stringify(b))!==e.backendContractSha256||Date.parse(e.capturedAt)>Date.parse(u.expiresAt)||Date.parse(e.capturedAt)<Date.parse(u.expiresAt)-b.durationMs||g(t,`backend-consumed-${e.grantId}`,16).toString("utf8")!=="consumed")&&s(),(!Array.isArray(e.backend)||e.backend.length<2||e.backend.length>b.maxRequests)&&s();for(const r of e.backend)(!h(r,["path","method","status","responseSha256"])||!b.routes.some(f=>f.path===r.path&&f.method===r.method)||!Number.isSafeInteger(r.status)||Number(r.status)<200||Number(r.status)>599||Number(r.status)>=300&&Number(r.status)<400||typeof r.responseSha256!="string"||!p.test(r.responseSha256))&&s();Number(e.allowedActionRequests)+Number(e.initialRequests)!==e.backend.length&&s();const k=new Map,O=new Set;for(const r of e.observations){(!h(r,["kind","artifactId","sha256","captureMethod","capturedAt","rationale"])||!x.includes(r.kind)||k.has(r.kind)||typeof r.artifactId!="string"||!/^[a-z][a-z0-9-]{0,63}\.(?:png|json)$/.test(r.artifactId)||O.has(r.artifactId)||r.captureMethod!==T[r.kind]||typeof r.sha256!="string"||!p.test(r.sha256)||r.capturedAt!==e.capturedAt||typeof r.rationale!="string"||r.rationale.length<30||r.rationale.length>500||/[\x00-\x1f\x7f]/.test(r.rationale))&&s();const f=g(t,r.artifactId,8*1024*1024);(m(f)!==r.sha256||r.captureMethod==="browser-screenshot"!==r.artifactId.endsWith(".png"))&&s(),O.add(r.artifactId),k.set(r.kind,f)}const S=y(k.get("interaction"));(!h(S,["schemaVersion","syntheticTarget","allowedActionRequests","deniedRequests","generation","scenarioSha256","checks","backend"])||S.schemaVersion!==3||S.syntheticTarget!==!0||S.allowedActionRequests!==e.allowedActionRequests||S.deniedRequests!==0||S.generation!==e.generation||S.scenarioSha256!==e.scenarioSha256||JSON.stringify(S.checks)!==JSON.stringify(e.checks)||JSON.stringify(S.backend)!==JSON.stringify(e.backend))&&s(),j(t,i,o).planSha256!==a.planSha256&&s();const V=x.filter(r=>r!=="interaction"&&!M(r,k.get(r)));return{receipt:e,observationSha256:n,rejectedKinds:V}}catch{return s()}}function N(t,i,o,n){(!h(n,["schemaVersion","kind","observationSha256","verdict","issues"])||n.schemaVersion!==3||n.kind!=="root-qa-synthetic-backend-report"||typeof n.observationSha256!="string"||!["approved","issues-found"].includes(String(n.verdict))||!Array.isArray(n.issues)||n.issues.length>128)&&s();const a=W(t,i,o,n.observationSha256);(n.verdict==="approved"&&(n.issues.length||a.rejectedKinds.length)||n.verdict==="issues-found"&&!n.issues.length)&&s();const d=new Set(a.receipt.observations.map(c=>c.artifactId));for(const c of n.issues)(!h(c,["severity","evidenceArtifactId","summary"])||!["critical","high","medium","low"].includes(String(c.severity))||!d.has(String(c.evidenceArtifactId))||typeof c.summary!="string"||c.summary.length<20||c.summary.length>500||/[\x00-\x1f\x7f]/.test(c.summary))&&s();const e=n;return{report:e,receipt:{schemaVersion:3,kind:"root-qa-synthetic-backend-review",sourceHead:a.receipt.sourceHead,planSha256:a.receipt.planSha256,observationSha256:a.observationSha256,reviewSha256:m(JSON.stringify(e)),verdict:e.verdict,evidenceCount:8,issueCount:e.issues.length,qaAccepted:e.verdict==="approved",checkpointAccepted:!1,workflowContinuationAuthorized:!1}}}function ee(t){try{t.authorizeRootReview!==!0&&s();const i=N(t.projectRoot,t.surface,t.targetUrl,t.report),o=JSON.stringify(i);A(t.projectRoot,`backend-review-${i.receipt.reviewSha256}.json`,o),JSON.stringify(N(t.projectRoot,t.surface,t.targetUrl,i.report))!==o&&s();const n=JSON.stringify({observationSha256:i.receipt.observationSha256,reviewSha256:i.receipt.reviewSha256});return A(t.projectRoot,`backend-reviewed-${i.receipt.observationSha256}.json`,n),i.receipt}catch{return s()}}function te(t,i,o,n){try{p.test(n)||s();const a=y(g(t,`backend-reviewed-${n}.json`,4096));(!h(a,["observationSha256","reviewSha256"])||a.observationSha256!==n||typeof a.reviewSha256!="string")&&s();const d=D(t,i,o,a.reviewSha256);return d.receipt.observationSha256!==n&&s(),d}catch{return s()}}function D(t,i,o,n){try{p.test(n)||s();const a=y(g(t,`backend-review-${n}.json`,131072));h(a,["report","receipt"])||s();const d=N(t,i,o,a.report);return(d.receipt.reviewSha256!==n||JSON.stringify(d.receipt)!==JSON.stringify(a.receipt))&&s(),d}catch{return s()}}function H(t,i,o){(!Array.isArray(o)||!o.length||o.length>32)&&s();const n=E(t,i),a=F(t,i),d=new Set,e=o.map(c=>{(!h(c,["surface","targetUrl","observationSha256","reviewSha256"])||typeof c.surface!="string"||d.has(c.surface)||typeof c.targetUrl!="string"||typeof c.observationSha256!="string"||typeof c.reviewSha256!="string")&&s(),d.add(c.surface);const u=D(t,c.surface,c.targetUrl,c.reviewSha256);return(u.receipt.sourceHead!==n.sourceHead||u.receipt.observationSha256!==c.observationSha256)&&s(),u.receipt});return JSON.stringify(o.map(c=>c.targetUrl).sort((c,u)=>Buffer.from(c).compare(Buffer.from(u))))!==JSON.stringify(a)&&s(),{schemaVersion:3,kind:"root-qa-synthetic-backend-discovered-phase",sourceHead:n.sourceHead,discoverySha256:i,aggregateSha256:m(JSON.stringify({discoverySha256:i,targets:o,receipts:e})),surfaceCount:o.length,qaAccepted:e.every(c=>c.qaAccepted),issueCount:e.reduce((c,u)=>c+u.issueCount,0),workflowContinuationAuthorized:!1,checkpointAccepted:!1}}function re(t,i,o){try{const n=H(t,i,o),a=JSON.stringify(n),d=`backend-phase-${n.aggregateSha256}.json`;return A(t,d,a),Q(t,i,o)}catch{return s()}}function Q(t,i,o){try{const n=H(t,i,o),a=y(g(t,`backend-phase-${n.aggregateSha256}.json`,4096));return JSON.stringify(a)!==JSON.stringify(n)&&s(),n}catch{return s()}}export{re as acceptSyntheticBackendDiscoveredPhase,ee as acceptSyntheticBackendRootReview,Q as readSyntheticBackendDiscoveredPhase,W as readSyntheticBackendObservation,te as readSyntheticBackendReviewedObservation,D as readSyntheticBackendRootReview};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface SyntheticBackendContract {
|
|
2
|
+
readonly generation: string;
|
|
3
|
+
readonly scenarioSha256: string;
|
|
4
|
+
readonly containerId: string;
|
|
5
|
+
readonly imageId: string;
|
|
6
|
+
readonly programSha256: string;
|
|
7
|
+
readonly port: number;
|
|
8
|
+
readonly routes: readonly {
|
|
9
|
+
readonly path: string;
|
|
10
|
+
readonly method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
11
|
+
readonly fields: Readonly<Record<string, readonly string[]>>;
|
|
12
|
+
}[];
|
|
13
|
+
readonly maxRequests: number;
|
|
14
|
+
readonly maxBodyBytes: number;
|
|
15
|
+
readonly maxResponseBytes: number;
|
|
16
|
+
readonly durationMs: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function validateSyntheticBackendContract(v: unknown): SyntheticBackendContract;
|
|
19
|
+
export declare function verifySyntheticBackendSandbox(contract: SyntheticBackendContract): Promise<void>;
|
|
20
|
+
/** Separate SDK command. Registration requires explicit root consent; capture
|
|
21
|
+
* consumes that source-bound grant and cannot emit a QA/checkpoint approval. */
|
|
22
|
+
export declare function syntheticBackendCliHandler(args: readonly string[]): Promise<number>;
|
|
23
|
+
/** Host operator consent is required; no DOM marker or scenario JSON grants network. */
|
|
24
|
+
export declare function registerSyntheticBackendGrant(options: {
|
|
25
|
+
readonly projectRoot: string;
|
|
26
|
+
readonly surface: string;
|
|
27
|
+
readonly targetUrl: string;
|
|
28
|
+
readonly contract: SyntheticBackendContract;
|
|
29
|
+
readonly authorizeSyntheticBackend: boolean;
|
|
30
|
+
}): Promise<string>;
|
|
31
|
+
export declare function openSyntheticBackendSession(options: {
|
|
32
|
+
readonly projectRoot: string;
|
|
33
|
+
readonly surface: string;
|
|
34
|
+
readonly targetUrl: string;
|
|
35
|
+
readonly grantId: string;
|
|
36
|
+
readonly scenarioSha256: string;
|
|
37
|
+
readonly generation: string;
|
|
38
|
+
}): Promise<{
|
|
39
|
+
request: (url: string, method: string, body: string | null, headers: Readonly<Record<string, string>>) => Promise<{
|
|
40
|
+
status: number;
|
|
41
|
+
body: Buffer;
|
|
42
|
+
contentType: string;
|
|
43
|
+
}>;
|
|
44
|
+
verify: () => Promise<void>;
|
|
45
|
+
contractSha256: string;
|
|
46
|
+
observations: () => readonly {
|
|
47
|
+
path: string;
|
|
48
|
+
method: string;
|
|
49
|
+
status: number;
|
|
50
|
+
responseSha256: string;
|
|
51
|
+
}[];
|
|
52
|
+
}>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{spawn as F}from"node:child_process";import{createHash as H,randomUUID as P}from"node:crypto";import{closeSync as b,constants as u,fstatSync as j,fsyncSync as q,openSync as w,readFileSync as D,writeFileSync as T}from"node:fs";import{join as A}from"node:path";import{planRootQaScan as z,rootQaScanEvidenceDirectory as C}from"./qa-scan-review.js";const B=/^[a-f0-9]{64}$/,I=e=>H("sha256").update(e).digest("hex");function s(e){throw new Error(`qa-synthetic-backend-${e}`)}const k=(e,r)=>!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).sort().join(",")===[...r].sort().join(","),R=(e,r)=>Number.isSafeInteger(e)&&Number(e)>0&&Number(e)<=r;function _(e){(!k(e,["generation","scenarioSha256","containerId","imageId","programSha256","port","routes","maxRequests","maxBodyBytes","maxResponseBytes","durationMs"])||typeof e.generation!="string"||!B.test(e.generation)||typeof e.scenarioSha256!="string"||!B.test(e.scenarioSha256)||typeof e.containerId!="string"||!B.test(e.containerId)||typeof e.imageId!="string"||!/^sha256:[a-f0-9]{64}$/.test(e.imageId)||typeof e.programSha256!="string"||!B.test(e.programSha256)||!R(e.port,65535)||!R(e.maxRequests,64)||!R(e.maxBodyBytes,16384)||!R(e.maxResponseBytes,1048576)||!R(e.durationMs,3e4)||!Array.isArray(e.routes)||!e.routes.length||e.routes.length>32)&&s("contract-invalid");const r=new Set;for(const t of e.routes){(!k(t,["path","method","fields"])||typeof t.path!="string"||!/^\/[a-zA-Z0-9/_-]*$/.test(t.path)||t.path.length>256||!["GET","POST","PUT","DELETE"].includes(String(t.method))||!t.fields||typeof t.fields!="object"||Array.isArray(t.fields)||Object.keys(t.fields).length>16||t.method==="GET"&&Object.keys(t.fields).length)&&s("contract-invalid");for(const[a,i]of Object.entries(t.fields))(!/^[a-z][a-z0-9_]{0,31}$/.test(a)||["constructor","prototype","__proto__"].includes(a)||!Array.isArray(i)||!i.length||i.length>32||i.some(d=>typeof d!="string"||d.length>256||/[\x00-\x1f\x7f]/.test(d)))&&s("contract-invalid");const n=`${t.method} ${t.path}`;r.has(n)&&s("contract-invalid"),r.add(n)}return Buffer.byteLength(JSON.stringify(e))>24576&&s("contract-invalid"),JSON.parse(JSON.stringify(e))}async function J(e,r="",t=131072,n=5e3){return new Promise((a,i)=>{if(process.platform!=="linux"){i(new Error("qa-synthetic-backend-host-unsupported"));return}const d=F("docker",["--host","unix:///var/run/docker.sock",...e],{stdio:["pipe","pipe","pipe"]}),p=[];let g=0,S=!1;const f=c=>{S||(S=!0,clearTimeout(o),c?(d.kill("SIGKILL"),i(c)):a(Buffer.concat(p).toString("utf8")))},o=setTimeout(()=>f(new Error("qa-synthetic-backend-transport-timeout")),n);d.stdout.on("data",c=>{g+=c.length,g>t?f(new Error("qa-synthetic-backend-response-limit")):p.push(c)}),d.stderr.resume(),d.on("error",()=>f(new Error("qa-synthetic-backend-transport-unavailable"))),d.stdin.on("error",()=>f(new Error("qa-synthetic-backend-transport-unavailable"))),d.on("close",c=>f(c===0?void 0:new Error("qa-synthetic-backend-transport-failed"))),d.stdin.end(r)})}async function N(e){let r;try{const a=JSON.parse(await J(["inspect",e.containerId]));(!Array.isArray(a)||a.length!==1)&&s("sandbox-unverified"),r=a[0]}catch{return s("sandbox-unverified")}const t=r.HostConfig,n=r.Config;(r.Id!==e.containerId||r.Image!==e.imageId||!r.State?.Running||!t||!n||t.NetworkMode!=="none"||t.Privileged!==!1||t.ReadonlyRootfs!==!0||!Array.isArray(t.CapDrop)||!t.CapDrop.includes("ALL")||(t.CapAdd?.length??0)!==0||!t.SecurityOpt?.includes("no-new-privileges")||!/^[1-9][0-9]*(?::[1-9][0-9]*)?$/.test(n.User)||(r.Mounts?.length??0)!==0||Object.keys(t.PortBindings??{}).length!==0||t.PublishAllPorts||t.PidMode||t.IpcMode!=="private"||t.Devices?.length||t.Binds?.length||t.VolumesFrom?.length||t.ExtraHosts?.length||t.Memory<=0||t.Memory>512*1024*1024||t.PidsLimit<=0||t.PidsLimit>128||t.NanoCpus<=0||t.NanoCpus>1e9||t.DeviceRequests?.length||t.SecurityOpt.length!==1||t.UsernsMode==="host"||t.CgroupnsMode==="host"||Object.keys(t.Tmpfs??{}).some(a=>a!=="/tmp")||n.Labels?.["neocortex.qa.synthetic-generation"]!==e.generation||!Array.isArray(n.Cmd)||!n.Cmd.every(a=>typeof a=="string")||n.Entrypoint!==null&&(!Array.isArray(n.Entrypoint)||!n.Entrypoint.every(a=>typeof a=="string"))||I(JSON.stringify({entrypoint:n.Entrypoint,command:n.Cmd}))!==e.programSha256||(n.Env??[]).some(a=>!/^(PATH|NODE_VERSION|YARN_VERSION|HOME)=/.test(a)))&&s("sandbox-unverified")}async function Z(e){try{const r=e[0];let t=process.cwd(),n="",a="",i=!1,d=!1;const p=new Set;["register","capture","accept","status","observation"].includes(String(r))||s("action-invalid");for(let c=1;c<e.length;c++){const l=e[c];if(p.has(l)&&s("argument-invalid"),p.add(l),l==="--authorize-synthetic-backend")i=!0;else if(l==="--authorize-root-review")d=!0;else{const O=e[++c];(!O||O.startsWith("--"))&&s("argument-invalid"),l==="--project-root"?t=O:l==="--surface"?n=O:l==="--target-url"?a=O:s("argument-invalid")}}(!n||!a||i!==(r==="register")||d!==(r==="accept"))&&s("operator-approval-required");let g="";for await(const c of process.stdin)g+=String(c),Buffer.byteLength(g)>32768&&s("input-limit");const{parseDocument:S}=await import("yaml"),f=S(g,{strict:!0,uniqueKeys:!0,schema:"core",customTags:[]});(f.errors.length||f.warnings.length)&&s("input-invalid");const o=JSON.parse(g);if(r==="register"){const c=await W({projectRoot:t,surface:n,targetUrl:a,contract:_(o),authorizeSyntheticBackend:i});console.log(JSON.stringify({schemaVersion:1,grantId:c,qaAccepted:!1,checkpointAccepted:!1}))}else if(r==="capture"){(!k(o,["scenario","generation","grantId"])||typeof o.generation!="string"||typeof o.grantId!="string")&&s("input-invalid");const{captureSyntheticBackendScenario:c}=await import("./qa-synthetic-backend-capture.js");console.log(JSON.stringify(await c({projectRoot:t,surface:n,targetUrl:a,scenario:o.scenario,generation:o.generation,grantId:o.grantId})))}else{const c=await import("./qa-synthetic-backend-review.js");if(r==="accept"){const l=c.acceptSyntheticBackendRootReview({projectRoot:t,surface:n,targetUrl:a,report:o,authorizeRootReview:d});return console.log(JSON.stringify(l)),l.qaAccepted?0:2}if((!k(o,["sha256"])||typeof o.sha256!="string")&&s("input-invalid"),r==="observation")console.log(JSON.stringify(c.readSyntheticBackendObservation(t,n,a,o.sha256)));else{const l=c.readSyntheticBackendRootReview(t,n,a,o.sha256);return console.log(JSON.stringify(l.receipt)),l.receipt.qaAccepted?0:2}}return 0}catch(r){const t=r instanceof Error&&/^qa-(synthetic-backend|scan-review)-[a-z-]+$/.test(r.message)?r.message:"qa-synthetic-backend-unavailable";return console.error(t),1}}async function W(e){e.authorizeSyntheticBackend!==!0&&s("operator-approval-required");const r=_(e.contract),t=z(e.projectRoot,e.surface,e.targetUrl);await N(r);const n={schemaVersion:1,contract:r,planSha256:t.planSha256,sourceHead:t.sourceHead,surface:e.surface,targetUrl:e.targetUrl,expiresAt:new Date(Date.now()+r.durationMs).toISOString()},a=P(),i=C(e.projectRoot),d=w(A(i,`backend-grant-${a}.json`),u.O_WRONLY|u.O_CREAT|u.O_EXCL|u.O_NOFOLLOW,384);try{T(d,JSON.stringify(n)),q(d)}finally{b(d)}const p=w(i,u.O_RDONLY|u.O_DIRECTORY|u.O_NOFOLLOW);try{q(p)}finally{b(p)}return a}const Y=`let input='';for await(const b of process.stdin)input+=b;
|
|
2
|
+
const q=JSON.parse(input); const r=await fetch('http://127.0.0.1:'+q.port+q.path,{method:q.method,
|
|
3
|
+
headers:q.body===null?{}:{'content-type':'application/json'},body:q.body===null?undefined:q.body,
|
|
4
|
+
redirect:'manual',signal:AbortSignal.timeout(q.timeout)});
|
|
5
|
+
if(r.status>=300&&r.status<400||r.headers.has('set-cookie'))process.exit(3);
|
|
6
|
+
let size=0;const parts=[];for await(const b of r.body){size+=b.length;if(size>q.maxResponseBytes)process.exit(4);parts.push(Buffer.from(b));}
|
|
7
|
+
process.stdout.write(JSON.stringify({status:r.status,body:Buffer.concat(parts).toString('base64'),contentType:r.headers.get('content-type')||'application/octet-stream'}));`;async function ee(e){/^[a-f0-9-]{36}$/.test(e.grantId)||s("grant-invalid");const r=C(e.projectRoot),t=w(A(r,`backend-grant-${e.grantId}.json`),u.O_RDONLY|u.O_NOFOLLOW);let n,a;try{const o=j(t);(!o.isFile()||o.nlink!==1||o.uid!==process.getuid?.()||o.mode&63||o.size<1||o.size>32768)&&s("grant-invalid"),a=D(t,"utf8"),n=JSON.parse(a),k(n,["schemaVersion","contract","planSha256","sourceHead","surface","targetUrl","expiresAt"])||s("grant-invalid")}finally{b(t)}const i=_(n.contract),d=()=>{const o=w(A(r,`backend-grant-${e.grantId}.json`),u.O_RDONLY|u.O_NOFOLLOW);try{const l=j(o);(!l.isFile()||l.nlink!==1||l.uid!==process.getuid?.()||l.mode&63||l.size!==Buffer.byteLength(a)||D(o,"utf8")!==a)&&s("grant-stale")}finally{b(o)}const c=z(e.projectRoot,e.surface,e.targetUrl);(n.schemaVersion!==1||n.surface!==e.surface||n.targetUrl!==e.targetUrl||n.planSha256!==c.planSha256||n.sourceHead!==c.sourceHead||i.scenarioSha256!==e.scenarioSha256||i.generation!==e.generation||!Number.isFinite(Date.parse(n.expiresAt))||Date.parse(n.expiresAt)<=Date.now())&&s("grant-stale")};d(),await N(i);const p=w(A(r,`backend-consumed-${e.grantId}`),u.O_WRONLY|u.O_CREAT|u.O_EXCL|u.O_NOFOLLOW,384);try{T(p,"consumed"),q(p)}finally{b(p)}const g=w(r,u.O_RDONLY|u.O_DIRECTORY|u.O_NOFOLLOW);try{q(g)}finally{b(g)}let S=0;const f=[];return{contractSha256:I(JSON.stringify(i)),verify:async()=>{d(),await N(i),d()},observations:()=>f.map(o=>({...o})),request:async(o,c,l,O)=>{d();const U=new URL(e.targetUrl),h=new URL(o);(h.origin!==U.origin||h.username||h.password||h.hash||h.search||Object.keys(O).some(m=>/^(authorization|proxy-authorization|cookie)$/i.test(m)))&&s("request-denied");const x=i.routes.find(m=>m.path===h.pathname&&m.method===c);if((!x||++S>i.maxRequests)&&s("request-denied"),Object.keys(x.fields).length){(l===null||Buffer.byteLength(l)>i.maxBodyBytes)&&s("request-denied");let m;try{m=JSON.parse(l)}catch{return s("request-denied")}(!k(m,Object.keys(x.fields))||Object.entries(m).some(([M,v])=>typeof v!="string"||!x.fields[M].includes(v)))&&s("request-denied")}else l!==null&&l!==""&&s("request-denied");await N(i),d();const L=Math.min(5e3,Date.parse(n.expiresAt)-Date.now());L<1&&s("grant-stale");const $=await J(["exec","-i",i.containerId,"node","--input-type=module","-e",Y],JSON.stringify({port:i.port,path:h.pathname,method:c,body:l,maxResponseBytes:i.maxResponseBytes,timeout:L}),Math.ceil(i.maxResponseBytes*4/3)+1024,L+250);d(),await N(i);const y=JSON.parse($),E=Buffer.from(y.body,"base64");return(!R(y.status,599)||y.status<200||y.status>=300&&y.status<400||E.length>i.maxResponseBytes||typeof y.contentType!="string"||y.contentType.length>128||/[\r\n]/.test(y.contentType))&&s("response-denied"),f.push({path:h.pathname,method:c,status:y.status,responseSha256:I(E.toString("base64"))}),{status:y.status,body:E,contentType:y.contentType}}}}export{ee as openSyntheticBackendSession,W as registerSyntheticBackendGrant,Z as syntheticBackendCliHandler,_ as validateSyntheticBackendContract,N as verifySyntheticBackendSandbox};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface SyntheticBrokerPortConfiguration {
|
|
2
|
+
readonly projectRoot: string;
|
|
3
|
+
readonly surface: string;
|
|
4
|
+
readonly targetUrl: string;
|
|
5
|
+
readonly sourceHead: string;
|
|
6
|
+
readonly generation: string;
|
|
7
|
+
readonly scenarioSha256: string;
|
|
8
|
+
readonly grantId: string;
|
|
9
|
+
readonly contractSha256: string;
|
|
10
|
+
readonly socketPath: string;
|
|
11
|
+
readonly expiresAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SyntheticBackendCapturePort {
|
|
14
|
+
readonly contractSha256: string;
|
|
15
|
+
readonly scopeSha256: string;
|
|
16
|
+
readonly request: (url: string, method: string, body: string | null, headers: Readonly<Record<string, string>>) => Promise<{
|
|
17
|
+
status: number;
|
|
18
|
+
body: Buffer;
|
|
19
|
+
contentType: string;
|
|
20
|
+
}>;
|
|
21
|
+
readonly verify: () => Promise<void>;
|
|
22
|
+
readonly observations: () => readonly {
|
|
23
|
+
path: string;
|
|
24
|
+
method: string;
|
|
25
|
+
status: number;
|
|
26
|
+
responseSha256: string;
|
|
27
|
+
}[];
|
|
28
|
+
}
|
|
29
|
+
/** Trusted worker composition only. Public capture CLI never accepts a port. */
|
|
30
|
+
export declare function createSyntheticBrokerPort(value: SyntheticBrokerPortConfiguration): SyntheticBackendCapturePort;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as D}from"node:crypto";import{request as M}from"node:http";import{lstatSync as m,realpathSync as U}from"node:fs";import{dirname as z,isAbsolute as O}from"node:path";import{planRootQaScan as T}from"./qa-scan-review.js";function s(e="unverified"){throw new Error(`qa-synthetic-backend-broker-port-${e}`)}function N(e){(!e||Object.keys(e).sort().join(",")!=="contractSha256,expiresAt,generation,grantId,projectRoot,scenarioSha256,socketPath,sourceHead,surface,targetUrl"||!/^[a-f0-9]{64}$/.test(e.contractSha256)||!/^[a-f0-9]{64}$/.test(e.generation)||!/^[a-f0-9]{64}$/.test(e.scenarioSha256)||!/^[a-f0-9-]{36}$/.test(e.grantId)||!O(e.socketPath)||Buffer.byteLength(e.socketPath)>100||!Number.isFinite(Date.parse(e.expiresAt))||Date.parse(e.expiresAt)>Date.now()+3e4)&&s();const t=Object.freeze({...e}),i=z(t.socketPath),b=m(i),c=m(t.socketPath),A=new URL(t.targetUrl),$=performance.now()+Math.max(0,Date.parse(t.expiresAt)-Date.now()),h=()=>{const a=m(i),r=m(t.socketPath);(Date.now()>=Date.parse(t.expiresAt)||performance.now()>=$)&&s("expired"),(U(i)!==i||!a.isDirectory()||a.isSymbolicLink()||a.uid!==process.getuid?.()||(a.mode&511)!==448||a.dev!==b.dev||a.ino!==b.ino||!r.isSocket()||r.isSymbolicLink()||r.uid!==process.getuid?.()||(r.mode&511)!==384||r.dev!==c.dev||r.ino!==c.ino||r.ctimeMs!==c.ctimeMs||r.mtimeMs!==c.mtimeMs)&&s("custody"),T(t.projectRoot,t.surface,t.targetUrl).sourceHead!==t.sourceHead&&s("source")};h();let q=0;const S=[],E=D("sha256").update(JSON.stringify([t.sourceHead,t.surface,t.targetUrl,t.generation,t.scenarioSha256,t.grantId])).digest("hex");return Object.freeze({contractSha256:t.contractSha256,scopeSha256:E,verify:async()=>h(),observations:()=>S.map(a=>({...a})),request:async(a,r,d,L)=>{h();const n=new URL(a);(n.origin!==A.origin||n.username||n.password||n.search||n.hash||!/^\/[a-zA-Z0-9/_-]*$/.test(n.pathname)||!["GET","POST","PUT","DELETE"].includes(r)||Object.keys(L).some(y=>/^(authorization|proxy-authorization|cookie)$/i.test(y))||d!==null&&Buffer.byteLength(d)>16384||++q>64)&&s("request");const g=await new Promise((y,p)=>{const k=d===null?void 0:Buffer.from(d),f=M({socketPath:t.socketPath,path:n.pathname,method:r,agent:!1,headers:{...k?{"content-type":"application/json","content-length":String(k.length)}:{}}},o=>{const u=o.statusCode??502,l=o.headers["content-length"];if(u>=300&&u<400||u>=400||o.headers["set-cookie"]||l!==void 0&&(!/^[0-9]+$/.test(l)||Number(l)>1048576)){o.destroy(),p(new Error("qa-synthetic-backend-broker-port-unverified"));return}let w=0;const x=[];o.on("data",P=>{w+=P.length,w>1048576?(o.destroy(),p(new Error("qa-synthetic-backend-broker-port-unverified"))):x.push(P)}),o.on("error",()=>p(new Error("qa-synthetic-backend-broker-port-unverified"))),o.on("end",()=>y({status:u,body:Buffer.concat(x),contentType:o.headers["content-type"]??"application/octet-stream"}))});f.setTimeout(Math.max(1,Math.min(5e3,Date.parse(t.expiresAt)-Date.now())),()=>f.destroy()),f.on("error",o=>p(new Error(`qa-synthetic-backend-broker-port-${/^[A-Z_]+$/.test(o.code??"")?o.code.toLowerCase().replaceAll("_","-"):"transport"}`))),f.end(k)});return h(),S.push({path:n.pathname,method:r,status:g.status,responseSha256:D("sha256").update(g.body.toString("base64")).digest("hex")}),g}})}export{N as createSyntheticBrokerPort};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function launchSyntheticBackendBrowser(): Promise<import("playwright-core").Browser>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{lstatSync as s,realpathSync as c}from"node:fs";import{chromium as i}from"playwright-core";async function h(){if(process.platform!=="linux")throw new Error("qa-synthetic-backend-host-unsupported");const e=process.arch==="arm64",r=e?"/usr/bin/chromium":"/opt/google/chrome/chrome",n=["/usr/bin/bwrap","/usr","/usr/lib","/usr/lib64","/etc/fonts","/etc/ld.so.cache",...e?[r]:["/opt","/opt/google","/opt/google/chrome",r]];try{for(const o of n){const t=s(o);if(t.uid!==0||t.mode&18||t.isSymbolicLink()||c(o)!==o)throw new Error}}catch{throw new Error("qa-synthetic-backend-browser-unverified")}try{return await i.launch({executablePath:"/usr/bin/bwrap",ignoreDefaultArgs:!0,timeout:1e4,env:{PATH:"/usr/bin:/bin",LANG:"C.UTF-8"},args:["--unshare-all","--die-with-parent","--ro-bind","/usr","/usr","--ro-bind","/lib","/lib","--ro-bind","/lib64","/lib64",...e?[]:["--ro-bind","/opt/google/chrome","/opt/google/chrome"],"--ro-bind","/etc/fonts","/etc/fonts","--ro-bind","/etc/ld.so.cache","/etc/ld.so.cache","--proc","/proc","--dev","/dev","--tmpfs","/tmp","--dir","/tmp/home","--chdir","/tmp","--clearenv","--setenv","HOME","/tmp/home","--setenv","PATH","/usr/bin:/bin",r,"--headless=new","--no-sandbox","--remote-debugging-pipe","--user-data-dir=/tmp/qa-profile","--disable-dev-shm-usage","--no-first-run","--disable-background-networking","--disable-component-update","--disable-sync"]})}catch{throw new Error("qa-synthetic-backend-browser-unavailable")}}export{h as launchSyntheticBackendBrowser};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export type RefactorCharacterizationRunner = 'native' | 'vitest';
|
|
1
|
+
export type RefactorCharacterizationRunner = 'native' | 'vitest' | 'cpp';
|
|
2
2
|
/** Node's native type-stripping switch first exists in 22.6.0. */
|
|
3
3
|
export declare function supportsNativeTypeStrippingVersion(version: string): boolean;
|
|
4
|
+
/** Distribution capability is separate from semver; some Node builds disable Amaro. */
|
|
5
|
+
export declare function supportsNativeTypeStrippingRuntime(): boolean;
|
|
4
6
|
interface FileDigest {
|
|
5
7
|
readonly path: string;
|
|
6
8
|
readonly sha256: string;
|
|
@@ -20,7 +22,7 @@ export interface RefactorCharacterizationBaselineV1 {
|
|
|
20
22
|
}
|
|
21
23
|
export interface RefactorCharacterizationBaselineV2 extends Omit<RefactorCharacterizationBaselineV1, 'schemaVersion'> {
|
|
22
24
|
readonly schemaVersion: 2;
|
|
23
|
-
readonly runner: 'vitest';
|
|
25
|
+
readonly runner: 'vitest' | 'cpp';
|
|
24
26
|
readonly toolchainSha256: string;
|
|
25
27
|
}
|
|
26
28
|
export type RefactorCharacterizationBaseline = RefactorCharacterizationBaselineV1 | RefactorCharacterizationBaselineV2;
|
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import{spawnSync as
|
|
2
|
-
`)))throw new Error("refactor-root-baseline-invalid");return
|
|
3
|
-
`);if(
|
|
4
|
-
`,{mode:384,flag:"wx"})}const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`)
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import{spawnSync as G}from"node:child_process";import{createHash as lt,randomBytes as dt}from"node:crypto";import{closeSync as Q,constants as R,existsSync as C,fsyncSync as K,lstatSync as $,mkdirSync as Z,mkdtempSync as ut,openSync as tt,readFileSync as H,realpathSync as W,rmSync as pt,writeFileSync as z}from"node:fs";import{tmpdir as ht}from"node:os";import{basename as mt,dirname as N,join as y,resolve as wt}from"node:path";import{mutationQaGit as et}from"./mutation-qa-git.js";import{exactCommittedRefactorFile as vt,privateRefactorDirectory as rt,readPrivateRefactorAdmission as yt,verifyRootRefactorForCharacterization as ot}from"./refactor-root.js";const A=/^[a-f0-9]{64}$/,gt=64*1024*1024,st=32,nt=128;function bt(e){const t=e.match(/^(\d+)\.(\d+)\.(\d+)$/);if(!t)return!1;const r=Number(t[1]),n=Number(t[2]);return r>22||r===22&&n>=6}function St(){return bt(process.versions.node)&&process.config.variables.node_use_amaro===!0}function b(e){return lt("sha256").update(e).digest("hex")}function D(e){return e.length>0&&e.length<=512&&/^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)*$/.test(e)&&e.split("/").every(t=>t!=="."&&t!==".."&&![".git",".neocortex","node_modules"].includes(t.toLowerCase()))}function V(e){return[...e].sort((t,r)=>Buffer.from(t).compare(Buffer.from(r)))}function Et(e,t,r){if(!t.endsWith(".js")&&!t.endsWith(".ts"))return;let n=N(t);for(;;){const f=n==="."?"package.json":`${n}/package.json`;if(C(y(e,f))){if(!r.includes(f))throw new Error("refactor-root-tests-manifest-unbound");let s;try{s=JSON.parse(L(e,f).toString("utf8"))}catch{throw new Error("refactor-root-tests-manifest-invalid")}if(!s||typeof s!="object"||Array.isArray(s)||!["module","commonjs"].includes(s.type)||t.endsWith(".ts")&&s.type!=="module")throw new Error("refactor-root-tests-manifest-invalid");return}if(n===".")break;n=N(n)}throw new Error("refactor-root-tests-manifest-missing")}function L(e,t){if(!D(t))throw new Error("refactor-root-tests-path-invalid");const r=y(e,t),n=$(r);if(W(r)!==r||!n.isFile()||n.isSymbolicLink()||n.size<1||n.size>8*1024*1024)throw new Error("refactor-root-tests-source-unverified");const f=H(r);if(f.length<1||f.length>8*1024*1024||f.includes(0))throw new Error("refactor-root-tests-source-unverified");return new TextDecoder("utf-8",{fatal:!0}).decode(f),f}function q(e,t){if(!A.test(t))throw new Error("refactor-root-baseline-invalid");return y(rt(e),`characterization-baseline-${t}.json`)}function Y(e,t){const r=$(q(e,t));if(!r.isFile()||r.isSymbolicLink()||r.uid!==process.getuid?.()||(r.mode&63)!==0||r.size<100||r.size>64*1024)throw new Error("refactor-root-baseline-invalid");const n=H(q(e,t));if(n.length>64*1024)throw new Error("refactor-root-baseline-invalid");let f;try{f=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(n))}catch{throw new Error("refactor-root-baseline-invalid")}if(!f||typeof f!="object"||Array.isArray(f))throw new Error("refactor-root-baseline-invalid");const s=f,a=["schemaVersion","kind","admissionSha256","sourceHead","testFiles","dependencies","causalPath","candidateSha256","outputSha256","causalOutputSha256","baselineSha256"],l=o=>Array.isArray(o)&&o.every(p=>p&&typeof p=="object"&&!Array.isArray(p)&&Object.keys(p).sort().join("\0")==="path\0sha256"&&typeof p.path=="string"&&typeof p.sha256=="string"&&D(p.path)&&A.test(p.sha256)),w=s.schemaVersion===2;if(Object.keys(s).sort().join("\0")!==(w?[...a,"runner","toolchainSha256"]:a).sort().join("\0")||s.schemaVersion!==1&&s.schemaVersion!==2||w&&(!["vitest","cpp"].includes(String(s.runner))||!A.test(String(s.toolchainSha256)))||s.kind!=="root-refactor-characterization-baseline"||!A.test(String(s.admissionSha256))||typeof s.sourceHead!="string"||!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/.test(s.sourceHead)||!l(s.testFiles)||!l(s.dependencies)||s.testFiles.length<1||s.testFiles.length>st||s.dependencies.length>nt||typeof s.causalPath!="string"||!D(s.causalPath)||!A.test(String(s.candidateSha256))||!A.test(String(s.outputSha256))||!A.test(String(s.causalOutputSha256))||s.baselineSha256!==t)throw new Error("refactor-root-baseline-invalid");const c=s.testFiles,d=s.dependencies;if(new Set([...c,...d].map(o=>o.path)).size!==c.length+d.length||c.map(o=>o.path).join("\0")!==V(c.map(o=>o.path)).join("\0")||d.map(o=>o.path).join("\0")!==V(d.map(o=>o.path)).join("\0"))throw new Error("refactor-root-baseline-invalid");const{baselineSha256:i,...u}=s;if(b(JSON.stringify(u))!==t||!n.equals(Buffer.from(`${JSON.stringify(s)}
|
|
2
|
+
`)))throw new Error("refactor-root-baseline-invalid");return s}function kt(e,t){const r=b(JSON.stringify(t)),n=q(e,r),f={...t,baselineSha256:r},s=Buffer.from(`${JSON.stringify(f)}
|
|
3
|
+
`);if(C(n))Y(e,r);else{const a=tt(n,R.O_WRONLY|R.O_CREAT|R.O_EXCL|(R.O_NOFOLLOW??0),384);try{z(a,s),K(a)}finally{Q(a)}const l=tt(rt(e),R.O_RDONLY|(R.O_DIRECTORY??0));try{K(l)}finally{Q(l)}}return Y(e,r),r}function it(e){return[...e.files.map(t=>t.path),...e.schemaVersion===2?e.newFiles.map(t=>t.path):[]]}function at(e,t,r,n=[]){const f=new Map;let s=0;for(const l of[...it(t),...r]){if(n.includes(l)){try{$(y(e,l))}catch(c){if(c.code==="ENOENT")continue;throw c}throw new Error("refactor-root-tests-source-stale")}const w=L(e,l);if(s+=w.length,s>gt)throw new Error("refactor-root-tests-snapshot-too-large");f.set(l,w)}const a=b(JSON.stringify([...[...f].map(([l,w])=>[l,b(w)]),...n.map(l=>[l,null])]));return{files:f,candidateSha256:a}}function ct(){try{const e=W("/usr/bin/g++"),t=$(e);if(!e.startsWith("/usr/")||!/^[A-Za-z0-9_./+-]+$/.test(e)||!t.isFile()||t.uid!==0||(t.mode&18)!==0||t.size<1||t.size>32*1024*1024)throw new Error("invalid compiler");const r=G(e,["-dumpfullversion","-dumpversion"],{env:{PATH:"/usr/bin:/bin"},encoding:"utf8",timeout:1e4,maxBuffer:4096}),n=r.stdout?.trim();if(r.status!==0||!/^(?:11|12|13|14|15)\.[0-9]+\.[0-9]+$/.test(n))throw new Error("unsupported compiler");return{executable:e,sha256:b(JSON.stringify([e,n,b(H(e))]))}}catch{throw new Error("refactor-root-tests-toolchain-unverified")}}function Ot(e,t,r){let n="";for(const M of t){let J=N(M),F="";for(;;){const I=J==="."?"package.json":`${J}/package.json`;if(C(y(e,I))){F=I;break}if(J===".")break;J=N(J)}if(!F||n&&F!==n)throw new Error("refactor-root-tests-toolchain-unverified");n=F}if(!r.includes(n)||!r.includes("package-lock.json"))throw new Error("refactor-root-tests-toolchain-unbound");const f=L(e,n),s=L(e,"package-lock.json");let a,l;try{a=JSON.parse(f.toString("utf8")),l=JSON.parse(s.toString("utf8"))}catch{throw new Error("refactor-root-tests-toolchain-unverified")}const w=a.devDependencies?.vitest??a.dependencies?.vitest,c=l.packages,d=n==="package.json"?"":N(n),i=c?.[d],u=i?.devDependencies?.vitest??i?.dependencies?.vitest,o=c?.["node_modules/vitest"]?.version,p=c?.["node_modules/vite"]?.version;if(typeof w!="string"||w.length>80||!/^[\^~]?[0-9]+\.[0-9]+\.[0-9]+$/.test(w)||w!==u||typeof o!="string"||!/^[0-9]+\.[0-9]+\.[0-9]+$/.test(o)||!o.startsWith("3.2.")||typeof p!="string"||!/^[0-9]+\.[0-9]+\.[0-9]+$/.test(p)||!_t(p))throw new Error("refactor-root-tests-toolchain-unverified");const v=W(y(e,"node_modules")),g=$(v);if(mt(v)!=="node_modules"||!g.isDirectory()||g.isSymbolicLink()||g.uid!==process.getuid?.())throw new Error("refactor-root-tests-toolchain-unverified");const h=y(v,"vitest","package.json"),S=y(v,"vitest","vitest.mjs"),O=y(v,"vite","package.json"),E=$(h),_=$(S),B=$(O);if(!E.isFile()||E.isSymbolicLink()||!_.isFile()||_.isSymbolicLink()||!B.isFile()||B.isSymbolicLink()||W(h)!==h||W(S)!==S||W(O)!==O||E.size>64*1024||_.size>1024*1024||B.size>64*1024)throw new Error("refactor-root-tests-toolchain-unverified");const P=H(h),k=H(S),x=H(O);let j,T;try{j=JSON.parse(P.toString("utf8")),T=JSON.parse(x.toString("utf8"))}catch{throw new Error("refactor-root-tests-toolchain-unverified")}if(j.name!=="vitest"||j.version!==o||T.name!=="vite"||T.version!==p)throw new Error("refactor-root-tests-toolchain-unverified");return{nodeModules:v,sha256:b(JSON.stringify([b(f),b(s),b(P),b(k),b(x)]))}}function _t(e){const t=e.match(/^(\d+)\.(\d+)\.(\d+)$/);return!!t&&Number(t[1])<=7&&(Number(t[1])>6||Number(t[1])===6&&Number(t[2])>=1)}function ft(e,t,r,n,f,s,a){if(r==="python"){const c=N(t[0]),d=V([...e.keys()].filter(i=>(c==="."||i.startsWith(`${c}/`))&&/(?:^|\/)test_[A-Za-z0-9_]+\.py$/.test(i)));if(JSON.stringify(d)!==JSON.stringify(t))throw new Error("refactor-root-tests-path-invalid")}const l=W(r==="cpp"?"/usr/bin/dash":r==="python"?"/usr/bin/python3":process.execPath);if(r==="node-typescript"&&!St())throw new Error("refactor-root-tests-toolchain-unavailable");if(process.platform!=="linux"||!C("/usr/bin/bwrap")||!$("/usr/bin/bwrap").isFile()||!(l.startsWith("/usr/")||l.startsWith("/home/linuxbrew/.linuxbrew/")))throw new Error("refactor-root-tests-sandbox-unavailable");const w=ut(y(ht(),"p222-refactor-characterization-"));try{const c=y(w,"work");Z(c,{mode:448});for(const[h,S]of e){const O=y(c,h);Z(N(O),{recursive:!0,mode:448}),z(O,S,{mode:384,flag:"wx"})}if(r==="vitest"){if(!f)throw new Error("refactor-root-tests-toolchain-unavailable");Z(y(c,"node_modules"),{mode:448}),z(y(c,"p222-vitest.config.mjs"),`export default ${JSON.stringify({test:{include:t,environment:"node",silent:!0,passWithNoTests:!1,watch:!1,maxWorkers:1,fileParallelism:!1,pool:"forks",coverage:{enabled:!1}}})};
|
|
4
|
+
`,{mode:384,flag:"wx"})}if(r==="cpp"){if(!s||!a||!e.has(a))throw new Error("refactor-root-tests-toolchain-unavailable");const h=s.executable,S=V([...e.keys()].filter(E=>E.endsWith(".cpp")&&E!==a&&!t.includes(E))).map(E=>`'/work/${E}'`);n&&z(y(c,"p222-cpp-causal.cpp"),`#include <cstdio>
|
|
5
|
+
#include <cstdlib>
|
|
6
|
+
extern "C" void __cyg_profile_func_enter(void*,void*) { std::fputs(${JSON.stringify(n+`
|
|
7
|
+
`)},stderr); std::_Exit(86); }
|
|
8
|
+
extern "C" void __cyg_profile_func_exit(void*,void*) {}
|
|
9
|
+
`,{mode:384,flag:"wx"});const O=["set -eu","ulimit -c 0",`'${h}' -std=c++17 -O0 -UNDEBUG -I/work ${n?"-finstrument-functions -finstrument-functions-exclude-file-list=/usr/include ":""}-c '/work/${a}' -o /tmp/p222-cpp-causal.o`,...t.flatMap((E,_)=>[`'${h}' -std=c++17 -O0 -UNDEBUG -I/work '/work/${E}' ${S.join(" ")} /tmp/p222-cpp-causal.o ${n?"/work/p222-cpp-causal.cpp ":""}-o /tmp/p222-cpp-test-${_}`,`/tmp/p222-cpp-test-${_}`,`printf 'P222_CPP_TEST_PASSED_${_}\\n'`])].join(`
|
|
10
|
+
`)+`
|
|
11
|
+
`;z(y(c,"p222-cpp-runner.sh"),O,{mode:384,flag:"wx"})}const d=y(w,"etc");Z(d,{mode:448}),z(y(d,"passwd"),`nobody:x:65534:65534:nobody:/tmp:/bin/sh
|
|
12
|
+
`,{mode:384}),z(y(d,"group"),`nogroup:x:65534:
|
|
13
|
+
`,{mode:384}),z(y(d,"hosts"),`127.0.0.1 localhost
|
|
14
|
+
`,{mode:384}),z(y(d,"nsswitch.conf"),`hosts: files
|
|
15
|
+
`,{mode:384});const i=["--die-with-parent","--new-session","--unshare-all","--clearenv","--setenv","HOME","/tmp","--setenv","TMPDIR","/tmp","--setenv","PATH","/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin","--setenv","CI","true","--ro-bind","/usr","/usr"];r==="python"&&i.push("--setenv","PYTHONPATH","/work");for(const h of["/lib","/lib64","/bin"])C(h)&&i.push("--ro-bind",h,h);C("/home/linuxbrew/.linuxbrew")&&i.push("--ro-bind","/home/linuxbrew/.linuxbrew","/home/linuxbrew/.linuxbrew"),i.push("--dir","/etc");for(const h of["passwd","group","hosts","nsswitch.conf"])i.push("--ro-bind",y(d,h),`/etc/${h}`);i.push("--dev","/dev","--proc","/proc","--tmpfs","/tmp","--ro-bind",c,"/work"),r==="vitest"&&i.push("--ro-bind",f.nodeModules,"/work/node_modules"),i.push("--chdir","/work","--",l),r==="cpp"?i.push("/work/p222-cpp-runner.sh"):r==="python"?i.push("-B","-S","-m","unittest","discover","-s",N(t[0]),"-p","test_*.py"):r==="vitest"?i.push("/work/node_modules/vitest/vitest.mjs","run","--root","/work","--config","/work/p222-vitest.config.mjs","--configLoader=runner","--reporter=json","--no-cache","--no-file-parallelism","--maxWorkers=1"):(r==="node-typescript"&&i.push("--experimental-strip-types"),i.push("--test","--test-reporter=tap",...t));const u=G("/usr/bin/bwrap",i,{env:{PATH:"/usr/bin:/bin"},encoding:"buffer",timeout:18e4,maxBuffer:4*1024*1024});if(u.error||u.signal||u.status===null)throw new Error("refactor-root-tests-sandbox-unavailable");const o=Buffer.concat([u.stdout??Buffer.alloc(0),u.stderr??Buffer.alloc(0)]),p=r!=="python"||/^Ran [1-9][0-9]* tests? in /m.test(o.toString("utf8"));let v=!0;if(r==="vitest")try{const h=JSON.parse((u.stdout??Buffer.alloc(0)).toString("utf8"));v=Number.isSafeInteger(h.numPassedTests)&&Number(h.numPassedTests)>0&&h.numTotalTests===h.numPassedTests&&h.numFailedTests===0}catch{v=!1}const g=r!=="cpp"||t.every((h,S)=>o.toString("utf8").split(`
|
|
16
|
+
`).includes(`P222_CPP_TEST_PASSED_${S}`));return{passed:u.status===0&&p&&v&&g,outputSha256:b(o),canaryObserved:n!==void 0&&(r==="cpp"?o.toString("utf8").split(`
|
|
17
|
+
`).includes(n):o.includes(Buffer.from(n)))}}finally{pt(w,{recursive:!0,force:!0})}}function xt(e,t,r,n,f,s,a,l,w="native"){if(!s)throw new Error("refactor-root-run-authorization-required");if(r.length<1||r.length>st||n.length>nt||!["native","vitest","cpp"].includes(w)||f==="baseline"&&l!==void 0||f==="after"&&(!l||!A.test(l)))throw new Error("refactor-root-tests-arguments-invalid");const c=V(r),d=V(n),i=w==="cpp"?"cpp":w==="vitest"?"vitest":c.every(o=>/(?:^|\/)test_[A-Za-z0-9_]+\.py$/.test(o))&&a.endsWith(".py")?"python":c.every(o=>o.endsWith(".test.ts"))&&a.endsWith(".ts")?"node-typescript":"node";if(new Set([...c,...d]).size!==c.length+d.length||c.some(o=>!D(o)||(i==="cpp"?!o.endsWith(".test.cpp"):i==="python"?!/(?:^|\/)test_[A-Za-z0-9_]+\.py$/.test(o)||N(o)!==N(c[0]):i==="vitest"?!/\.test\.(?:ts|js|mjs)$/.test(o):i==="node-typescript"?!o.endsWith(".test.ts"):!/\.test\.(?:mjs|cjs|js)$/.test(o)))||!D(a)||(i==="cpp"?!a.endsWith(".cpp")||a.endsWith(".test.cpp"):i==="python"?!a.endsWith(".py"):i==="vitest"?!/\.(?:ts|js|mjs)$/.test(a)||/\.test\./.test(a):i==="node-typescript"?!a.endsWith(".ts")||a.endsWith(".test.ts"):!/\.(?:mjs|cjs|js)$/.test(a))||d.some(o=>!D(o)||i==="python"&&/(?:^|\/)test_[A-Za-z0-9_]+\.py$/.test(o)))throw new Error("refactor-root-tests-path-invalid");const u=wt(e);try{const o=yt(u,t),{pendingDocumentationPaths:p}=ot(u,t),v=new Set(it(o));if(c.some(m=>!v.has(m))||!o.files.some(m=>m.path===a)||c.includes(a)||d.some(m=>v.has(m)))throw new Error("refactor-root-tests-path-invalid");for(const m of[...c,a,...d])Et(u,m,d);for(const m of d)vt(u,m);const g=i==="vitest"?Ot(u,c,d):void 0,h=i==="cpp"?ct():void 0,S=g?.sha256??h?.sha256,O=et(u,["diff","--name-only","-z","--no-ext-diff","--no-textconv"]).toString("utf8").split("\0").filter(m=>m&&!m.startsWith(".neocortex/")),E=et(u,["ls-files","--others","--exclude-standard","-z"]).toString("utf8").split("\0").filter(m=>m&&!m.startsWith(".neocortex/")),_=[...O,...E].filter(m=>!c.includes(m));if(f==="baseline"&&_.length>0||f==="after"&&_.length===0)throw new Error("refactor-root-tests-phase-invalid");const B=c.map(m=>({path:m,sha256:b(L(u,m))})),P=d.map(m=>({path:m,sha256:b(L(u,m))})),k=f==="after"?Y(u,l):null;if(k&&(k.admissionSha256!==t||k.sourceHead!==o.sourceHead||k.causalPath!==a||(k.schemaVersion===2?w!==k.runner||k.toolchainSha256!==S:w!=="native")||JSON.stringify(k.testFiles)!==JSON.stringify(B)||JSON.stringify(k.dependencies)!==JSON.stringify(P)))throw new Error("refactor-root-baseline-stale");const x=at(u,o,d,p);if(k&&b(x.files.get(a))===o.files.find(m=>m.path===a).sha256)throw new Error("refactor-root-tests-phase-invalid");const j=ft(x.files,c,i,void 0,g,h,a);let T=null,M=!1;if(j.passed){const m=`P222_REFACTOR_CAUSAL_${dt(16).toString("hex")}`,X=new Map(x.files);i!=="cpp"&&X.set(a,Buffer.concat([Buffer.from(i==="python"?`raise RuntimeError(${JSON.stringify(m)})
|
|
18
|
+
`:`throw new Error(${JSON.stringify(m)});
|
|
19
|
+
`),x.files.get(a)]));const U=ft(X,c,i,m,g,h,a);T=U.outputSha256,M=!U.passed&&U.canaryObserved}const J=ot(u,t);if(JSON.stringify(J.pendingDocumentationPaths)!==JSON.stringify(p))throw new Error("refactor-root-tests-source-stale");const F=at(u,o,d,p);if(h&&ct().sha256!==h.sha256)throw new Error("refactor-root-tests-toolchain-stale");if(x.candidateSha256!==F.candidateSha256)throw new Error("refactor-root-tests-source-stale");let I=l??null;return f==="baseline"&&j.passed&&M&&T&&(I=kt(u,{...i==="vitest"||i==="cpp"?{schemaVersion:2,runner:i,toolchainSha256:S}:{schemaVersion:1},kind:"root-refactor-characterization-baseline",admissionSha256:t,sourceHead:o.sourceHead,testFiles:B,dependencies:P,causalPath:a,candidateSha256:x.candidateSha256,outputSha256:j.outputSha256,causalOutputSha256:T})),Object.freeze({schemaVersion:1,kind:"root-refactor-characterization-observation",phase:f,admissionSha256:t,baselineSha256:I,candidateSha256:x.candidateSha256,outputSha256:j.outputSha256,causalOutputSha256:T,testFileCount:c.length,dependencyCount:d.length,testsPassedObserved:j.passed,causalFailureObserved:M,qaAccepted:!1,gitCommitAuthorized:!1,publicSafe:!0})}catch(o){throw o instanceof Error&&o.message.startsWith("refactor-root-")?o:new Error("refactor-root-tests-unverified")}}function Wt(e){let t="",r="",n,f="",s=!1,a="",l="native",w="plain";const c=[],d=[];try{if(e[0]!=="characterize")throw new Error("refactor-root-tests-arguments-invalid");for(let o=1;o<e.length;o++){const p=e[o],v=()=>{const g=e[++o];if(!g||g.startsWith("--"))throw new Error("refactor-root-tests-arguments-invalid");return g};if(p==="--project-root"&&!t)t=v();else if(p==="--admission-sha"&&!r)r=v();else if(p==="--baseline-sha"&&!n)n=v();else if(p==="--phase"&&!f){const g=v();if(g!=="baseline"&&g!=="after")throw new Error("refactor-root-tests-arguments-invalid");f=g}else if(p==="--test-path")c.push(v());else if(p==="--dependency")d.push(v());else if(p==="--causal-path"&&!a)a=v();else if(p==="--runner"&&l==="native"){const g=v();if(g!=="vitest"&&g!=="cpp")throw new Error("refactor-root-tests-arguments-invalid");l=g}else if(p==="--authorize-run"&&!s)s=!0;else if(p==="--format"&&w==="plain")w=v();else throw new Error("refactor-root-tests-arguments-invalid")}if(!t||!r||!f||!a||!["plain","json"].includes(w))throw new Error("refactor-root-tests-arguments-invalid");const i=xt(t,r,c,d,f,s,a,n,l),u=i.testsPassedObserved&&i.causalFailureObserved;return process.stdout.write(`${JSON.stringify({ok:u,observation:i})}
|
|
20
|
+
`),u?0:1}catch(i){const u=i instanceof Error&&/^refactor-root-[a-z-]+$/.test(i.message)?i.message:"refactor-root-tests-unverified";return process.stdout.write(`${JSON.stringify({ok:!1,reasonCode:u})}
|
|
21
|
+
`),1}}export{Y as readRootRefactorBaseline,Wt as refactorCharacterizationCliHandler,xt as runRootRefactorCharacterization,St as supportsNativeTypeStrippingRuntime,bt as supportsNativeTypeStrippingVersion};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function requestRootControl(family: 'refactor' | 'qa', input: Readonly<{
|
|
2
|
+
serverUrl: string;
|
|
3
|
+
token: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
storyId: string;
|
|
6
|
+
platformTarget: string;
|
|
7
|
+
}>, fetchFn?: typeof fetch): Promise<Record<string, unknown>>;
|
|
8
|
+
export declare function requestRefactorControl(input: Parameters<typeof requestRootControl>[1], fetchFn?: typeof fetch): Promise<Record<string, unknown>>;
|
|
9
|
+
export declare function refactorControlCliHandler(args: readonly string[], family?: 'refactor' | 'qa'): Promise<number>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{lstatSync as S,readFileSync as v,realpathSync as R}from"node:fs";import{join as w,resolve as g}from"node:path";import{signNxInvokeRequest as k}from"../../../shared/dist/nx-invoke-signature.js";import{COMMAND_REGISTRY_VERSION as q,COMMAND_REGISTRY_CHECKSUM as C}from"../generated/command-registry.generated.js";import{CLIENT_VERSION as N}from"../version.js";import{loadSecureConfig as b}from"../config/secure-config.js";import{neocortexProfileDirectory as _}from"../config/profile-directory.js";import{EncryptedCache as A}from"../cache/encrypted-cache.js";import{LicenseClient as T}from"../license/license-client.js";import{detectPlatform as I}from"../adapters/platform-detector.js";const y=new Set(["refactor-control-input-invalid","refactor-control-auth-required","refactor-control-tier-required","refactor-control-read-only","refactor-control-signature-required","refactor-control-client-unsupported","refactor-control-registry-mismatch","refactor-control-executor-unavailable"]),L=new Set(["arguments-invalid","authorization-required","host-unsupported","project-unbound","auth-required","response-invalid","request-refused","outcome-unknown"].map(e=>`refactor-root-control-${e}`));async function j(e){const o=e.body?.getReader();if(!o)throw new Error("refactor-root-control-response-invalid");let n=!1;try{const t=[];let c=0;for(;;){const a=await o.read();if(a.done){n=!0;break}if(c+=a.value.byteLength,c>16384)throw new Error("refactor-root-control-response-invalid");t.push(Buffer.from(a.value))}return JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(Buffer.concat(t,c)))}catch{throw new Error("refactor-root-control-response-invalid")}finally{n||await o.cancel().catch(()=>{}),o.releaseLock()}}async function E(e,o,n=fetch){if(e!=="refactor"&&e!=="qa")throw new Error("refactor-root-control-arguments-invalid");const t=`/api/v1/invoke/${e}/control`,c=k({method:"POST",target:t,body:Buffer.from(JSON.stringify({projectId:o.projectId,storyId:o.storyId,platformTarget:o.platformTarget,registryVersion:q,registryChecksum:C})),bearerToken:o.token,clientVersion:N}),a=await n(`${o.serverUrl.replace(/\/+$/,"")}${t}`,{method:"POST",redirect:"error",signal:AbortSignal.timeout(2e5),headers:{...c.headers,Authorization:`Bearer ${o.token}`},body:c.body}),r=await j(a);if(!a.ok)throw new Error(typeof r?.error_code=="string"&&y.has(r.error_code.replace(/^qa-/,"refactor-"))&&r.error_code.startsWith(`${e}-`)?r.error_code:"refactor-root-control-request-refused");const l=["schemaVersion","kind","status","completedStages","authority","qaAccepted","gitAuthority","billingAuthority","publicSafe"];if(!r||typeof r!="object"||Array.isArray(r)||Object.keys(r).some(s=>!l.includes(s))||r.schemaVersion!==1||r.kind!==`root-${e}-control`||typeof r.status!="string"||!["advanced","waiting","blocked","candidate-ready",...e==="qa"?["debt"]:[]].includes(r.status)||r.authority!==(e==="qa"?"LOCAL_ROOT_QA_CANDIDATE_ONLY":"LOCAL_ROOT_CANDIDATE_ONLY")||r.qaAccepted!==!1||r.gitAuthority!=="NONE"||r.billingAuthority!=="NONE"||r.publicSafe!==!0||r.completedStages!==void 0&&(typeof r.completedStages!="number"||!Number.isInteger(r.completedStages)||r.completedStages<0||r.completedStages>(e==="qa"?3:7)))throw new Error("refactor-root-control-response-invalid");return r}async function B(e,o=fetch){return E("refactor",e,o)}async function Y(e,o="refactor"){try{let n="",t="",c=!1,a="json";const r=[...e];if(r.shift()!=="control")throw new Error("refactor-root-control-arguments-invalid");for(let i=0;i<r.length;i++){const d=r[i];if(d==="--authorize-root-control")c=!0;else if(d==="--project-root")n=r[++i]??"";else if(d==="--story")t=r[++i]??"";else if(d==="--format")a=r[++i]??"";else throw new Error("refactor-root-control-arguments-invalid")}if(!c||!n||a!=="json"||!/^P[0-9]{1,12}(?:\.[0-9]{1,12}){1,3}$/.test(t))throw new Error("refactor-root-control-authorization-required");const l=I({cwd:g(n),env:process.env}).targetId;if(l!=="codex")throw new Error("refactor-root-control-host-unsupported");const s=w(g(n),".neocortex","state.json"),u=S(s);if(!u.isFile()||u.isSymbolicLink()||R(s)!==s||u.size>16*1024*1024)throw new Error("refactor-root-control-project-unbound");const p=JSON.parse(v(s,"utf8")).config?.project_id;if(typeof p!="string"||!/^[A-Za-z0-9][A-Za-z0-9_-]{15,127}$/.test(p))throw new Error("refactor-root-control-project-unbound");const f=b({strictReadOnly:!0});if(!f?.licenseKey)throw new Error("refactor-root-control-auth-required");const h=process.env.NEOCORTEX_SERVER_URL??f.serverUrl;if(!h)throw new Error("refactor-root-control-auth-required");const m=await new T({serverUrl:h,licenseKey:f.licenseKey,cacheProvider:new A({cacheDir:w(_(),"cache"),passphrase:f.licenseKey})}).getToken();if(!m)throw new Error("refactor-root-control-auth-required");const O=await E(o,{serverUrl:h,token:m,projectId:p,storyId:t,platformTarget:l});return process.stdout.write(`${JSON.stringify({ok:!0,control:O})}
|
|
2
|
+
`),0}catch(n){const t=n instanceof Error?n.message.replace(/^qa-/,"refactor-"):"",c=L.has(t)||y.has(t)?t:"refactor-root-control-outcome-unknown";return process.stdout.write(`${JSON.stringify({ok:!1,reasonCode:o==="qa"?c.replace(/^refactor-/,"qa-"):c})}
|
|
3
|
+
`),1}}export{Y as refactorControlCliHandler,B as requestRefactorControl,E as requestRootControl};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Preserve line numbers while excluding C++ comments and quoted/raw string data. */
|
|
2
|
+
export declare function cppRefactorExecutableLines(text: string): string[];
|
|
3
|
+
/** Syntactic anchor only; independent root review checks the failure body and behavior. */
|
|
4
|
+
export declare function isCppRefactorAssertionSite(line: string): boolean;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
function u(t){let n="",e=0,s="code",r="",c=!1,o="";for(;e<t.length;){const i=t[e];if(i===`
|
|
2
|
+
`){n+=`
|
|
3
|
+
`,e++,s==="line"&&(s="code"),s==="quote"&&(c=!1);continue}if(s==="line"){e++;continue}if(s==="block"){t.startsWith("*/",e)?(s="code",e+=2):e++;continue}if(s==="quote"){c?c=!1:i==="\\"?c=!0:i===r&&(s="code"),e++;continue}if(s==="raw"){t.startsWith(o,e)?(s="code",e+=o.length):e++;continue}if(t.startsWith("//",e)){s="line",e+=2,n+=" ";continue}if(t.startsWith("/*",e)){s="block",e+=2,n+=" ";continue}const f=/^(?:u8|u|U|L)?R"([^\s()\\]{0,16})\(/.exec(t.slice(e,e+24));if(f){o=`)${f[1]}"`,s="raw",e+=f[0].length,n+=" ";continue}if(i==='"'||i==="'"){r=i,s="quote",c=!1,e++,n+=" ";continue}if(/[A-Za-z_0-9]/.test(i)){const a=e++,l=/[0-9]/.test(i);for(;e<t.length&&(l?/[A-Za-z_0-9.']/.test(t[e]):/[A-Za-z_0-9]/.test(t[e]));)e++;n+=t.slice(a,e);continue}n+=i,e++}return n.split(/\r?\n/)}function h(t){return!/^\s*#/.test(t)&&(/\bassert\s*\(/.test(t)||/\bthrow\s+\S/.test(t)||/^\s*(?:else\s+)?if\s*\(/.test(t))}export{u as cppRefactorExecutableLines,h as isCppRefactorAssertionSite};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{createHash as
|
|
2
|
-
`))||o.checksumSha256!==v(`root-refactor-semantic-record-v1\0${JSON.stringify({report:o.report,receipt:o.receipt})}`))throw new Error("refactor-root-review-unverified");return o}function
|
|
3
|
-
`);if(
|
|
4
|
-
`),0}catch(
|
|
5
|
-
`),1}}export{
|
|
1
|
+
import{createHash as $,randomUUID as C}from"node:crypto";import{closeSync as R,existsSync as k,fsyncSync as x,linkSync as H,lstatSync as N,openSync as O,readFileSync as F,realpathSync as j,unlinkSync as I,writeFileSync as V}from"node:fs";import{join as y,resolve as B}from"node:path";import{readRootRefactorBaseline as W,runRootRefactorCharacterization as D}from"./refactor-characterization.js";import{cppRefactorExecutableLines as M,isCppRefactorAssertionSite as T}from"./refactor-cpp-assertions.js";import{privateRefactorDirectory as z,readPrivateRefactorAdmission as q,verifyRootRefactor as _}from"./refactor-root.js";const l=/^[a-f0-9]{64}$/,S=128*1024;function v(t){return $("sha256").update(t).digest("hex")}function p(t,e){return t!==null&&typeof t=="object"&&!Array.isArray(t)&&Object.keys(t).sort().join("\0")===[...e].sort().join("\0")}function J(t,e){return typeof t=="string"&&t.length>=30&&t.length<=e&&!/[\x00-\x1f\x7f]/.test(t)}function g(t,e,n){if(!l.test(e)||!l.test(n))throw new Error("refactor-root-review-unverified");const o=B(t),i=q(o,e),a=W(o,n),c=_(o,e),r=D(o,e,a.testFiles.map(u=>u.path),a.dependencies.map(u=>u.path),"after",!0,a.causalPath,n,a.schemaVersion===2?a.runner:"native");if(a.admissionSha256!==e||a.sourceHead!==i.sourceHead||r.baselineSha256!==n||!r.testsPassedObserved||!r.causalFailureObserved||c.changedFileCount<2)throw new Error("refactor-root-review-unverified");return Object.freeze({root:o,storyId:i.storyId,sourceHead:i.sourceHead,admissionSha256:e,baselineSha256:n,candidateSha256:r.candidateSha256,testFiles:a.testFiles,changedFileCount:c.changedFileCount})}function P(t,e){if(!p(e,["schemaVersion","kind","storyId","sourceHead","admissionSha256","baselineSha256","candidateSha256","verdict","behaviorRationale","assertions"])||e.schemaVersion!==1||e.kind!=="root-refactor-semantic-review"||e.storyId!==t.storyId||e.sourceHead!==t.sourceHead||e.admissionSha256!==t.admissionSha256||e.baselineSha256!==t.baselineSha256||e.candidateSha256!==t.candidateSha256||e.verdict!=="approved"||!J(e.behaviorRationale,1e3)||!Array.isArray(e.assertions)||e.assertions.length<t.testFiles.length||e.assertions.length>64||Buffer.byteLength(JSON.stringify(e))>S)throw new Error("refactor-root-review-unverified");const n=new Map(t.testFiles.map(r=>[r.path,r.sha256])),o=new Map,i=new Map;for(const[r,u]of n){const f=y(t.root,r),s=N(f);if(!s.isFile()||s.isSymbolicLink()||j(f)!==f||s.size<1||s.size>8*1024*1024)throw new Error("refactor-root-review-unverified");const d=F(f);if(v(d)!==u)throw new Error("refactor-root-review-unverified");const h=new TextDecoder("utf-8",{fatal:!0}).decode(d);o.set(r,h.split(/\r?\n/)),r.endsWith(".cpp")&&i.set(r,M(h))}const a=new Set,c=new Set;for(const r of e.assertions){if(!p(r,["testPath","assertionLine","rationale"])||typeof r.testPath!="string"||!n.has(r.testPath)||!Number.isSafeInteger(r.assertionLine)||Number(r.assertionLine)<1||Number(r.assertionLine)>(o.get(r.testPath)?.length??0)||!J(r.rationale,500))throw new Error("refactor-root-review-unverified");const u=`${r.testPath}:${r.assertionLine}`;if(a.has(u))throw new Error("refactor-root-review-unverified");a.add(u),c.add(r.testPath);const f=o.get(r.testPath)[Number(r.assertionLine)-1],s=r.testPath.endsWith(".py")?(f.split("#")[0]??"").trimStart():f.split("//")[0]??"";if(!(r.testPath.endsWith(".cpp")?T(i.get(r.testPath)?.[Number(r.assertionLine)-1]??""):r.testPath.endsWith(".py")?/^self\.assert[A-Z][A-Za-z0-9_]*\s*\(/.test(s)||/^assert\s+\S/.test(s):/\b(?:assert|expect|throw)\b/.test(s)))throw new Error("refactor-root-review-unverified")}if(c.size!==n.size)throw new Error("refactor-root-review-unverified");return e}function A(t,e){return Object.freeze({schemaVersion:1,kind:"root-refactor-semantic-acceptance",storyId:t.storyId,sourceHead:t.sourceHead,admissionSha256:t.admissionSha256,baselineSha256:t.baselineSha256,candidateSha256:t.candidateSha256,reviewSha256:v(`root-refactor-semantic-review-v1\0${JSON.stringify(e)}`),testFileCount:t.testFiles.length,assertionCount:e.assertions.length,changedFileCount:t.changedFileCount,executionVerified:!0,qaAccepted:!0,gitCommitAuthorized:!1,publicSafe:!0})}function L(t,e,n){return y(z(t),`review-${e}-${n}.json`)}function E(t){const e=N(t);if(!e.isFile()||e.isSymbolicLink()||e.uid!==process.getuid?.()||(e.mode&63)!==0||e.size<100||e.size>S+4096)throw new Error("refactor-root-review-unverified");const n=F(t),o=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(n));if(!p(o,["schemaVersion","kind","report","receipt","checksumSha256"])||o.schemaVersion!==1||o.kind!=="root-refactor-semantic-record"||typeof o.checksumSha256!="string"||!l.test(o.checksumSha256)||!n.equals(Buffer.from(`${JSON.stringify(o)}
|
|
2
|
+
`))||o.checksumSha256!==v(`root-refactor-semantic-record-v1\0${JSON.stringify({report:o.report,receipt:o.receipt})}`))throw new Error("refactor-root-review-unverified");return o}function U(t,e,n,o){try{const i=g(t,e,n),a=P(i,o),c=A(i,a),r=L(i.root,e,i.candidateSha256),u={report:a,receipt:c},f={schemaVersion:1,kind:"root-refactor-semantic-record",...u,checksumSha256:v(`root-refactor-semantic-record-v1\0${JSON.stringify(u)}`)},s=Buffer.from(`${JSON.stringify(f)}
|
|
3
|
+
`);if(k(r)){const m=E(r);if(JSON.stringify(m.report)!==JSON.stringify(a)||JSON.stringify(m.receipt)!==JSON.stringify(c))throw new Error("refactor-root-review-conflict");return c}const d=z(i.root),h=y(d,`review-${C()}.tmp`),w=O(h,"wx",384);try{V(w,s),x(w)}finally{R(w)}try{if(g(i.root,e,n).candidateSha256!==c.candidateSha256)throw new Error("refactor-root-review-unverified");H(h,r);const b=O(d,"r");try{x(b)}finally{R(b)}}finally{k(h)&&I(h)}return E(r),c}catch(i){throw i instanceof Error&&i.message==="refactor-root-review-conflict"?i:new Error("refactor-root-review-unverified")}}function Z(t,e,n){try{const o=g(t,e,n),i=E(L(o.root,e,o.candidateSha256));if(!p(i,["schemaVersion","kind","report","receipt","checksumSha256"]))throw new Error("refactor-root-review-unverified");const a=P(o,i.report),c=A(o,a);if(JSON.stringify(i.receipt)!==JSON.stringify(c))throw new Error("refactor-root-review-unverified");return c}catch{throw new Error("refactor-root-review-unverified")}}async function te(t){const e=t[0];let n="",o="",i="",a=!1,c=!1,r="plain";const u=new Set;try{if(e!=="review-accept"&&e!=="review-status")throw new Error("refactor-root-review-arguments-invalid");for(let s=1;s<t.length;s++){const d=t[s];if(u.has(d))throw new Error("refactor-root-review-arguments-invalid");u.add(d);const h=()=>{const w=t[++s];if(!w||w.startsWith("--"))throw new Error("refactor-root-review-arguments-invalid");return w};if(d==="--project-root")n=h();else if(d==="--admission-sha")o=h();else if(d==="--baseline-sha")i=h();else if(d==="--authorize-run")a=!0;else if(d==="--authorize-root-review")c=!0;else if(d==="--format")r=h();else throw new Error("refactor-root-review-arguments-invalid")}if(!n||!l.test(o)||!l.test(i)||!["plain","json"].includes(r)||!a||c!==(e==="review-accept"))throw new Error("refactor-root-review-arguments-invalid");let f;if(e==="review-accept"){let s="";for await(const w of process.stdin)if(s+=String(w),Buffer.byteLength(s)>S)throw new Error("refactor-root-review-unverified");const{parseDocument:d}=await import("yaml"),h=d(s,{strict:!0,uniqueKeys:!0,schema:"core",customTags:[]});if(h.errors.length||h.warnings.length)throw new Error("refactor-root-review-unverified");f=U(n,o,i,JSON.parse(s))}else f=Z(n,o,i);return process.stdout.write(`${JSON.stringify({ok:!0,acceptance:f})}
|
|
4
|
+
`),0}catch(f){const s=f instanceof Error&&/^refactor-root-[a-z-]+$/.test(f.message)?f.message:"refactor-root-review-unverified";return process.stdout.write(`${JSON.stringify({ok:!1,reasonCode:s})}
|
|
5
|
+
`),1}}export{U as acceptRootRefactorSemanticReview,Z as readRootRefactorSemanticReview,te as refactorReviewCliHandler};
|
|
@@ -17,7 +17,7 @@ export declare function exactCommittedRefactorFile(root: string, path: string):
|
|
|
17
17
|
sha256: string;
|
|
18
18
|
mode: number;
|
|
19
19
|
}>;
|
|
20
|
-
/** Preserve
|
|
20
|
+
/** Preserve pre-existing visible and ignored Neocortex controls without copying them to a model. */
|
|
21
21
|
export declare function refactorSidecarDigest(root: string): string;
|
|
22
22
|
export interface PrivateRefactorAdmissionV1 {
|
|
23
23
|
readonly schemaVersion: 1;
|
|
@@ -81,5 +81,12 @@ export interface RefactorRootContainmentReceiptV2 extends Omit<RefactorRootConta
|
|
|
81
81
|
readonly newFileCount: number;
|
|
82
82
|
}
|
|
83
83
|
export declare function verifyRootRefactor(projectRoot: string, admissionSha256: string): RefactorRootContainmentReceiptV1 | RefactorRootContainmentReceiptV2;
|
|
84
|
+
/** Private characterization preparation only. Full review/commit still requires
|
|
85
|
+
* every admitted new file. Missing Markdown cannot authorize QA or Git effects.
|
|
86
|
+
*/
|
|
87
|
+
export declare function verifyRootRefactorForCharacterization(projectRoot: string, admissionSha256: string): Readonly<{
|
|
88
|
+
receipt: RefactorRootContainmentReceiptV1 | RefactorRootContainmentReceiptV2;
|
|
89
|
+
pendingDocumentationPaths: readonly string[];
|
|
90
|
+
}>;
|
|
84
91
|
export declare function planRootRefactor(projectRoot: string, storyId: string): RefactorRootPlanV1;
|
|
85
92
|
export declare function refactorRootCliHandler(args: readonly string[]): number;
|