@ornexus/neocortex 4.60.63 → 4.60.64
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 +23 -23
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +7 -2
- 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 +85 -80
- 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 +12 -3
- package/packages/client/dist/commands/refactor-characterization.js +21 -12
- package/packages/client/dist/commands/refactor-control.d.ts +17 -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.d.ts +13 -0
- package/packages/client/dist/commands/refactor-review.js +6 -5
- package/packages/client/dist/commands/refactor-root.d.ts +165 -1
- package/packages/client/dist/commands/refactor-root.js +12 -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-contract.d.ts +19 -0
- package/packages/client/dist/commands/shared-architecture-non-ui-contract.js +1 -0
- package/packages/client/dist/errors/error-messages.js +1 -1
- package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -4
- package/packages/client/dist/git/git-lifecycle-store.js +7 -7
- 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/clean-baseline.d.ts +6 -0
- package/packages/client/dist/private-execution/clean-baseline.js +2 -2
- package/packages/client/dist/private-execution/codex-executor.d.ts +48 -4
- package/packages/client/dist/private-execution/codex-executor.js +9 -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 +18 -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 +7 -0
- package/packages/client/dist/private-execution/implementation-validation.d.ts +24 -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/ux-source-validation.js +1 -1
- package/packages/client/dist/runner-cli.js +0 -0
- 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/invocation/index.js +4 -2
- package/packages/shared/dist/invocation/packed-invoke.d.ts +12 -0
- package/packages/shared/dist/invocation/packed-invoke.js +58 -0
- package/packages/shared/dist/invocation/packed-invoke.test.d.ts +1 -0
- package/packages/shared/dist/invocation/packed-invoke.test.js +21 -0
- package/packages/shared/dist/planning/diagnosis-state.js +5 -2
- package/packages/shared/dist/private-qa-structural-admission.js +14 -0
- package/packages/shared/dist/private-yolo-predecessor-decision.js +32 -0
- package/packages/shared/dist/project-memory-targets.js +243 -0
- package/packages/shared/dist/project-validation-commands.js +96 -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/gemini-cli/agent.md +2 -2
- package/targets-stubs/opencode/neocortex-root.md +1 -1
- package/targets-stubs/vscode/neocortex.agent.md +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{decodeJwt as h}from"jose";import{NoOpCache as
|
|
1
|
+
import{decodeJwt as h}from"jose";import{NoOpCache as o}from"../types/index.js";import{getMachineFingerprint as l}from"../machine/fingerprint.js";import{CLIENT_VERSION as u}from"../version.js";const a="neocortex:jwt:token",s="neocortex:jwt:refresh_token",f=300,c=10080*60*1e3;class w{serverUrl;licenseKey;cache;clientVersion;machineId;strictReadOnly;token=null;refreshToken=null;constructor(e){this.serverUrl=e.serverUrl.replace(/\/+$/,""),this.licenseKey=e.licenseKey,this.cache=e.cacheProvider??new o,this.clientVersion=e.clientVersion??u,this.strictReadOnly=e.strictReadOnly??!1,this.machineId=l({strictReadOnly:this.strictReadOnly})}async getToken(){try{if(this.strictReadOnly){const t=await this.inspectToken();return t.status==="authenticated"?t.token:null}if(this.token){const t=this.checkTokenValidity(this.token);if(t==="valid")return this.token;if(t==="needs-refresh")return this.strictReadOnly?this.token:(await this.refresh())?.token??this.token;this.token=null}const e=await this.loadFromCache();if(e){this.token=e;const t=this.checkTokenValidity(e);if(t==="valid")return e;if(t==="needs-refresh")return this.strictReadOnly?e:(await this.refresh())?.token??e;this.token=null}if(this.strictReadOnly)return null;if(this.refreshToken||(this.refreshToken=await this.loadRefreshTokenFromCache()),this.refreshToken){const t=await this.refresh();if(t?.token)return t.token}return(await this.activate())?.token??null}catch{return null}}async inspectToken(){try{const e=this.token??await this.loadFromCache();if(e){const i=this.checkTokenValidity(e);return i==="valid"?{status:"authenticated",token:e}:{status:"refresh-required",reason:i==="needs-refresh"?"near-expiry":"expired"}}return this.licenseKey?{status:"refresh-required",reason:"unavailable"}:{status:"not-configured"}}catch{return this.licenseKey?{status:"refresh-required",reason:"unavailable"}:{status:"not-configured"}}}async activate(){if(this.strictReadOnly)return null;try{const e=this.licenseKey.startsWith("nxk_"),i=e?"activate-key":"activate",t=e?{api_key:this.licenseKey}:{license_key:this.licenseKey},r=await fetch(`${this.serverUrl}/api/v1/license/${i}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,machine_id:this.machineId,client_version:this.clientVersion})});if(!r.ok)return null;const n=await r.json();return n.tier!==void 0&&n.tier!=="free"&&n.tier!=="pro"&&n.tier!=="enterprise"?null:(this.token=n.token,this.refreshToken=n.refresh_token??null,await this.cache.set(a,n.token,n.expires_in*1e3).catch(()=>{}),n.refresh_token&&await this.cache.set(s,n.refresh_token,c).catch(()=>{}),{token:n.token,expiresIn:n.expires_in,refreshToken:n.refresh_token,tier:n.tier})}catch{return null}}async refresh(e){if(this.strictReadOnly)return null;try{const i=this.refreshToken??await this.loadRefreshTokenFromCache();if(!i)return null;const t=await fetch(`${this.serverUrl}/api/v1/license/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:i})});if(!t.ok)return this.refreshToken=null,await this.cache.set(s,"",1).catch(()=>{}),null;const r=await t.json();return this.token=r.token,this.refreshToken=r.refresh_token??null,await this.cache.set(a,r.token,r.expires_in*1e3).catch(()=>{}),r.refresh_token&&await this.cache.set(s,r.refresh_token,c).catch(()=>{}),{token:r.token,expiresIn:r.expires_in,refreshToken:r.refresh_token}}catch{return null}}async forceRefresh(){if(this.strictReadOnly)return null;try{const e=await this.refresh();return e?.token?e.token:(this.token=null,this.refreshToken=null,await this.cache.clear().catch(()=>{}),(await this.activate())?.token??null)}catch{return null}}checkTokenValidity(e){try{const i=h(e);if(!i.exp)return"expired";const t=Math.floor(Date.now()/1e3);return i.exp<=t?"expired":i.exp-t<=f?"needs-refresh":"valid"}catch{return"expired"}}async loadFromCache(){try{return await this.cache.get(a)}catch{return null}}async loadRefreshTokenFromCache(){try{const e=await this.cache.get(s);return e&&e.length>0?e:null}catch{return null}}}export{w as LicenseClient};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function invalidProjectMemoryPath(reason: 'invalid' | 'out-of-scope'): never;
|
|
2
|
+
export declare function isValidScopedRelativePath(path: unknown): path is string;
|
|
3
|
+
/** Reject unsafe paths before canonical content or any target is read or written. */
|
|
4
|
+
export declare function assertProjectMemoryPaths(projectRoot: string, relativeFiles: readonly string[]): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{lstatSync as E,readlinkSync as P,realpathSync as S}from"node:fs";import{dirname as A,isAbsolute as u,join as m,relative as O,resolve as d,sep as R,win32 as g}from"node:path";import{CANONICAL_PROJECT_MEMORY_SOURCE as p}from"./shared-project-memory-types.js";function t(o){throw new Error(`project-memory-path-${o}`)}function j(o){return typeof o=="string"&&o.length>0&&!o.startsWith("~")&&!o.includes("\\")&&!o.includes("\0")&&!u(o)&&!g.isAbsolute(o)&&!/^[a-zA-Z]:/.test(o)&&!o.split("/").some(e=>e===""||e==="."||e==="..")}function N(o,e){let i;try{i=S(o)}catch{t("out-of-scope")}const y=m(i,p);for(const r of e){j(r)||t("invalid");const h=d(i,r),c=O(i,h);(c===""||c===".."||c.startsWith(`..${R}`)||u(c))&&t("out-of-scope");const s=r.split("/");for(let n=0;n<s.length;n++){const l=m(i,...s.slice(0,n+1));let f;try{f=E(l)}catch(v){if(v.code==="ENOENT")continue;t("out-of-scope")}if(!f.isSymbolicLink())continue;(n!==s.length-1||r===p)&&t("out-of-scope");let a;try{a=P(l)}catch{t("out-of-scope")}d(A(l),a)!==y&&t("out-of-scope")}}}export{N as assertProjectMemoryPaths,t as invalidProjectMemoryPath,j as isValidScopedRelativePath};
|
|
@@ -21,6 +21,8 @@ export interface WriteProjectMemoryOptions {
|
|
|
21
21
|
readonly fs?: ProjectMemoryWriterFs;
|
|
22
22
|
readonly symlinkCapability?: ProjectMemorySymlinkCapability;
|
|
23
23
|
readonly dryRun?: boolean;
|
|
24
|
+
/** Root lifecycle backups stay outside the project write claim. */
|
|
25
|
+
readonly backupDirectory?: string;
|
|
24
26
|
}
|
|
25
27
|
export interface ProjectMemorySymlinkCapability {
|
|
26
28
|
readonly os: NodeJS.Platform | string;
|
|
@@ -54,7 +56,7 @@ export interface WriteProjectMemoryTargetFilesResult {
|
|
|
54
56
|
readonly files: readonly WriteProjectMemoryFileResult[];
|
|
55
57
|
readonly changed: boolean;
|
|
56
58
|
}
|
|
57
|
-
export declare function createNodeProjectMemoryFs(): ProjectMemoryWriterFs;
|
|
59
|
+
export declare function createNodeProjectMemoryFs(backupDirectory?: string): ProjectMemoryWriterFs;
|
|
58
60
|
export declare const PROJECT_MEMORY_LAYER_CATEGORIES: readonly ["skills-agents", "frontend", "backend", "api", "db", "schemas", "envs", "devops", "cyber-security", "testing-qa", "observability", "product-business", "docs-architecture", "platform-memory", "command-behavior", "generic"];
|
|
59
61
|
export type ProjectMemoryLayerCategory = typeof PROJECT_MEMORY_LAYER_CATEGORIES[number];
|
|
60
62
|
export type ProjectMemoryChangeKind = 'feature' | 'rule' | 'flag' | 'route' | 'api' | 'db-schema' | 'architecture' | 'debt' | 'decision' | 'generic';
|
|
@@ -68,6 +70,7 @@ export interface ClassifiedProjectMemoryUpdate {
|
|
|
68
70
|
export declare function classifyProjectMemoryUpdate(value: string): ClassifiedProjectMemoryUpdate;
|
|
69
71
|
export declare function createSafeProjectMemoryDiff(before: string | undefined, after: string): string;
|
|
70
72
|
export declare function bootstrapArchitectureMemory(projectRoot: string): BootstrapArchitectureMemory;
|
|
73
|
+
export declare function shouldUseManagedWrapper(target: ProjectMemoryTarget, relativeFile: string): boolean;
|
|
71
74
|
export declare function buildProjectMemoryContent(target: ProjectMemoryTarget, existingContent: string | undefined, memoryNotes?: readonly string[], architectureReferences?: readonly ArchitectureReference[], bootstrapArchitecture?: BootstrapArchitectureMemory): string;
|
|
72
75
|
export declare function writeProjectMemory(options: WriteProjectMemoryOptions): WriteProjectMemoryResult;
|
|
73
76
|
export declare function writeCanonicalProjectMemory(options: Omit<WriteProjectMemoryOptions, 'targetId'>): WriteProjectMemoryResult;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import{randomUUID as
|
|
2
|
-
`).length>e.budget.maxLines||Buffer.byteLength(t,"utf8")>e.budget.maxBytes)throw new Error("Canonical project memory update exceeds its context budget; refusing to truncate existing content.")}function
|
|
1
|
+
import{randomUUID as U}from"node:crypto";import{constants as V,existsSync as g,lstatSync as C,mkdirSync as O,copyFileSync as j,readdirSync as Q,readFileSync as E,readlinkSync as ee,realpathSync as we,renameSync as te,rmSync as N,statSync as Ee,symlinkSync as B,unlinkSync as re,writeFileSync as q}from"node:fs";import{platform as M}from"node:os";import{basename as Re,dirname as I,join as p,relative as Se,resolve as Ce}from"node:path";import{CANONICAL_PROJECT_MEMORY_SOURCE as b,getProjectMemoryTarget as W,renderArchitectureReferenceTable as Pe}from"./shared-project-memory-types.js";import{assertProjectMemoryPaths as F,invalidProjectMemoryPath as $e,isValidScopedRelativePath as Te}from"./project-memory-path-scope.js";function ne(e){return(e.memoryNotes?.length??0)>0||(e.architectureReferences?.length??0)>0||e.bootstrapArchitecture!==void 0}const X="<!-- NEOCORTEX-REFRESH-UPDATES-START -->",z="<!-- NEOCORTEX-REFRESH-UPDATES-END -->";function A(e,t){return e.split(t).length-1}function ve(e){ce(e.memoryNotes??[],e.architectureReferences??[],e.bootstrapArchitecture);const t=G(e.memoryNotes??[]).map(r=>`- [${r.reasonCode}] ${r.summary} (layer: ${r.layer})`),n=(e.architectureReferences??[]).map(r=>`- [architecture-reference] \`${r.path}\`: ${r.title}; ${r.purpose}; use: ${r.suggestedUsage}`),o=e.bootstrapArchitecture,s=o===void 0?[]:[...(o.universalLaws??[]).map(r=>`- [bootstrap-law] ${r}`),...(o.businessContext??[]).map(r=>`- [bootstrap-business] ${r}`),...(o.activeContext??[]).map(r=>`- [bootstrap-context] ${r}`),...(o.repositoryMap??[]).map(r=>`- [bootstrap-repository] ${r}`),...(o.environmentPractices??[]).map(r=>`- [bootstrap-environment] ${r}`),...(o.platformMemoryContract??[]).map(r=>`- [bootstrap-platform] ${r}`),...(o.maintenanceRules??[]).map(r=>`- [bootstrap-maintenance] ${r}`),...(o.heuristics??[]).map(r=>`- [bootstrap-heuristic] ${r}`)];return w([...t,...n,...s])}function xe(e,t){if(t.split(`
|
|
2
|
+
`).length>e.budget.maxLines||Buffer.byteLength(t,"utf8")>e.budget.maxBytes)throw new Error("Canonical project memory update exceeds its context budget; refusing to truncate existing content.")}function oe(e,t,n){const o=ve(n);if(o.length===0)return t;const s=t.includes(`\r
|
|
3
3
|
`)?`\r
|
|
4
4
|
`:`
|
|
5
|
-
`,
|
|
5
|
+
`,r=$(e),a=L(e),c=A(t,r),u=A(t,a);if(c!==1||u!==1||t.indexOf(a)<t.indexOf(r))throw new Error("Canonical project memory has ambiguous managed-block markers; refusing refresh.");const l=A(t,X),i=A(t,z);if(l!==i||l>1)throw new Error("Canonical project memory has ambiguous refresh-update markers; refusing refresh.");let d;if(l===0){const m=t.indexOf(a),h=t.slice(0,m),k=[X,"## Durable Refresh Updates",...o,z,""].join(s);d=`${h}${h.endsWith(s)?"":s}${k}${t.slice(m)}`}else{const m=t.indexOf(X),h=t.indexOf(z),k=t.indexOf(r),R=t.indexOf(a);if(m<k||h>R||h<m)throw new Error("Canonical refresh-update block is outside the managed block; refusing refresh.");const _=t.slice(m,h),D=new Set(_.split(/\r?\n/).map(S=>S.trim().toLowerCase())),f=o.filter(S=>!D.has(S.trim().toLowerCase()));if(f.length===0)return t;const x=t.slice(0,h);d=`${x}${x.endsWith(s)?"":s}${f.join(s)}${s}${t.slice(h)}`}return xe(e,d),d}function Oe(e){return{readFile(t){try{return E(t,"utf8")}catch{return}},writeFileAtomic(t,n){O(I(t),{recursive:!0});const o=U(),s=`${t}.tmp-${o}`,r=g(t)?fe(t,o,e):void 0;try{return q(s,n,{encoding:"utf8",flag:"wx",mode:384}),r!==void 0&&j(t,r,V.COPYFILE_EXCL),te(s,t),{backupPath:r}}catch(a){if(N(s,{force:!0}),r!==void 0&&g(r))try{j(r,t)}catch{}throw a}},join(...t){return p(...t)}}}function $(e){return`<!-- ${e.ownedBlockName}-START -->`}function L(e){return`<!-- ${e.ownedBlockName}-END -->`}function w(e){const t=new Set,n=[];for(const o of e){const s=o.trim().replace(/\s+/g," ");s.length===0||t.has(s.toLowerCase())||(t.add(s.toLowerCase()),n.push(s))}return n}function je(e){const t=new Set,n=[];for(const o of e)t.has(o.path)||(t.add(o.path),n.push(o));return n}function Ne(e){switch(e.templateKind){case"neocortex-md":return"# NEOCORTEX.md Project Memory";case"claude-md":return"# CLAUDE.md Project Memory";case"agents-md":return"# AGENTS.md Project Instructions";case"gemini-md":return"# GEMINI.md Project Memory";case"copilot-instructions":return"# GitHub Copilot Repository Instructions";case"cursor-rule":return`---
|
|
6
6
|
description: Neocortex project memory
|
|
7
7
|
alwaysApply: true
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# Cursor Project Memory`}}const
|
|
10
|
+
# Cursor Project Memory`}}const Me=["Keep always-loaded memory compact: laws, active context, and references only.","Preserve human-authored instructions outside this owned block.","Prefer repository SSoT docs over duplicating architecture details here."],Ie=["Consult `docs/architecture/` before changes that affect architecture, contracts, data, security, performance, UX, or infrastructure.","Reference architecture documents by repository path, such as `docs/architecture/architecture.md`, before changing related implementation.","Summarize decisions and trade-offs in NEOCORTEX.md; do not paste complete architecture documents into memory.","Update memory for durable cross-layer changes across skills/agents, frontend, backend, API, DB, schemas, envs, DevOps, cyber security, testing/QA, observability, product, docs, and platform contracts.","Prioritize compact summaries of durable decisions, public contracts, operational risks, debts, command behavior, and repository paths; skip transient logs, raw payloads, secrets, private prompts, long documents, and duplicated canonical sources.","Keep platform memory files symlink-backed or include-backed to NEOCORTEX.md when supported."],it=["skills-agents","frontend","backend","api","db","schemas","envs","devops","cyber-security","testing-qa","observability","product-business","docs-architecture","platform-memory","command-behavior","generic"],Ae=360,se={feature:"Features",rule:"Rules/Policies",flag:"Flags",route:"Routes",api:"APIs/Contracts","db-schema":"DB/Schema",architecture:"Architecture",debt:"Debts",decision:"Decisions",generic:"General Updates"},Le=/\b(private|proprietary|server[- ]only|system)\s+prompt\b|\b(api[-_ ]?key|license[-_ ]?key|password|authorization|bearer|token|secret)\s*[:=]|\b(ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|xox[baprs]-[A-Za-z0-9-]+)\b|\b(customer|cliente)\s+(payload|record|email|phone)\b|\b(customer|cliente)\s+(data|dados)\s+(payload|record|email|phone)\b|\b(customer|cliente)\s+(data|dados)\s*[:=]|\braw\s+payload\b/i;function _e(e){const t=e.toLowerCase();return/\b(project memory|canonical memory|memory heuristic|neocortex\.md|\*update-memory)\b/.test(t)?"decision":/\b(feature|capability|funcionalidade|release)\b/.test(t)?"feature":/\b(rule|policy|guardrail|regra|lei|must|never)\b/.test(t)?"rule":/\b(flag|feature[- ]?flag|toggle|env var|environment variable)\b/.test(t)?"flag":/\b(api|contract|schema contract|graphql|rest|rpc|webhook)\b/.test(t)?"api":/\b(db|database|schema|migration|table|column|prisma|sql)\b/.test(t)?"db-schema":/\b(decision|decisão|decisao|accepted|rejected|trade[- ]?off)\b/.test(t)?"decision":/\b(route|endpoint route|url path|pathname)\b|\/(api|admin|portal|v\d+)\//.test(t)?"route":/\b(architecture|arquitetura|adr|topology|infra|boundary)\b/.test(t)?"architecture":/\b(debt|follow[- ]?up|todo|tech[- ]?debt|dívida|divida)\b/.test(t)?"debt":"generic"}function De(e){const t=e.toLowerCase();return/\b(neocortex\.md|project memory|canonical memory|memory wrapper|symlink|owned block|memory heuristic)\b/.test(t)?"platform-memory":/\b(command|cli|\*update-memory|\*create-epic|\*arch-plan|workflow behavior)\b/.test(t)?"command-behavior":/\b(skill|agent|subagent|orchestrator|opencode|codex|claude|gemini|cursor)\b/.test(t)?"skills-agents":/\b(frontend|ui|ux|react|component|design[- ]?system|css|accessibility|a11y)\b/.test(t)?"frontend":/\b(backend|server|service|worker|job|queue)\b/.test(t)?"backend":/\b(api|endpoint|rest|graphql|rpc|webhook|contract)\b/.test(t)?"api":/\b(db|database|table|column|migration|sql|prisma)\b/.test(t)?"db":/\b(schema|schemas|zod|json schema|protobuf|openapi)\b/.test(t)?"schemas":/\b(env|environment|\.env\.example|config|configuration|feature[- ]?flag)\b/.test(t)?"envs":/\b(devops|deploy|deployment|ci|cd|docker|container|kubernetes|infra|terraform|rollback)\b/.test(t)?"devops":/\b(security|cyber|auth|authorization|permission|compliance|vulnerability|secret|token redaction)\b/.test(t)?"cyber-security":/\b(test|testing|qa|e2e|unit|integration|snapshot|property[- ]?based|flaky)\b/.test(t)?"testing-qa":/\b(observability|metric|metrics|log|logging|trace|tracing|alert|monitoring|slo)\b/.test(t)?"observability":/\b(product|business|user journey|onboarding|pricing|tenant|customer-facing)\b/.test(t)?"product-business":/\b(docs|documentation|architecture|arquitetura|adr|runbook|decision record)\b/.test(t)?"docs-architecture":"generic"}function ae(e){const t=e.trim().replace(/\s+/g," ");if(Buffer.byteLength(t,"utf8")<=Ae)return t;const n=t.match(/(?:^|\s)([\w.-]+(?:\/[\w.@-]+)+(?:\.[A-Za-z0-9]+)?)/)?.[1],o=t.slice(0,220).replace(/\s+\S*$/,"").trim();return n?`${o}\u2026 See ${n} for details.`:`${o}\u2026 Details omitted from always-loaded memory; keep source content in repository docs.`}function Ue(e){y(e);const t=_e(e),n=De(e);return{kind:t,layer:n,sectionTitle:se[t],summary:ae(e),reasonCode:`memory_update_${t.replace("-","_")}`}}function G(e){const t=new Set,n=[];for(const o of e){const s=Ue(o),r=`${s.kind}:${s.summary.toLowerCase()}`;t.has(r)||(t.add(r),n.push(s))}return n}function y(e){if(Le.test(e))throw new Error("Project memory input violates IP boundary guardrails.")}function ie(e,t){const n=(e??"").split(`
|
|
11
11
|
`),o=t.split(`
|
|
12
|
-
`),
|
|
13
|
-
`);return
|
|
14
|
-
`)}function
|
|
15
|
-
`)}const
|
|
16
|
-
${t.slice(0,2e3)}`),o=t.replace(/^---[\s\S]*?---\s*/,"").split(/\n{2,}/).map(
|
|
12
|
+
`),s=[],r=Math.max(n.length,o.length);for(let c=0;c<r;c++){const u=n[c],l=o[c];if(u!==l&&(u!==void 0&&s.push(`- ${u}`),l!==void 0&&s.push(`+ ${l}`),s.length>=80)){s.push("\u2026 diff truncated; inspect repository diff for full context.");break}}const a=s.join(`
|
|
13
|
+
`);return y(a),a}function H(e){y(e.path),y(e.title),y(e.purpose),y(e.suggestedUsage)}function ce(e,t,n){e.forEach(y),t.forEach(H),n?.universalLaws?.forEach(y),n?.businessContext?.forEach(y),n?.activeContext?.forEach(y),n?.repositoryMap?.forEach(y),n?.environmentPractices?.forEach(y),n?.platformMemoryContract?.forEach(y),n?.maintenanceRules?.forEach(y),n?.heuristics?.forEach(y),n?.importantReferences?.forEach(H),n?.architectureReferences?.forEach(H)}function ue(e){return[Ne(e),"","This file contains compact, always-loaded project memory. Keep detailed architecture in referenced docs.",""].join(`
|
|
14
|
+
`)}function de(e,t,n,o){ce(t,n,o);const s=w([...Me,...o?.universalLaws??[]]),r=w([...o?.activeContext??[],...t.map(ae)]),a=G(t),c=w(o?.businessContext??["Product/business context was not explicitly documented during bootstrap; treat conclusions as repository-inferred until a human updates this section."]),u=w(o?.repositoryMap??["Source, tests, package/build files, docs, CI, and runtime manifests are the permitted bootstrap sources for repository orientation."]),l=w(o?.environmentPractices??["Use `.env.example` for configuration shape only; do not read real environment files or credential-bearing files into always-loaded memory."]),i=w(o?.platformMemoryContract??["Semantic platform memory file must resolve to NEOCORTEX.md through a symlink; do not replace it with an unrelated wrapper or copied frontmatter.","Platform wrapper/frontmatter must be preserved via split/include/managed block while the semantic memory payload remains symlink-backed by NEOCORTEX.md."]),d=w(o?.maintenanceRules??["Keep NEOCORTEX.md deterministic, compact, objective, and direct; store only summaries, indexes, and links to detailed docs.","Do not copy protected prompt bodies, proprietary wrappers, server-side internals, customer data, license keys, or long document bodies into always-loaded memory."]),m=je([...o?.importantReferences??[],...o?.architectureReferences??[],...n]),h=w([...Ie,...o?.heuristics??[]]),k=s.map(f=>`- ${f}`),R=r.length>0?r.map(f=>`- ${f}`):["- No active project notes recorded."],_=m.length>0?Pe(m):"No architecture references discovered.",D=a.length>0?Object.entries(se).flatMap(([f,x])=>{const S=a.filter(P=>P.kind===f);return S.length>0?[`### ${x}`,...S.map(P=>`- [${P.reasonCode}] ${P.summary} (layer: ${P.layer})`)]:[]}):["- No durable change feedback recorded."];return[$(e),"## Universal Project Laws",...k,"","## Business/Product Context",...c.map(f=>`- ${f}`),"","## Active Context",...R,"","## Durable Change Feedback",...D,"","## Architecture References",_,"","## Repository Map",...u.map(f=>`- ${f}`),"","## Environment/Container/Production/Security/Dev Practices",...l.map(f=>`- ${f}`),"","## Platform Memory Contract",...i.map(f=>`- ${f}`),`- NEOCORTEX.md is the canonical project memory source for every platform target; run \`${e.bidirectionalReference.feedbackTrigger}\` when durable context discovered in a platform wrapper should be fed back into canonical memory.`,"","## Maintenance Rules",...d.map(f=>`- ${f}`),"","## Architecture Heuristics",...h.map(f=>`- ${f}`),L(e)].join(`
|
|
15
|
+
`)}const le=["docs/architecture","docs/arquitetura-software"],Be=["README.md","readme.md","architecture.md","docs/architecture.md"],qe=["package.json","pnpm-lock.yaml","package-lock.json","yarn.lock","tsconfig.json","vite.config.ts","turbo.json"],We=["Dockerfile","docker-compose.yml","compose.yml",".env.example","fly.toml"],Fe=["AGENTS.md","CLAUDE.md","GEMINI.md",".opencode/AGENTS.md",".cursor/rules/neocortex.mdc"];function me(e,t,n=24e3){const o=p(e,t);try{if(!g(o)||C(o).isDirectory())return;const s=E(o,"utf8");return s.length<=n?s:s.slice(0,n)}catch{return}}function fe(e,t,n){if(!n)return`${e}.bak-${t}`;const o=Ce(n),s=C(o);if(!s.isDirectory()||s.isSymbolicLink()||s.uid!==process.getuid?.()||(s.mode&63)!==0||we(o)!==o)throw new Error("project-memory-backup-directory-unsafe");return p(o,`${Re(e)}.bak-${t}`)}function Y(e,t,n){O(I(e),{recursive:!0});const o=U(),s=`${e}.tmp-${o}`,r=g(e)?fe(e,o,n):void 0;try{return q(s,t,{encoding:"utf8",flag:"wx",mode:384}),r!==void 0&&j(e,r,V.COPYFILE_EXCL),te(s,e),r}catch(a){if(N(s,{force:!0}),r!==void 0&&g(r))try{j(r,e)}catch{}throw a}}function K(e){return Array.from(new Set(G(e).map(t=>t.reasonCode)))}function T(e,t){try{return g(p(e,t))}catch{return!1}}function Xe(e,t){try{return Q(p(e,t),{withFileTypes:!0}).filter(n=>!n.name.startsWith(".")&&!n.name.toLowerCase().includes("secret")).sort((n,o)=>n.name.localeCompare(o.name)).slice(0,8).map(n=>`${t}/${n.name}${n.isDirectory()?"/":""}`)}catch{return[]}}function pe(e,t,n=16){try{const o=Q(p(e,t),{withFileTypes:!0}).filter(r=>!r.name.startsWith(".")&&!r.name.startsWith("_")).sort((r,a)=>r.name.localeCompare(a.name)),s=[];for(const r of o){const a=`${t}/${r.name}`;if(r.isDirectory()?s.push(...pe(e,a,n-s.length)):/\.(md|markdown)$/i.test(r.name)&&s.push(a),s.length>=n)break}return s}catch{return[]}}function ze(e,t){const n=t.match(/^#\s+(.+?)\s*$/m)?.[1]?.trim();return n?n.replace(/[`*_#]/g,""):e.split("/").pop()?.replace(/\.(md|markdown)$/i,"").replace(/[-_]+/g," ")??e}function Ge(e,t){const n=/\b(stale|deprecated|outdated|incerto|uncertain)\b/i.test(`${e}
|
|
16
|
+
${t.slice(0,2e3)}`),o=t.replace(/^---[\s\S]*?---\s*/,"").split(/\n{2,}/).map(r=>r.replace(/^#+\s+.+$/gm,"").replace(/[`*_>#]/g,"").replace(/\s+/g," ").trim()).find(r=>r.length>0&&!r.startsWith("|"));return`${n?"[stale/uncertain evidence] ":""}${(o??"Architecture reference for this project.").slice(0,180)}`}function He(e){const t=e.toLowerCase();return/deploy|infra|docker|production|runbook/.test(t)?"Use before changing deployment, runtime, containers, or production operations.":/security|auth|compliance/.test(t)?"Use before changing auth, compliance, or security-sensitive behavior.":/api|contract|state|schema/.test(t)?"Use before changing contracts, APIs, schemas, or persisted state.":"Use before implementation in this area; verify freshness when marked stale or uncertain."}function ye(e){const t=qe.filter(i=>T(e,i)),n=We.filter(i=>T(e,i)),o=Fe.filter(i=>T(e,i)),s=["packages","src","apps","tests","__tests__"].filter(i=>T(e,i)),a=[...le.flatMap(i=>pe(e,i)),...Be.filter(i=>T(e,i))].slice(0,24).flatMap(i=>{const d=me(e,i,48e3);return d?[{path:i,title:ze(i,d),purpose:Ge(i,d),suggestedUsage:He(i),source:le.some(m=>i.startsWith(`${m}/`))?"architecture-root":"fallback-file"}]:[]}),c=me(e,"package.json"),u=c?.match(/"name"\s*:\s*"([^"]+)"/)?.[1],l=[...c?.matchAll(/"(test|build|lint|typecheck|dev)"\s*:/g)??[]].map(i=>i[1]);return{universalLaws:["Bootstrap canonical memory before creating or repairing platform memory wrappers when NEOCORTEX.md is absent.","Use only permitted repository sources for bootstrap: package/build files, architecture docs, README/deploy docs, .env.example, runtime manifests, CI, source/test layout, and platform memory wrappers."],businessContext:[u?`Repository package name: ${u}.`:"Repository product name was not declared in package metadata.","Business/product conclusions are bootstrap-inferred and must be refined from canonical docs or human input."],activeContext:[`Bootstrap scanned ${t.length} package/build files, ${a.length} architecture/readme docs, ${n.length} runtime/config templates, and ${o.length} platform memory wrappers.`,l.length>0?`Detected quality scripts: ${l.sort().join(", ")}.`:"No standard quality scripts were detected in package metadata."],repositoryMap:[t.length>0?`Package/build files: ${t.join(", ")}.`:"No package/build files detected in permitted bootstrap set.",s.length>0?`Source/test roots: ${s.flatMap(i=>Xe(e,i)).slice(0,16).join(", ")}.`:"Source/test roots were not detected in standard locations.",o.length>0?`Platform memory/wrappers: ${o.join(", ")}.`:"No platform memory wrappers detected before bootstrap."],environmentPractices:[n.length>0?`Runtime/config templates: ${n.join(", ")}.`:"No Docker/compose/.env.example/runtime manifest detected in permitted bootstrap set.","Read `.env.example` only for configuration shape; never ingest real .env files, credentials, customer data, or license keys into memory.","Run repository quality scripts before commit and keep CI/deploy evidence referenced by path or URL rather than copied verbatim."],platformMemoryContract:["Semantic platform memory file must resolve to NEOCORTEX.md through a symlink; do not replace it with an unrelated wrapper or copied frontmatter.","Preserve wrappers/frontmatter via split/include/managed block while the semantic memory payload remains symlink-backed by NEOCORTEX.md."],maintenanceRules:["Generated memory must be deterministic, objective, direct, compact, and inside the target always-loaded context budget.","Cite long architecture docs by path with usage guidance; mark stale or uncertain docs when repository evidence indicates that status.","Do not copy protected prompt bodies, proprietary wrappers, server internals, secrets, customer data, license keys, or complete long documents."],architectureReferences:a,heuristics:["Before processing a story, consult the cited Architecture References whose path or suggested usage intersects the change.","When a referenced doc is marked stale/uncertain, validate against current package/runtime/source evidence before relying on it."]}}function J(e,t,n){const o=$(t),s=L(t),r=e.indexOf(o),a=e.indexOf(s);if(r>=0&&a>=r){const u=a+s.length;return`${e.slice(0,r)}${n}${e.slice(u)}`}const c=e.endsWith(`
|
|
17
17
|
`)?`
|
|
18
18
|
`:`
|
|
19
19
|
|
|
20
|
-
`;return`${e}${
|
|
21
|
-
`}function
|
|
20
|
+
`;return`${e}${c}${n}
|
|
21
|
+
`}function Ye(e){return e.endsWith(".mdc")?`---
|
|
22
22
|
description: Neocortex project memory
|
|
23
23
|
alwaysApply: true
|
|
24
24
|
---
|
|
@@ -32,9 +32,9 @@ name: neocortex
|
|
|
32
32
|
description: Neocortex project memory wrapper
|
|
33
33
|
---
|
|
34
34
|
|
|
35
|
-
`:""}function
|
|
35
|
+
`:""}function be(e,t){const n=I(p(e,t)),o=p(e,b),s=Se(n,o);return s.length>0?s:b}function v(e,t){return!!(e.targetId==="canonical"||e.requiresWrapperPreservation||e.linkRequirement.requiresWrapperPreservation||e.linkRequirement.wrapperAllowed||t==="AGENTS.md"||t.includes("/agents/")||t.includes("/skills/")||t.endsWith(".toml")||t.endsWith(".mdc")||t.endsWith(".agent.md")||t.endsWith(".instructions.md"))}function Ke(e){return e.linkRequirement.symlinkBacked&&e.linkRequirement.semanticFileRequired}function Z(e){return/EPERM|EACCES|operation not permitted|permission/i.test(e)?"EPERM: symlink permission denied":/ENOSYS|ENOTSUP|EOPNOTSUPP|not supported/i.test(e)?"symlink filesystem unsupported":"symlink capability unavailable"}function he(e,t,n,o,s=!1){if(o!==void 0)return o;const r=Ke(t);if(!r)return{os:M(),supported:!1,permission:"unknown",filesystem:"unknown",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:r,requiresWrapperPreservation:v(t,n),reason:`target policy ${t.linkRequirement.policy} does not allow semantic symlink orchestration`};if(s)return{os:M(),supported:!0,permission:"unknown",filesystem:"unknown",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:r,requiresWrapperPreservation:v(t,n),reason:"dry-run does not probe filesystem symlink support"};const a=p(e,".neocortex","tmp"),c=U(),u=p(a,`symlink-capability-source-${c}`),l=p(a,`symlink-capability-link-${c}`);try{O(a,{recursive:!0}),q(u,"probe",{encoding:"utf8",flag:"wx",mode:384}),B(u,l);const i=C(l).isSymbolicLink()&&Ee(l).isFile();return{os:M(),supported:i,permission:i?"ok":"unknown",filesystem:i?"supports-symlink":"no-symlink-support",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:r,requiresWrapperPreservation:v(t,n),reason:i?void 0:"filesystem probe did not create a resolvable symbolic link"}}catch(i){const d=i instanceof Error?i.message:String(i),m=/EPERM|EACCES|operation not permitted|permission/i.test(d);return{os:M(),supported:!1,permission:m?"denied":"unknown",filesystem:"no-symlink-support",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:r,requiresWrapperPreservation:v(t,n),reason:Z(d)}}finally{N(l,{force:!0}),N(u,{force:!0})}}function Je(e,t,n,o){const s=be(o,t),r=n??`${Ye(t)}# ${e.platformName} Neocortex Memory Wrapper
|
|
36
36
|
|
|
37
|
-
`,a=[
|
|
38
|
-
`);return
|
|
39
|
-
`)}${
|
|
40
|
-
`).length<=e.budget.maxLines&&Buffer.byteLength(
|
|
37
|
+
`,a=[$(e),"## Canonical Project Memory Source","",`This platform wrapper preserves host-specific frontmatter/instructions while resolving project memory to \`${s}\`.`,"",`- Canonical source: \`${b}\``,`- Symlink-backed/source-of-truth file: \`${s}\``,`- Feedback loop: read \`${s}\` for shared context and run \`${e.bidirectionalReference.feedbackTrigger}\` when durable platform findings should update \`${b}\`.`,"- Human-authored content outside this managed block is preserved byte-for-byte.",L(e)].join(`
|
|
38
|
+
`);return J(r,e,a)}function ge(e,t,n,o,s,r=!1){const a=p(e,t),c=Z(s),l=`${["[NEOCORTEX COMPATIBILITY REMEDIATION]","Materialized project memory fallback because semantic symlink orchestration failed.","This is not product mode; repair host permissions/filesystem support and restore the symlink to NEOCORTEX.md.","WARNING: materialized fallback is remediation debt, not a silent mode; run *update-memory for durable context and repair this file back to canonical NEOCORTEX.md resolution.",`Fallback reason: ${c}`,""].join(`
|
|
39
|
+
`)}${n}`,d=(g(a)?E(a,"utf8"):void 0)!==l;return d&&!r&&(g(a)&&C(a).isSymbolicLink()&&re(a),Y(a,l)),{filePath:a,relativeFile:t,changed:d,content:l,mode:"compatibility-materialized-fallback",canonicalSource:b,symlinkCapability:o,fallbackReason:c,remediationDebt:`Repair ${t} so it is a symlink to ${b}; fallback is compatibility remediation only.`}}function Ze(e,t,n,o,s,r=!1){const a=p(e,t),c=be(e,t);r||O(I(a),{recursive:!0});const u=he(e,n,t,s,r);if(!u.supported)return ge(e,t,o,u,u.reason??"symlink capability detection reported unsupported host",r);if(r){let i=!0;try{i=!(g(a)&&C(a).isSymbolicLink()&&ee(a)===c)}catch{i=!0}return{filePath:a,relativeFile:t,changed:i,content:o,mode:"semantic-symlink",canonicalSource:b,symlinkCapability:u}}let l=!1;try{return g(a)?C(a).isSymbolicLink()&&ee(a)===c?l=!1:(re(a),B(c,a),l=!0):(B(c,a),l=!0),{filePath:a,relativeFile:t,changed:l,content:E(a,"utf8"),mode:"semantic-symlink",canonicalSource:b,symlinkCapability:u}}catch(i){const d=i instanceof Error?i.message:String(i),m=Z(d);return ge(e,t,o,{...u,supported:!1,permission:/EPERM|EACCES|operation not permitted|permission/i.test(d)?"denied":u.permission,filesystem:"no-symlink-support",reason:m},m,r)}}function Ve(e,t,n,o,s){const r=u=>u.split(`
|
|
40
|
+
`).length<=e.budget.maxLines&&Buffer.byteLength(u,"utf8")<=e.budget.maxBytes;if(r(t))return t;const a=de(e,n.slice(0,8),o.slice(0,12),s),c=J(t.includes($(e))?t:ue(e),e,a);return r(c)?c:c.slice(0,e.budget.maxBytes)}function ke(e,t,n=[],o=[],s){const r=t??ue(e),a=de(e,n,o,s),c=J(r,e,a);return Ve(e,c,n,o,s)}function Qe(e){const t=W(e.targetId),n=e.fs??Oe(e.backupDirectory),o=n.join(e.projectRoot,t.primaryFile);if(e.fs===void 0&&t.targetId==="canonical"&&F(e.projectRoot,[b]),t.targetId!=="canonical"&&e.fs===void 0){const u=et(e).files.find(l=>l.relativeFile===t.primaryFile);if(u===void 0)throw new Error(`Primary project memory file was not written for ${t.targetId}.`);return{filePath:u.filePath,changed:u.changed,content:u.content}}const s=n.readFile(o),r=e.bootstrapArchitecture??(e.fs===void 0&&t.targetId==="canonical"&&s===void 0?ye(e.projectRoot):void 0),a=t.targetId==="canonical"&&s!==void 0?ne(e)?oe(t,s,e):s:ke(t,s,e.memoryNotes,e.architectureReferences,r);if(s===a)return{filePath:o,changed:!1,content:a};const c=e.dryRun?void 0:n.writeFileAtomic(o,a);return{filePath:o,changed:!0,content:a,safeDiff:ie(s,a),backupPath:c?.backupPath,reasonCodes:K(e.memoryNotes??[])}}function ct(e){return Qe({...e,targetId:"canonical"})}function et(e){if(e.fs!==void 0)throw new Error("writeProjectMemoryTargetFiles requires the node filesystem to manage symlinks safely.");const t=W(e.targetId),n=W("canonical");t.secondaryFiles.some(d=>d===null||d.scope!=="project"&&d.scope!=="user"||!Te(d.path))&&$e("invalid");const o=Array.from(new Set([t.primaryFile,...t.targetId==="canonical"?[]:t.secondaryFiles.filter(d=>d.scope==="project").map(d=>d.path)]));F(e.projectRoot,[b,...o,".neocortex/tmp"]);const s=p(e.projectRoot,b),r=g(s)?E(s,"utf8"):void 0,a=e.bootstrapArchitecture??(r===void 0?ye(e.projectRoot):void 0),c=r!==void 0?ne(e)?oe(n,r,e):r:ke(n,r,e.memoryNotes,e.architectureReferences,a),u=!g(s)||E(s,"utf8")!==c;let l;if(u&&!e.dryRun&&(l=Y(s,c,e.backupDirectory)),t.targetId==="canonical")return{targetId:t.targetId,canonicalFilePath:s,changed:u,files:[{filePath:s,relativeFile:b,changed:u,content:c,mode:"canonical",canonicalSource:b,safeDiff:ie(r,c),backupPath:l,reasonCodes:K(e.memoryNotes??[])}]};const i=o.map(d=>{if(F(e.projectRoot,[d,".neocortex/tmp"]),!v(t,d))return Ze(e.projectRoot,d,t,c,e.symlinkCapability,e.dryRun);const m=p(e.projectRoot,d),h=g(m)?E(m,"utf8"):void 0,k=Je(t,d,h,e.projectRoot),R=h!==k;return R&&!e.dryRun&&Y(m,k,e.backupDirectory),{filePath:m,relativeFile:d,changed:R,content:k,mode:"managed-wrapper",canonicalSource:b,symlinkCapability:he(e.projectRoot,t,d,e.symlinkCapability,e.dryRun),reasonCodes:K(e.memoryNotes??[])}});return{targetId:t.targetId,canonicalFilePath:s,files:i,changed:u||i.some(d=>d.changed)}}export{it as PROJECT_MEMORY_LAYER_CATEGORIES,ye as bootstrapArchitectureMemory,ke as buildProjectMemoryContent,Ue as classifyProjectMemoryUpdate,Oe as createNodeProjectMemoryFs,ie as createSafeProjectMemoryDiff,v as shouldUseManagedWrapper,ct as writeCanonicalProjectMemory,Qe as writeProjectMemory,et as writeProjectMemoryTargetFiles};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { DirectYoloSetupReceipt } from '../git/direct-yolo-checkpoint.js';
|
|
2
2
|
export declare function privateYoloRootOnlySetupReady(story: unknown): boolean;
|
|
3
|
+
/** A later C01 lease receives its own record names; historical records stay immutable. */
|
|
4
|
+
export declare function privateYoloRecordLocation(root: string, storyId: string, kind: 'baseline' | 'session', currentSetupSessionId: string): Promise<{
|
|
5
|
+
parent: string;
|
|
6
|
+
name: string;
|
|
7
|
+
path: string;
|
|
8
|
+
}>;
|
|
3
9
|
/** Call immediately before root C01 setup; a dirty or ambiguous checkout fails closed. */
|
|
4
10
|
export declare function capturePrivateYoloCleanHead(projectRoot: string): string;
|
|
5
11
|
/** Persist only after physical setup succeeded without changing the clean HEAD. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{execFileSync as
|
|
2
|
-
`)}async function
|
|
1
|
+
import{execFileSync as H}from"node:child_process";import{createHash as b}from"node:crypto";import{existsSync as m,lstatSync as N,readFileSync as d}from"node:fs";import{join as x,resolve as y}from"node:path";import{assertGitLifecyclePrivateFile as w,ensureGitLifecyclePrivateChildDirectory as W,gitLifecycleRuntimeDirectory as z,readGitLifecycleRuntimeSync as v}from"../git/git-lifecycle-store.js";import{anchoredAtomicWriteFile as C}from"../git/secure-filesystem-boundary.js";const D="809db253d486b5d2620d318666219e8a2b4df05016174ba3c8a33fa17b65802a";function $(r){if(!r||typeof r!="object"||Array.isArray(r))return!1;const e=r,t=e.steps_completed;return e.status!=="branch-ready"||typeof e.last_step!="string"||!Array.isArray(t)||t.length!==1||typeof t[0]!="string"||e.last_step.length>128||t[0].length>128||e.last_step!==t[0]?!1:b("sha256").update(e.last_step).digest("hex")===D}function S(r,e){const t=JSON.parse(r);if(!t||typeof t!="object"||Array.isArray(t))throw new Error("private-execution-clean-baseline-write-set-invalid");const n=t.stories,c=n&&typeof n=="object"&&!Array.isArray(n)?n[e]:void 0,i=c&&typeof c=="object"&&!Array.isArray(c)?c.files_to_modify:void 0;if(i!==void 0&&(!Array.isArray(i)||i.length>1024||i.some(s=>typeof s!="string"||s.length===0||s.length>1024||s.startsWith("/")||s.includes("\\")||s.includes("\0")||s.startsWith(".git/")||s.split("/").includes(".."))))throw new Error("private-execution-clean-baseline-write-set-invalid");if(!c)throw new Error("private-execution-clean-baseline-write-set-invalid");return[...new Set(i??[])].sort()}function I(r,e){const t=S(r,e);return b("sha256").update("private-yolo-authorized-write-set-v1\0").update(JSON.stringify(t)).digest("hex")}function _(r,e){const t=x(r,".neocortex","state.json"),n=N(t);if(!n.isFile()||n.isSymbolicLink())throw new Error("private-execution-clean-baseline-write-set-invalid");return I(d(t,"utf8"),e)}function O(r,e){return I(f(r,["show","HEAD:.neocortex/state.json"],16*1024*1024).toString("utf8"),e)}function f(r,e,t=1024*1024){const n={...process.env};for(const c of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete n[c];return H("git",[...e],{cwd:r,env:n,stdio:["ignore","pipe","pipe"],timeout:15e3,maxBuffer:t})}function g(r){return f(r,["rev-parse","HEAD"]).toString("utf8").trim()}function R(r){return f(r,["symbolic-ref","--quiet","--short","HEAD"]).toString("utf8").trim()}function A(r,e,t){const c=v(r,{required:!0}).epics[e]?.branch_lease,i=c&&typeof c=="object"&&!Array.isArray(c)?c:void 0,s=i?.ownerStoryId===t?i.sessionId:void 0;if(typeof s!="string"||!/^setup-[a-f0-9]{64}$/.test(s)||s!==i?.idempotencyKey||typeof i?.expiresAt!="string"||!Number.isFinite(Date.parse(i.expiresAt))||Date.parse(i.expiresAt)<=Date.now())throw new Error("private-execution-clean-baseline-lease-invalid");return s}async function j(r,e,t,n){const c=await z(r),i=await W(c,"private-execution"),s=l=>b("sha256").update(l).digest("hex"),o=`${t}-${s(e)}.json`,a=`${t}-${s(`${e}\0${n}`)}.json`,h=x(i,a),u=x(i,o);if(m(h)){await w(h,i);const l=JSON.parse(d(h,"utf8"));if(!l||typeof l!="object"||Array.isArray(l)||l.storyId!==e||l.setupSessionId!==n)throw new Error("private-yolo-record-session-mismatch");return{parent:i,name:a,path:h}}if(!m(u))return{parent:i,name:o,path:u};await w(u,i);const p=JSON.parse(d(u,"utf8"));if(!p||typeof p!="object"||Array.isArray(p)||p.storyId!==e||typeof p.setupSessionId!="string"||!/^setup-[a-f0-9]{64}$/.test(p.setupSessionId))throw new Error("private-yolo-record-legacy-invalid");return p.setupSessionId===n?{parent:i,name:o,path:u}:{parent:i,name:a,path:h}}async function T(r,e){return j(r,e,"baseline",A(r,e.split(".")[0],e))}async function P(r,e,t,n){try{const{parent:c,path:i}=await j(r,e,"session",t.setupSessionId);if(!m(i))return!1;await w(i,c);const s=JSON.parse(d(i,"utf8"));if(!s||typeof s!="object"||Array.isArray(s))return!1;const o=s,a=o.workspace&&typeof o.workspace=="object"&&!Array.isArray(o.workspace)?o.workspace:void 0,h=Number(o.sequence),u=v(r,{required:!0}).stories[e],p=h===0&&o.lastPatchSha256===null&&o.snapshotSha===a?.baseSha&&Array.isArray(o.graphHistory)&&o.graphHistory.length===2&&$(u);return o.schemaVersion===1&&o.kind==="private-yolo-isolated-session"&&o.storyId===e&&o.initialGraphRevision===t.graphRevision&&o.graphRevision===n&&o.setupSessionId===t.setupSessionId&&Array.isArray(o.graphHistory)&&o.graphHistory.length>1&&o.graphHistory.length<=65&&o.graphHistory[0]===t.graphRevision&&o.graphHistory[o.graphHistory.length-1]===n&&new Set(o.graphHistory).size===o.graphHistory.length&&Number.isSafeInteger(o.sequence)&&(h>0||p)&&typeof o.snapshotSha=="string"&&/^[a-f0-9]{40,64}$/.test(o.snapshotSha)&&a?.sourceRoot===r&&a.baseSha===t.headSha&&a.executionBranch===t.executionBranch}catch{return!1}}function V(r){const e=y(r);try{const t=g(e);if(f(e,["status","--porcelain=v1","-z","--untracked-files=all"]).byteLength!==0)throw new Error("private-execution-checkout-dirty");if(g(e)!==t)throw new Error("private-execution-checkout-raced");return t}catch(t){throw t instanceof Error&&/^private-execution-[a-z-]+$/.test(t.message)?t:new Error("private-execution-checkout-unverified")}}async function K(r,e,t){const n=y(r),i=v(n,{required:!0}).epics[e.epicId],s=i?.branch_lease,o=s&&typeof s=="object"&&!Array.isArray(s)?s:void 0,a=i?.origin_binding,h=a&&typeof a=="object"&&!Array.isArray(a)?a:void 0;if(!/^[a-f0-9]{40,64}$/.test(t)||e.kind!=="direct-yolo-setup-receipt"||i?.execution_branch!==e.executionBranch||i?.origin_branch!==e.originBranch||o?.ownerStoryId!==e.storyId||o?.setupHeadSha!==t||o?.expiresAt!==e.leaseExpiresAt||h?.originBranch!==e.originBranch||h?.executionBranch!==e.executionBranch||h?.originHeadSha!==e.originHeadSha||h?.capturedFromCurrentCheckout!==!0||g(n)!==t||R(n)!==e.executionBranch||f(n,["status","--porcelain=v1","-z","--untracked-files=all"]).byteLength!==0)throw new Error("private-execution-clean-baseline-raced");try{f(n,["merge-base","--is-ancestor",e.originHeadSha,t])}catch{throw new Error("private-execution-clean-baseline-raced")}const u=A(n,e.epicId,e.storyId),p=O(n,e.storyId);if(p!==_(n,e.storyId)||g(n)!==t)throw new Error("private-execution-clean-baseline-raced");const l=i?.graph_revision;if(typeof l!="string"||!/^[a-f0-9]{64}$/.test(l))throw new Error("private-execution-clean-baseline-graph-invalid");const B=Object.freeze({schemaVersion:3,kind:"private-yolo-clean-baseline",storyId:e.storyId,epicId:e.epicId,executionBranch:e.executionBranch,headSha:t,setupSessionId:u,graphRevision:l,authorizedWriteSetSha256:p}),E=await T(n,e.storyId);await C(E.parent,E.name,`${JSON.stringify(B)}
|
|
2
|
+
`)}async function k(r,e,t,n,c){const i=y(r);try{const s=await T(i,e);await w(s.path,s.parent);const o=JSON.parse(d(s.path,"utf8"));if(!o||typeof o!="object"||Array.isArray(o))throw new Error("private-execution-clean-baseline-invalid");const a=o,h=v(i,{required:!0}).epics[a.epicId]?.graph_revision,u=h===a.graphRevision||c===a.graphRevision&&h===n||typeof h=="string"&&await P(i,e,a,h);if(Object.keys(a).sort().join(",")!==["schemaVersion","kind","storyId","epicId","executionBranch","headSha","setupSessionId","graphRevision","authorizedWriteSetSha256"].sort().join(",")||a.schemaVersion!==3||a.kind!=="private-yolo-clean-baseline"||a.storyId!==e||a.executionBranch!==t||a.epicId!==e.split(".")[0]||typeof a.headSha!="string"||!/^[a-f0-9]{40,64}$/.test(a.headSha)||typeof a.authorizedWriteSetSha256!="string"||!/^[a-f0-9]{64}$/.test(a.authorizedWriteSetSha256)||typeof a.graphRevision!="string"||!/^[a-f0-9]{64}$/.test(a.graphRevision)||n!==void 0&&h!==n||!u||a.authorizedWriteSetSha256!==O(i,e)||a.authorizedWriteSetSha256!==_(i,e)||a.setupSessionId!==A(i,a.epicId,e)||g(i)!==a.headSha||R(i)!==t)throw new Error("private-execution-clean-baseline-invalid")}catch{throw new Error("private-execution-clean-baseline-unverified")}}async function L(r,e,t,n){return k(r,e,t,n)}async function U(r,e,t,n){await L(r,e,t,n);try{const c=S(f(y(r),["show","HEAD:.neocortex/state.json"],16777216).toString("utf8"),e);if(c.length===0)throw new Error("write-set-empty");return Object.freeze([...c])}catch{throw new Error("private-execution-clean-baseline-unverified")}}async function X(r,e,t,n,c){await k(r,e,t,c,n);try{const i=S(f(y(r),["show","HEAD:.neocortex/state.json"],16777216).toString("utf8"),e);if(i.length===0)throw new Error("write-set-empty");return Object.freeze([...i])}catch{throw new Error("private-execution-clean-baseline-unverified")}}function Q(r,e,t){try{const n=S(r,e);if(n.length!==t.length||n.some((c,i)=>c!==t[i]))throw new Error("write-set-drift")}catch{throw new Error("private-execution-clean-baseline-write-set-unverified")}}export{V as capturePrivateYoloCleanHead,j as privateYoloRecordLocation,$ as privateYoloRootOnlySetupReady,U as readPrivateYoloFrozenWriteSet,X as readPrivateYoloFrozenWriteSetForTransition,K as recordPrivateYoloCleanBaseline,Q as verifyPrivateYoloCandidateWriteSet,L as verifyPrivateYoloCleanBaseline};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export interface
|
|
2
|
-
readonly schemaVersion:
|
|
1
|
+
export interface PrivateCodexPreflightV6 {
|
|
2
|
+
readonly schemaVersion: 6;
|
|
3
3
|
readonly hostKind: 'codex-cli';
|
|
4
4
|
readonly hostVersion: string;
|
|
5
5
|
readonly projectRoot: string;
|
|
@@ -11,6 +11,7 @@ export interface PrivateCodexPreflightV5 {
|
|
|
11
11
|
readonly mcpIsolation: 'passed';
|
|
12
12
|
readonly environmentIsolation: 'passed';
|
|
13
13
|
readonly networkDenied: 'passed';
|
|
14
|
+
readonly webSearchDisabled: 'passed';
|
|
14
15
|
readonly credentialKind: 'chatgpt-subscription';
|
|
15
16
|
}
|
|
16
17
|
export interface PrivateCodexExecutionReceiptV1 {
|
|
@@ -23,6 +24,37 @@ export interface PrivateCodexExecutionReceiptV1 {
|
|
|
23
24
|
readonly stderrBytes: number;
|
|
24
25
|
readonly publicSafe: true;
|
|
25
26
|
}
|
|
27
|
+
/** Host-only failure telemetry. No material, output text, path, ID or effect verdict. */
|
|
28
|
+
export type PrivateCodexWorkspaceEffectFailureV1 = Readonly<{
|
|
29
|
+
schemaVersion: 1;
|
|
30
|
+
kind: 'PrivateCodexWorkspaceEffectFailure/1';
|
|
31
|
+
phase: 'before-capture' | 'branch-before' | 'after-capture' | 'identity-after' | 'no-payload-change' | 'process-return';
|
|
32
|
+
agentReturnedSuccessfully: boolean;
|
|
33
|
+
processOutcome?: Readonly<{
|
|
34
|
+
exitCode: number | null;
|
|
35
|
+
timedOut: boolean;
|
|
36
|
+
outputExceeded: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
events?: PrivateCodexEventCounts;
|
|
39
|
+
stdoutSha256?: string;
|
|
40
|
+
stderrSha256?: string;
|
|
41
|
+
stdoutBytes?: number;
|
|
42
|
+
stderrBytes?: number;
|
|
43
|
+
publicSafe: true;
|
|
44
|
+
}>;
|
|
45
|
+
/** Fixed aggregate counters only: untrusted agent strings never cross this boundary. */
|
|
46
|
+
interface PrivateCodexEventCounts {
|
|
47
|
+
readonly agentMessages: number;
|
|
48
|
+
readonly commands: number;
|
|
49
|
+
readonly failedCommands: number;
|
|
50
|
+
readonly fileChanges: number;
|
|
51
|
+
readonly failedFileChanges: number;
|
|
52
|
+
readonly failedTurns: number;
|
|
53
|
+
readonly unavailableCommands: number;
|
|
54
|
+
readonly permissionDenials: number;
|
|
55
|
+
readonly missingInputs: number;
|
|
56
|
+
readonly thinClientReentries: number;
|
|
57
|
+
}
|
|
26
58
|
interface BoundedProcessResult {
|
|
27
59
|
readonly exitCode: number | null;
|
|
28
60
|
readonly stdout: Buffer;
|
|
@@ -35,6 +67,7 @@ export type PrivateCodexRunner = (args: readonly string[], options: {
|
|
|
35
67
|
readonly stdin?: string;
|
|
36
68
|
readonly timeoutMs: number;
|
|
37
69
|
readonly maxOutputBytes: number;
|
|
70
|
+
readonly configReadProbe?: true;
|
|
38
71
|
}) => Promise<BoundedProcessResult>;
|
|
39
72
|
/** The CLI needs its login location and executable path, not host secrets. */
|
|
40
73
|
export declare function privateCodexEnvironment(source: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
@@ -43,6 +76,8 @@ export declare function runBoundedCodexProcess(args: readonly string[], options:
|
|
|
43
76
|
readonly stdin?: string;
|
|
44
77
|
readonly timeoutMs: number;
|
|
45
78
|
readonly maxOutputBytes: number;
|
|
79
|
+
readonly codexHome?: string;
|
|
80
|
+
readonly configReadProbe?: true;
|
|
46
81
|
}): Promise<BoundedProcessResult>;
|
|
47
82
|
/**
|
|
48
83
|
* Probe the exact default sandbox configuration used by `codex exec`. This
|
|
@@ -55,11 +90,20 @@ export declare function preflightPrivateCodexExecutor(projectRoot: string, optio
|
|
|
55
90
|
readonly userHome?: string;
|
|
56
91
|
readonly now?: () => number;
|
|
57
92
|
readonly networkProbe?: (root: string, runner: PrivateCodexRunner) => Promise<boolean>;
|
|
58
|
-
}): Promise<
|
|
59
|
-
export declare function runPrivateCodexStep(material: string, preflight:
|
|
93
|
+
}): Promise<PrivateCodexPreflightV6>;
|
|
94
|
+
export declare function runPrivateCodexStep(material: string, preflight: PrivateCodexPreflightV6, options?: {
|
|
60
95
|
readonly runner?: PrivateCodexRunner;
|
|
61
96
|
readonly now?: () => number;
|
|
62
97
|
readonly requireWorkspaceEffect?: boolean;
|
|
63
98
|
readonly expectedExecutionBranch?: string;
|
|
99
|
+
/** Root observer only; its return value never authorizes an effect. */
|
|
100
|
+
readonly onWorkspaceEffectFailure?: (observation: PrivateCodexWorkspaceEffectFailureV1) => void;
|
|
101
|
+
/** Trusted in-memory root observation only; copied bytes cannot alter the receipt or runner. */
|
|
102
|
+
readonly onExecutionOutput?: (output: Readonly<{
|
|
103
|
+
stdout: Buffer;
|
|
104
|
+
stderr: Buffer;
|
|
105
|
+
}>) => void | Promise<void>;
|
|
106
|
+
/** Operator-selected subscription model; no global configuration mutation. */
|
|
107
|
+
readonly model?: string;
|
|
64
108
|
}): Promise<PrivateCodexExecutionReceiptV1>;
|
|
65
109
|
export {};
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
import{execFileSync as
|
|
2
|
-
|
|
1
|
+
import{codexLifecycleGuardPath as J}from"./codex-lifecycle-guard.js";import{execFileSync as q,spawn as U}from"node:child_process";import{createHash as T,randomBytes as Y}from"node:crypto";import{connect as Q,createServer as Z}from"node:net";import{accessSync as D,lstatSync as R,mkdtempSync as ee,readFileSync as te,realpathSync as re,rmdirSync as k,unlinkSync as A,constants as M}from"node:fs";import{homedir as oe}from"node:os";import{join as g,resolve as L}from"node:path";import{gitLifecycleRuntimeDirectory as ne}from"../git/git-lifecycle-store.js";import{captureDirectYoloCheckoutEvidence as N}from"../git/direct-yolo-checkpoint.js";import{createPrivateCodexScopedRunner as ie}from"./codex-scoped-permissions.js";import{createPrivateCodexHostRuntime as se}from"./codex-host-runtime.js";const j=3e4,m=16*1024,ae=1024*1024,ce=256*1024,H=`
|
|
2
|
+
|
|
3
|
+
Private executor boundary (client owned):
|
|
4
|
+
Execute only the supplied private step. This process is an isolated executor, not a root Neocortex invocation or native task delegation. Root-only platform dispatch wrappers describe the parent. Do not re-enter Neocortex orchestration, invoke neocortex-client or neocortex to restart a workflow, delegate another agent, manage Git controls, approve QA or change lifecycle/billing state. Preserve applicable project coding rules and the step-specific artifact/write-set contract. Missing prerequisites leave this candidate incomplete; report gaps only in an authorized artifact.
|
|
5
|
+
`,G=/^codex-cli\s+(\d+\.\d+\.\d+)\s*$/,y="p222-isolated",de=["PATH","HOME","LANG","LC_ALL","TERM","CODEX_HOME"],$=["-c",'web_search="disabled"',"-c","features.hooks=false","-c","analytics.enabled=false","-c",'history.persistence="none"',"-c",'otel.exporter="none"',"-c",'otel.metrics_exporter="none"',"-c",'otel.trace_exporter="none"',"-c","otel.log_user_prompt=false","-c","notify=[]"];function ue(i){const e={agentMessages:0,commands:0,failedCommands:0,fileChanges:0,failedFileChanges:0,failedTurns:0,unavailableCommands:0,permissionDenials:0,missingInputs:0,thinClientReentries:0},t=o=>{e[o]=Math.min(1e3,e[o]+1)};for(const o of i.toString("utf8").split(`
|
|
6
|
+
`))if(!(o.length>128*1024))try{const n=JSON.parse(o);if(!n||typeof n!="object"||Array.isArray(n)||(n.type==="turn.failed"&&t("failedTurns"),n.type!=="item.completed"||!n.item||typeof n.item!="object"||Array.isArray(n.item)))continue;const r=n.item;if(r.type==="agent_message"&&t("agentMessages"),r.type==="command_execution"){if(t("commands"),r.status==="failed"||Number.isSafeInteger(r.exit_code)&&r.exit_code!==0){t("failedCommands"),(r.exit_code===126||r.exit_code===127)&&t("unavailableCommands");const d=typeof r.aggregated_output=="string"?r.aggregated_output:"";/permission denied|operation not permitted|sandbox.*denied/i.test(d)&&t("permissionDenials"),/no such file or directory|cannot find module/i.test(d)&&t("missingInputs")}typeof r.command=="string"&&/\bneocortex(?:-client)?\s+invoke\b/.test(r.command)&&t("thinClientReentries")}r.type==="file_change"&&(t("fileChanges"),r.status==="failed"&&t("failedFileChanges"))}catch{}return Object.freeze(e)}const I=new WeakMap,B=new WeakMap;function le(i){const e={};for(const t of de)typeof i[t]=="string"&&(e[t]=i[t]);return e}async function z(i,e){if(e.configReadProbe&&(e.stdin!==void 0||i.at(-1)!=="app-server"))throw new Error("private-codex-web-search-isolation-unproven");return new Promise((t,o)=>{const n=le(process.env);e.codexHome!==void 0&&(n.CODEX_HOME=e.codexHome);const r=process.platform==="linux",s=U(r?process.execPath:e.codexHome===void 0?"codex":"/bin/sh",r?[J,"process"]:e.codexHome===void 0?[...i]:["-c",'umask 077; exec codex "$@"',"neocortex-private-codex",...i],{cwd:e.cwd,stdio:r?["pipe","pipe","pipe","ipc"]:["pipe","pipe","pipe"],env:n,detached:r}),d=()=>{if(process.platform==="linux"&&s.pid!==void 0)try{process.kill(-s.pid,"SIGKILL")}catch(p){if(p.code!=="ESRCH")throw p}else s.kill("SIGKILL")},a=[],l=[];let h=0,f=0,c=!1,u=!1,x="",E=!1;const b=p=>s.stdin.write(`${JSON.stringify(p)}
|
|
7
|
+
`),O=setTimeout(()=>{c=!0,d()},e.timeoutMs);s.stdout.on("data",p=>{if(h+=p.byteLength,h+f>e.maxOutputBytes)u=!0,d();else if(a.push(p),e.configReadProbe){x+=p.toString("utf8");let v;for(;(v=x.indexOf(`
|
|
8
|
+
`))>=0;){const P=x.slice(0,v);x=x.slice(v+1);try{const C=JSON.parse(P);C.id===1&&C.result&&!E?(E=!0,b({method:"initialized",params:{}}),b({id:2,method:"config/read",params:{includeLayers:!1,cwd:e.cwd}})):C.id===2&&s.stdin.end()}catch{}}}}),s.stderr.on("data",p=>{f+=p.byteLength,h+f>e.maxOutputBytes?(u=!0,d()):l.push(p)}),s.on("error",p=>{clearTimeout(O),o(p)}),s.on("close",p=>{clearTimeout(O),t({exitCode:p,stdout:Buffer.concat(a),stderr:Buffer.concat(l),timedOut:c,outputExceeded:u})}),s.stdin.on("error",()=>{}),r&&s.send({kind:"private-codex-launch",args:[...i],codexHome:e.codexHome},p=>{p&&(clearTimeout(O),d(),o(new Error("private-codex-process-guard-unavailable")))}),e.configReadProbe?b({id:1,method:"initialize",params:{clientInfo:{name:"p222-isolation-probe",version:"1"},capabilities:{}}}):s.stdin.end(e.stdin)})}function w(i){return i.exitCode===0&&!i.timedOut&&!i.outputExceeded}async function F(i,e){const t=await e(["-c","features.plugins=false","plugin","list","--json"],{cwd:i,timeoutMs:1e4,maxOutputBytes:m}),o=await e(["mcp","list","--json"],{cwd:i,timeoutMs:1e4,maxOutputBytes:m});if(!w(t)||!w(o))return null;try{const n=JSON.parse(t.stdout.toString("utf8")),r=JSON.parse(o.stdout.toString("utf8"));if(!!!(n&&typeof n=="object"&&!Array.isArray(n)&&Array.isArray(n.installed)&&n.installed.length===0)||!Array.isArray(r)||r.length>64)return null;const d=r.map(c=>{if(!c||typeof c!="object"||Array.isArray(c))throw new Error("invalid catalog");const u=c;if(typeof u.name!="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(u.name)||typeof u.enabled!="boolean")throw new Error("invalid catalog");return u.name});if(new Set(d).size!==d.length)return null;if(d.length===0)return[];const a=[...d].sort().flatMap(c=>["-c",`mcp_servers.${c}.enabled=false`]),l=await e([...a,"mcp","list","--json"],{cwd:i,timeoutMs:1e4,maxOutputBytes:m});if(!w(l))return null;const h=JSON.parse(l.stdout.toString("utf8"));if(!Array.isArray(h)||h.length!==d.length)return null;const f=new Set;for(const c of h){if(!c||typeof c!="object"||Array.isArray(c)||typeof c.name!="string"||!d.includes(c.name)||c.enabled!==!1||f.has(c.name))return null;f.add(c.name)}return Object.freeze(a)}catch{return null}}async function W(i,e){const t=await e(["-c","features.hooks=false","features","list"],{cwd:i,timeoutMs:1e4,maxOutputBytes:m});if(!w(t))return!1;const o=t.stdout.toString("utf8").split(/\r?\n/).filter(n=>/^hooks\s+\S+\s+(?:true|false)\s*$/.test(n));return o.length===1&&/^hooks\s+\S+\s+false\s*$/.test(o[0])}async function V(i,e,t){const o=await e(["-c","features.plugins=false",...t,...$,"--strict-config","app-server"],{cwd:i,configReadProbe:!0,timeoutMs:1e4,maxOutputBytes:262144});try{if(!w(o))return!1;const r=o.stdout.toString("utf8").split(/\r?\n/).filter(Boolean).map(s=>JSON.parse(s)).filter(s=>s&&s.id===2);return r.length===1&&!r[0].error&&r[0].result?.config?.web_search==="disabled"}catch{return!1}finally{o.stdout.fill(0),o.stderr.fill(0)}}function fe(i){const e=R(i);if(!e.isFile()||e.isSymbolicLink())throw new Error("private-codex-auth-unavailable");D(i,M.R_OK)}function K(i){const e={...process.env};for(const t of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete e[t];try{const t=n=>q("git",[...n],{cwd:i,env:e,encoding:"utf8",timeout:5e3,maxBuffer:m,stdio:["ignore","pipe","ignore"]}).trim(),o=[t(["rev-parse","--git-dir"]),t(["rev-parse","--git-common-dir"])].map(n=>re(L(i,n)));if(o.some(n=>!R(n).isDirectory()))throw new Error("git-control-invalid");return[...new Set(o)]}catch{throw new Error("private-codex-git-control-unavailable")}}async function pe(i,e){const t=await e(["sandbox","-P",y,"--","git","rev-parse","--git-dir"],{cwd:i,timeoutMs:1e4,maxOutputBytes:m});if(!w(t))return!1;for(const o of K(i)){const n=g(o,`.neocortex-git-probe-${Y(16).toString("hex")}`),r=await e(["sandbox","-P",y,"--","sh","-c",'mkdir "$1"',"sh",n],{cwd:i,timeoutMs:1e4,maxOutputBytes:m});let s=!1,d=!1;try{const a=R(n);s=!0,d=a.isDirectory()}catch(a){if(a.code!=="ENOENT")return!1}if(s&&(d?k(n):A(n)),r.exitCode!==1||r.timedOut||r.outputExceeded||s)return!1}return!0}async function me(i,e,t){if(!R(e).isDirectory())return!1;D(e,M.R_OK);const o=await t(["sandbox","-P",y,"--","sh","-c",'if test -r "$1"; then exit 42; else exit 43; fi',"sh",e],{cwd:i,timeoutMs:1e4,maxOutputBytes:m});return o.exitCode===43&&!o.timedOut&&!o.outputExceeded}async function he(i,e){const t=Z(o=>o.end());await new Promise((o,n)=>{t.once("error",n),t.listen(0,"127.0.0.1",()=>o())});try{const o=t.address();if(!o||typeof o=="string")return!1;const n='const s=require("node:net").connect(Number(process.argv[1]),"127.0.0.1");s.setTimeout(1500);s.on("connect",()=>{s.end();process.exit(0)});s.on("error",()=>process.exit(1));s.on("timeout",()=>process.exit(1))';if(!await new Promise(a=>{const l=Q(o.port,"127.0.0.1");l.setTimeout(1500),l.once("connect",()=>{l.end(),a(!0)}),l.once("error",()=>a(!1)),l.once("timeout",()=>{l.destroy(),a(!1)})}))return!1;const s=await e(["sandbox","-P",y,"--","node","--version"],{cwd:i,timeoutMs:5e3,maxOutputBytes:m});if(!w(s))return!1;const d=await e(["sandbox","-P",y,"--","node","-e",n,String(o.port)],{cwd:i,timeoutMs:5e3,maxOutputBytes:m});return d.exitCode===1&&!d.timedOut&&!d.outputExceeded}finally{t.close()}}async function Re(i,e={}){if((e.platform??process.platform)!=="linux")throw new Error("private-codex-platform-unsupported");const t=L(i),o=e.userHome??oe(),n=e.codexHome??process.env.CODEX_HOME??g(o,".codex"),r=e.runner?void 0:se(t,n);try{const s=r?async(_,X)=>(r.verify(),z(_,{...X,codexHome:r.home})):z,d=r?.home??n,a=e.runner??await ie(t,s,{...e,codexHome:d,credentialSourceHome:r?.sourceHome??n,gitControlDirectories:K(t)}),l=g(d,"auth.json");try{fe(l)}catch{throw new Error("private-codex-auth-unavailable")}const h=await a(["--version"],{cwd:t,timeoutMs:5e3,maxOutputBytes:m}),f=w(h)?G.exec(h.stdout.toString("utf8").trim()):null;if(!f)throw new Error("private-codex-version-unavailable");const c=await a(["login","status"],{cwd:t,timeoutMs:5e3,maxOutputBytes:m});if(!w(c)||!/Logged in using ChatGPT/i.test(Buffer.concat([c.stdout,c.stderr]).toString("utf8")))throw new Error("private-codex-subscription-required");const u=await F(t,a).catch(()=>null);if(u===null)throw new Error("private-codex-mcp-isolation-unproven");if(!await W(t,a).catch(()=>!1))throw new Error("private-codex-hook-isolation-unproven");if(!await V(t,a,u).catch(()=>!1))throw new Error("private-codex-web-search-isolation-unproven");const E=await ne(t).catch(()=>{throw new Error("private-codex-git-lifecycle-read-isolation-unproven")}),b=g(o,".ssh"),O=await a(["sandbox","-P",y,"--","sh","-c",...r?['test ! -r "$1" && test ! -r "$2" && test ! -r "$3"',"sh",l,b,g(n,"auth.json")]:['test ! -r "$1" && test ! -r "$2"',"sh",l,b]],{cwd:t,timeoutMs:1e4,maxOutputBytes:m});if(!w(O))throw new Error("private-codex-auth-isolation-unproven");const p=ee(g(t,".private-codex-probe-")),v=g(p,"receipt");try{const _=await a(["sandbox","-P",y,"--","sh","-c",'printf "P222_PROBE\\n" > "$1"',"sh",v],{cwd:t,timeoutMs:1e4,maxOutputBytes:m});if(!w(_)||te(v,"utf8")!==`P222_PROBE
|
|
9
|
+
`)throw new Error("private-codex-workspace-write-unproven")}catch{throw new Error("private-codex-workspace-write-unproven")}finally{try{A(v)}catch{}k(p)}if(!await pe(t,a).catch(()=>!1))throw new Error("private-codex-git-control-isolation-unproven");if(!await me(t,E,a).catch(()=>!1))throw new Error("private-codex-git-lifecycle-read-isolation-unproven");if(!await(e.networkProbe??he)(t,a))throw new Error("private-codex-network-isolation-unproven");const S=Object.freeze({schemaVersion:6,hostKind:"codex-cli",hostVersion:f[1],projectRoot:t,observedAtMs:(e.now??Date.now)(),authIsolation:"passed",workspaceWrite:"passed",gitControlWriteDenied:"passed",gitLifecycleReadDenied:"passed",mcpIsolation:"passed",environmentIsolation:"passed",networkDenied:"passed",webSearchDisabled:"passed",credentialKind:"chatgpt-subscription"});if(I.set(S,a),r){const _=setTimeout(()=>{B.delete(S),I.delete(S);try{r.close()}catch{}},j);_.unref(),B.set(S,{runtime:r,timer:_})}return S}catch(s){throw r?.close(),s}}async function Ie(i,e,t={}){const o=B.get(e);o&&(clearTimeout(o.timer),B.delete(e));try{const n=(t.now??Date.now)();if(t.model!==void 0&&!/^gpt-[a-z0-9][a-z0-9.-]{0,63}$/.test(t.model))throw new Error("private-codex-model-invalid");if(e.schemaVersion!==6||e.hostKind!=="codex-cli"||e.authIsolation!=="passed"||e.workspaceWrite!=="passed"||e.gitControlWriteDenied!=="passed"||e.gitLifecycleReadDenied!=="passed"||e.mcpIsolation!=="passed"||e.environmentIsolation!=="passed"||e.webSearchDisabled!=="passed"||e.networkDenied!=="passed"||e.credentialKind!=="chatgpt-subscription"||n<e.observedAtMs||n-e.observedAtMs>j||typeof i!="string"||Buffer.byteLength(i,"utf8")<1||Buffer.byteLength(i,"utf8")+Buffer.byteLength(H,"utf8")>ce)throw new Error("private-codex-preflight-stale");const r=I.get(e);if(r&&t.runner&&t.runner!==r)throw new Error("private-codex-runner-binding-mismatch");if(t.onExecutionOutput!==void 0&&typeof t.onExecutionOutput!="function")throw new Error("private-codex-output-observation-failed");const s=r??t.runner;if(!s)throw new Error("private-codex-preflight-stale");const d=await s(["--version"],{cwd:e.projectRoot,timeoutMs:5e3,maxOutputBytes:m});if(!w(d)||G.exec(d.stdout.toString("utf8").trim())?.[1]!==e.hostVersion)throw new Error("private-codex-version-drift");const a=(c,u,x="private-codex-workspace-effect-unverified")=>{const E=Object.freeze({schemaVersion:1,kind:"PrivateCodexWorkspaceEffectFailure/1",phase:c,agentReturnedSuccessfully:u!==void 0&&w(u),...u===void 0?{}:{...c!=="process-return"?{}:{processOutcome:Object.freeze({exitCode:Number.isInteger(u.exitCode)&&u.exitCode>=0&&u.exitCode<=255?u.exitCode:null,timedOut:u.timedOut===!0,outputExceeded:u.outputExceeded===!0})},events:ue(u.stdout),stdoutSha256:T("sha256").update(u.stdout).digest("hex"),stderrSha256:T("sha256").update(u.stderr).digest("hex"),stdoutBytes:u.stdout.length,stderrBytes:u.stderr.length},publicSafe:!0});try{Promise.resolve(t.onWorkspaceEffectFailure?.(E)).catch(()=>{})}catch{}return new Error(x)},l=t.requireWorkspaceEffect?await N(e.projectRoot).catch(()=>{throw a("before-capture")}):void 0;if(l&&t.expectedExecutionBranch!==void 0&&l.branch!==t.expectedExecutionBranch)throw a("branch-before");if(!await W(e.projectRoot,s).catch(()=>!1))throw new Error("private-codex-hook-isolation-unproven");const h=await F(e.projectRoot,s).catch(()=>null);if(h===null)throw new Error("private-codex-mcp-isolation-unproven");if(!await V(e.projectRoot,s,h).catch(()=>!1))throw new Error("private-codex-web-search-isolation-unproven");const f=await s(["exec","--ephemeral","--json","--strict-config","-c","features.plugins=false",...t.model===void 0?[]:["--model",t.model],...h,...$,"-c","shell_environment_policy.ignore_default_excludes=false","-c",'shell_environment_policy.include_only=["PATH","HOME","LANG","LC_ALL","TERM"]',"-c",`default_permissions="${y}"`,"-C",e.projectRoot,"-"],{cwd:e.projectRoot,stdin:i+H,timeoutMs:10*6e4,maxOutputBytes:ae});if(!w(f))throw a("process-return",f,"private-codex-execution-unverified");if(t.onExecutionOutput)try{await t.onExecutionOutput(Object.freeze({stdout:Buffer.from(f.stdout),stderr:Buffer.from(f.stderr)}))}catch{throw new Error("private-codex-output-observation-failed")}if(o?.runtime.verify(),l){const c=await N(e.projectRoot).catch(()=>{throw a("after-capture",f)});if(c.headSha!==l.headSha||c.branch!==l.branch)throw a("identity-after",f);if(c.payloadDigest===l.payloadDigest)throw a("no-payload-change",f)}return Object.freeze({schemaVersion:1,outcome:"executor-returned-unverified",exitCode:0,stdoutSha256:T("sha256").update(f.stdout).digest("hex"),stderrSha256:T("sha256").update(f.stderr).digest("hex"),stdoutBytes:f.stdout.byteLength,stderrBytes:f.stderr.byteLength,publicSafe:!0})}finally{o&&(I.delete(e),o.runtime.close())}}export{Re as preflightPrivateCodexExecutor,le as privateCodexEnvironment,z as runBoundedCodexProcess,Ie as runPrivateCodexStep};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface PrivateCodexHostRuntime {
|
|
2
|
+
readonly home: string;
|
|
3
|
+
readonly sourceHome: string;
|
|
4
|
+
verify(): void;
|
|
5
|
+
close(): void;
|
|
6
|
+
}
|
|
7
|
+
/** The CLI may record project trust in its own configuration. Keep that write in
|
|
8
|
+
* short-lived, owner-private host control storage using the existing account.
|
|
9
|
+
* No credential is placed in, mounted into or passed to the model checkout. */
|
|
10
|
+
export declare function createPrivateCodexHostRuntime(projectRoot: string, sourceHome: string): PrivateCodexHostRuntime;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{startPrivateCodexHomeGuard as L}from"./codex-lifecycle-guard.js";import{createHash as k}from"node:crypto";import{closeSync as H,constants as O,fstatSync as z,lstatSync as g,mkdtempSync as M,openSync as R,readFileSync as T,realpathSync as S,rmSync as _,writeFileSync as C}from"node:fs";import{isAbsolute as P,join as c,relative as W}from"node:path";const p=d=>k("sha256").update(d).digest("hex"),w=new Set;let b=!1;function r(){throw new Error("private-codex-host-runtime-unverified")}function a(d,v){const f=R(d,O.O_RDONLY|O.O_NOFOLLOW|O.O_NONBLOCK);try{const e=z(f);(!e.isFile()||e.uid!==process.getuid?.()||e.nlink!==1||e.mode&18||v&&(e.mode&511)!==384||e.size<1||e.size>1048576)&&r();const l=T(f),s=z(f),m=g(d);return(l.length!==e.size||[s,m].some(t=>t.dev!==e.dev||t.ino!==e.ino||t.size!==e.size||t.mtimeMs!==e.mtimeMs||t.ctimeMs!==e.ctimeMs||t.mode!==e.mode||t.nlink!==1))&&r(),l}finally{H(f)}}function K(d,v){try{const f=S(d),e=S(v),l=W(f,e),s=g(e);(!l||!l.startsWith("..")&&!P(l)||!s.isDirectory()||s.uid!==process.getuid?.()||s.mode&18)&&r();const m=a(c(e,"auth.json"),!0);let t;try{t=a(c(e,"config.toml"),!1)}catch(o){if(o.code!=="ENOENT")throw o}const D=p(m),F=t?p(t):void 0,n=M(c(e,".neocortex-executor-")),N=g(n),u=process.platform==="linux"?L(n):void 0;let x=!1;const E=()=>{const o=g(n),i=g(e);(S(e)!==e||i.dev!==s.dev||i.ino!==s.ino||i.uid!==s.uid||i.mode&18||o.dev!==N.dev||o.ino!==N.ino||o.uid!==process.getuid?.()||(o.mode&511)!==448||!o.isDirectory()||o.isSymbolicLink())&&r()};let y;const j=()=>{if(!x)try{E(),_(n,{recursive:!0}),x=!0,y&&w.delete(y),u?.connected&&u.disconnect()}catch{r()}};try{C(c(n,"auth.json"),m,{mode:384,flag:"wx"}),t&&C(c(n,"config.toml"),t,{mode:384,flag:"wx"}),m.fill(0),t?.fill(0);const o=()=>{try{(x||u&&(!u.connected||u.exitCode!==null||u.signalCode!==null))&&r(),E(),p(a(c(e,"auth.json"),!0))!==D&&r();let i;try{i=a(c(e,"config.toml"),!1)}catch(h){if(h.code!=="ENOENT")throw h}(i?p(i):void 0)!==F&&r(),a(c(n,"auth.json"),!0);try{a(c(n,"config.toml"),!0)}catch(h){if(h.code!=="ENOENT")throw h}}catch{r()}};return o(),y=Object.freeze({home:n,sourceHome:e,verify:o,close:j}),w.add(y),b||(b=!0,process.once("exit",()=>{for(const i of w)try{i.close()}catch{}})),y}catch(o){throw j(),o}}catch{r()}}export{K as createPrivateCodexHostRuntime};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Mechanical Linux process/custody lifetime; no workflow material or authority. */
|
|
2
|
+
import { type ChildProcess } from 'node:child_process';
|
|
3
|
+
export declare const codexLifecycleGuardPath: string;
|
|
4
|
+
export declare function startPrivateCodexHomeGuard(home: string): ChildProcess;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{spawn as i}from"node:child_process";import{lstatSync as d,realpathSync as a,rmSync as u}from"node:fs";import{basename as f}from"node:path";import{fileURLToPath as m}from"node:url";const p=m(new URL(import.meta.url.endsWith(".ts")?"../../dist/private-execution/codex-lifecycle-guard.js":"./codex-lifecycle-guard.js",import.meta.url));function L(r){const e=d(r),c=i(process.execPath,[p,"home",r,String(e.dev),String(e.ino)],{detached:!0,env:{},stdio:["ignore","ignore","ignore","ipc"]});return c.on("error",()=>{}),c.unref(),c.channel?.unref(),c}function n(){process.kill(-process.pid,"SIGKILL"),process.exit(1)}function l(){const[r,e,c]=process.argv.slice(3);let s=!1;const o=()=>{if(!s){s=!0;try{if(!r||!f(r).startsWith(".neocortex-executor-"))throw new Error;const t=d(r);if(a(r)!==r||!t.isDirectory()||t.isSymbolicLink()||t.uid!==process.getuid?.()||(t.mode&511)!==448||String(t.dev)!==e||String(t.ino)!==c)throw new Error;u(r,{recursive:!0}),process.exit(0)}catch(t){process.exit(t.code==="ENOENT"?0:1)}}};process.on("disconnect",o),process.connected||o()}function x(){process.on("disconnect",n),process.on("SIGTERM",n),process.on("SIGINT",n),process.stdout.on("error",n),process.stderr.on("error",n),process.connected||n(),process.once("message",r=>{const e=r;(!e||e.kind!=="private-codex-launch"||!Array.isArray(e.args)||e.args.some(o=>typeof o!="string")||e.codexHome!==void 0&&typeof e.codexHome!="string")&&n();const c=e.args,s=i(e.codexHome===void 0?"codex":"/bin/sh",e.codexHome===void 0?c:["-c",'umask 077; exec codex "$@"',"neocortex-private-codex",...c],{cwd:process.cwd(),env:Object.fromEntries(["PATH","HOME","LANG","LC_ALL","TERM","CODEX_HOME"].filter(o=>process.env[o]!==void 0).map(o=>[o,process.env[o]])),detached:!1,stdio:["pipe","pipe","pipe"]});process.stdin.pipe(s.stdin),s.stdin.on("error",()=>{}),s.stdout.pipe(process.stdout),s.stderr.pipe(process.stderr),s.on("error",n),s.on("close",o=>{process.stdin.unpipe(s.stdin),process.stdin.pause(),process.removeListener("disconnect",n),process.connected&&process.disconnect?.(),process.exitCode=typeof o=="number"?o:1})})}process.argv[1]===p&&process.platform==="linux"&&(process.argv[2]==="home"?l():process.argv[2]==="process"?x():process.exit(1));export{p as codexLifecycleGuardPath,L as startPrivateCodexHomeGuard};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PrivateCodexRunner } from './codex-executor.js';
|
|
2
|
+
/** Per-invocation permissions; never modifies the operator's configuration. */
|
|
3
|
+
export declare function createPrivateCodexScopedRunner(projectRoot: string, base: PrivateCodexRunner, options: {
|
|
4
|
+
readonly userHome?: string;
|
|
5
|
+
readonly codexHome?: string;
|
|
6
|
+
readonly credentialSourceHome?: string;
|
|
7
|
+
readonly gitControlDirectories: readonly string[];
|
|
8
|
+
}): Promise<PrivateCodexRunner>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomBytes as g}from"node:crypto";import{accessSync as D,constants as J,lstatSync as S,readdirSync as N,realpathSync as u}from"node:fs";import{homedir as R}from"node:os";import{createRequire as k}from"node:module";import{basename as $,delimiter as P,dirname as x,join as a,resolve as l,sep as b}from"node:path";import{gitLifecycleRuntimeDirectory as _}from"../git/git-lifecycle-store.js";function E(p){const o=new Set;for(const t of p){const r=S(t);if(!r.isDirectory()||r.isSymbolicLink()||u(t)!==t)throw new Error("private-codex-root-state-isolation-unproven");for(const s of N(t)){if(!s.startsWith("neocortex-"))continue;const d=a(t,s),c=S(d);if(!/^[A-Za-z0-9._-]{1,128}$/.test(s)||c.isSymbolicLink()||!c.isDirectory()&&!c.isFile())throw new Error("private-codex-root-state-isolation-unproven");if(o.add(d),o.size>64)throw new Error("private-codex-root-state-isolation-unproven")}}return[...o].sort()}function C(){for(const p of(process.env.PATH??"").split(P).filter(Boolean))try{const o=u(a(p,"codex"));if(D(o,J.X_OK),!S(o).isFile())continue;if($(o)!=="codex.js"||$(x(o))!=="bin")return[x(o)];const t=[x(x(o))],r=process.arch==="x64"?"@openai/codex-linux-x64":process.arch==="arm64"?"@openai/codex-linux-arm64":void 0;if(r)try{t.push(u(x(k(o).resolve(`${r}/package.json`))))}catch{}return[...new Set(t)]}catch{}throw new Error("private-codex-version-unavailable")}async function M(p,o,t){const r=u(l(p)),s=Object.freeze([...t.gitControlDirectories]),d=t.userHome??R(),c=t.codexHome??process.env.CODEX_HOME??a(d,".codex"),O=C();if(O.some(e=>[b,l(d),l(c),r].includes(e)||e.startsWith(r+b)))throw new Error("private-codex-executable-scope-unsafe");const j=await _(r),y=E(s),i={":root":"deny",":minimal":"read",[r]:"write",[a(d,".ssh")]:"deny",[a(c,"auth.json")]:"deny"};if(t.credentialSourceHome){const e=l(t.credentialSourceHome),n=l(c);i[e]="deny",n!==e&&!n.startsWith(e+b)&&(i[n]="deny"),delete i[a(c,"auth.json")]}for(const e of O)i[e]="read";for(const e of s)i[e]="read";i[a(r,".git")]="read",i[j]="deny";for(const e of y)i[e]="deny";const h=`p222-isolated-${g(16).toString("hex")}`,w=`permissions.${h}={filesystem={${Object.entries(i).map(([e,n])=>`${JSON.stringify(e)}=${JSON.stringify(n)}`).join(",")}},network={enabled=false}}`;return async(e,n)=>{if(u(l(n.cwd))!==r)throw new Error("private-codex-execution-root-drift");if(JSON.stringify(E(s))!==JSON.stringify(y))throw new Error("private-codex-root-state-isolation-unproven");if(e[0]!=="sandbox"&&e[0]!=="exec")return o(e,n);const f=[...e];if(e[0]==="sandbox"){if(e[1]!=="-P"||e[2]!=="p222-isolated")throw new Error("private-codex-permission-profile-invalid");f[2]=h}else{const H=f.findIndex((v,m)=>v==='default_permissions="p222-isolated"'&&f[m-1]==="-c");if(H<0)throw new Error("private-codex-permission-profile-invalid");f[H]=`default_permissions="${h}"`;for(const v of y){const m=await o(["-c",w,"sandbox","-P",h,"--","sh","-c",'test ! -r "$1"',"sh",v],{cwd:r,timeoutMs:1e4,maxOutputBytes:16384});if(m.exitCode!==0||m.timedOut||m.outputExceeded||JSON.stringify(E(s))!==JSON.stringify(y))throw new Error("private-codex-root-state-isolation-unproven")}}return o(e[0]==="exec"?["exec","-c",w,...f.slice(1)]:["-c",w,...f],n)}}export{M as createPrivateCodexScopedRunner};
|