@ornexus/neocortex 4.59.1 → 4.59.3

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.
@@ -6,6 +6,8 @@
6
6
  */
7
7
  import { type ContinuitySqliteAdapter, type ContinuitySqliteAdapterLoadResult } from '../continuity/sqlite-store.js';
8
8
  import { type RunnerSchedulerCommandOptions } from './scheduler.js';
9
+ export { RUNNER_BINARY_REASON_CODES, checkRunnerBinaryTrust, runnerTrustRelativePath } from './binary.js';
10
+ export type { RunnerBinaryTrustResult } from './binary.js';
9
11
  export declare const RUNNER_REASON_CODES: Readonly<{
10
12
  readonly OK: "continuity-ok";
11
13
  readonly LEASE_CONFLICT: "lease-conflict";
@@ -95,16 +97,6 @@ export interface RunnerDoctorSummary {
95
97
  readonly reasonCodes: readonly RunnerReasonCode[];
96
98
  readonly publicSafe: true;
97
99
  }
98
- export interface RunnerBinaryTrustResult {
99
- readonly trusted: boolean;
100
- readonly reasonCode?: typeof RUNNER_REASON_CODES.RUNNER_BINARY_UNTRUSTED;
101
- readonly packageName?: string;
102
- readonly packageVersion?: string;
103
- readonly packageRoot?: string;
104
- readonly executablePath?: string;
105
- readonly expectedRelativePath?: string;
106
- readonly publicSafe: true;
107
- }
108
100
  interface RunnerDirective extends Record<string, unknown> {
109
101
  readonly kind: string;
110
102
  readonly commandClass?: string;
@@ -113,9 +105,6 @@ interface RunnerDirective extends Record<string, unknown> {
113
105
  export declare function defaultRunnerServerInvoker(input: RunnerServerInvokeInput): Promise<RunnerServerInvokeResult>;
114
106
  export declare function runRunnerTick(options?: RunnerTickOptions): Promise<RunnerTickSummary>;
115
107
  export declare function runRunnerDoctor(options?: RunnerCliOptions): Promise<RunnerDoctorSummary>;
116
- export declare function checkRunnerBinaryTrust(executablePath: string | undefined): RunnerBinaryTrustResult;
117
108
  export declare function extractRunnerDirectives(metadata: Record<string, unknown> | undefined): readonly RunnerDirective[];
118
109
  export declare function assertRunnerDirectiveTrusted(directive: unknown, jobId: string): asserts directive is RunnerDirective;
119
110
  export declare function runRunnerCli(argv: readonly string[], options?: RunnerCliOptions): Promise<number>;
120
- export declare function runnerTrustRelativePath(packageRoot: string, executablePath: string): string;
121
- export {};
@@ -1,13 +1,13 @@
1
- import{createHash as ee,randomBytes as te}from"node:crypto";import{existsSync as re,readFileSync as ne,realpathSync as oe}from"node:fs";import{dirname as x,join as J,relative as ae,resolve as N}from"node:path";import{openContinuitySqliteStore as B}from"../continuity/sqlite-store.js";import{invoke as se}from"../commands/invoke.js";import{runRunnerSchedulerCommand as V}from"./scheduler.js";const d=Object.freeze({OK:"continuity-ok",LEASE_CONFLICT:"lease-conflict",LEASE_EXPIRED:"lease-expired",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted",RUNNER_DIRECTIVE_UNTRUSTED:"runner-directive-untrusted",RUNNER_SERVER_INVOKE_FAILED:"runner-server-invoke-failed",SQLITE_ADAPTER_UNAVAILABLE:"sqlite-adapter-unavailable",SQLITE_INTEGRITY_FAILED:"sqlite-integrity-failed",BACKOFF_SCHEDULED:"backoff-scheduled",MISSED_RUN_CATCHUP:"missed-run-catchup"}),ce=300*1e3,de=30*1e3,ie=30*1e3,ue=1,le=10,q=new Set(["@ornexus/neocortex","@neocortex/client"]),fe=new Set(["append_event","append_receipt","update_job_status","schedule_next_tick","release_lease","noop"]),pe=new Set(["goal-tick","loop-tick","jobs","runner"]),me=new Set(["accepted","applied","ignored","failed","deferred"]),ye=new Set(["draft","planned","active","running","waiting_external","waiting_human","backoff","paused","blocked","completed","aborted","cancelled"]),be=/(raw[_-]?logs?|prompt(?:[_-]?(?:body|text))?|private[_-]?urls?|secret|token|password|protected(?:[_-]?(?:field|body|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|authorization|api[_-]?key|license[_-]?key)/i,O=/(https?:\/\/\S+|ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|-----BEGIN [A-Z ]*PRIVATE KEY-----|authorization\s*:|password\s*=|token\s*=|api[_-]?key\s*=|license[_-]?key\s*=|raw[_-]?log|transcript|stack trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY)/i,he=/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;async function Ie(e){const t=await se({args:e.args,projectRoot:e.projectRoot,format:"json",platformTarget:"runner",serverUrl:e.serverUrl});return{success:t.success,instructions:t.instructions,metadata:t.metadata,error:t.error,exitCode:t.exitCode}}async function ke(e={}){const t=N(e.projectRoot??process.cwd()),r=U(e.runnerId??Le(t)),n=e.now??(()=>new Date().toISOString()),o=$(e.dueJobLimit??ue,1,le),u=$(e.leaseMs??ce,1e3,3600*1e3),l=$(e.staleLeaseAfterMs??de,0,1440*60*1e3),a=e.idFactory??Ne,p=[],y=[];if(e.trustCheck!==!1&&!w(e.executablePath??process.argv[1]).trusted)return{ok:!1,runnerId:r,processedJobCount:0,dueJobCount:0,recoveredLeaseIds:[],receipts:[],reasonCodes:[d.RUNNER_BINARY_UNTRUSTED],publicSafe:!0};const i=await B({projectRoot:t,adapter:e.adapter,adapterLoader:e.adapterLoader,now:n});try{const s=i.recoverStaleLeases({nowIso:n(),staleAfterMs:l,limit:o*2});if(s.recoveredLeaseIds.length>0){p.push(d.LEASE_EXPIRED);for(const c of s.recoveredLeaseIds);}const f=i.listDueJobs({nowIso:n(),limit:o});if(f.length===0)return{ok:!0,runnerId:r,processedJobCount:0,dueJobCount:0,recoveredLeaseIds:s.recoveredLeaseIds,receipts:y,reasonCodes:j(p.length>0?p:[d.OK]),publicSafe:!0};for(const c of f){const b=await Se({store:i,job:c,projectRoot:t,runnerId:r,leaseMs:u,now:n,idFactory:a,serverUrl:e.serverUrl,serverInvoker:e.serverInvoker??Ie});y.push(b),p.push(b.reasonCode)}return{ok:y.every(c=>c.outcome!=="failed"),runnerId:r,processedJobCount:y.length,dueJobCount:f.length,recoveredLeaseIds:s.recoveredLeaseIds,receipts:y,reasonCodes:j(p.length>0?p:[d.OK]),publicSafe:!0}}finally{i.close()}}async function ge(e={}){const t=N(e.projectRoot??process.cwd()),r=e.now??(()=>new Date().toISOString()),n=r(),o={};let u=null,l=null;try{l=await B({projectRoot:t,adapter:e.adapter,adapterLoader:e.adapterLoader,now:r}),u=l.collectSnapshotRows({nowIso:n,jobLimit:10,staleLeaseLimit:10,receiptLimit:10,eventLimit:10,snapshotLimit:5});const c=String(l.pragmaValue("journal_mode")??"").toLowerCase();o["db-integrity"]=I("db-integrity","DB integrity","ok",[d.OK],"Continuity SQLite integrity check completed.",{jobs:g(u.counts,"jobs"),receipts:g(u.counts,"receipts"),events:g(u.counts,"events")}),o["sqlite-wal"]=I("sqlite-wal","SQLite WAL",c==="wal"?"ok":"blocked",c==="wal"?[d.OK]:[d.SQLITE_INTEGRITY_FAILED],c==="wal"?"SQLite journal mode is WAL.":"SQLite journal mode is not WAL."),o.migrations=I("migrations","Migrations",u.schemaVersion>=1?"ok":"blocked",u.schemaVersion>=1?[d.OK]:[d.SQLITE_INTEGRITY_FAILED],`Continuity schema version ${u.schemaVersion} is readable.`)}catch(c){const b=Y(c);o["db-integrity"]=I("db-integrity","DB integrity","blocked",[b],"Continuity SQLite could not be opened safely."),o["sqlite-wal"]=I("sqlite-wal","SQLite WAL","blocked",[b],"SQLite WAL could not be verified."),o.migrations=I("migrations","Migrations","blocked",[b],"Continuity migrations could not be verified.")}finally{if(l)try{l.close()}catch{}}const a=u?g(u.counts,"staleLeases"):0;o.leases=I("leases","Lease health",a>0?"degraded":"ok",a>0?[d.LEASE_EXPIRED]:[d.OK],a>0?"Stale leases are eligible for bounded recovery.":"No stale leases reported.",{staleLeases:a});const p=u?.outboxCounts??{},y=g(p,"failed")+g(p,"dead_letter");o.outbox=I("outbox","Outbox state",y>0?"degraded":"ok",y>0?[d.BACKOFF_SCHEDULED]:[d.OK],y>0?"Failed/dead-letter outbox entries can be retried with dedupe.":"Outbox has no failed/dead-letter entries.",{pending:g(p,"pending"),failed:g(p,"failed"),deadLetter:g(p,"dead_letter")}),o.metering=I("metering","Metering receipts","ok",[d.OK],"Metering evidence is represented by public job receipts and counts only.",{receipts:u?g(u.counts,"receipts"):0}),o["portal-sync"]=I("portal-sync","Portal sync",y>0?"degraded":"ok",y>0?[d.BACKOFF_SCHEDULED]:[d.OK],y>0?"Portal sync has retryable outbox debt.":"Portal sync outbox has no failed/dead-letter entries.");const i=e.trustCheck===!1?{trusted:!0,publicSafe:!0}:w(e.executablePath??process.argv[1]);o.runner=I("runner","Runner health",i.trusted?"ok":"blocked",i.trusted?[d.OK]:[d.RUNNER_BINARY_UNTRUSTED],i.trusted?"Runner binary trust check passed.":"Runner binary trust check failed.");try{const c=await V({command:"doctor",projectRoot:t,executablePath:e.scheduler?.executablePath??e.executablePath??process.argv[1],platform:e.scheduler?.platform,env:e.scheduler?.env,dryRun:!0,intervalSeconds:e.scheduler?.intervalSeconds,strategy:e.scheduler?.strategy,allowCronFallback:e.scheduler?.allowCronFallback,trustCheck:e.scheduler?.trustCheck??e.trustCheck,uid:e.scheduler?.uid,commandAvailable:e.scheduler?.commandAvailable,commandRunner:e.scheduler?.commandRunner,trustChecker:e.scheduler?.trustChecker??w}),b=c.reasonCodes.includes(d.RUNNER_BINARY_UNTRUSTED)||c.reasonCodes.includes("scheduler-install-unsafe");o.scheduler=I("scheduler","Scheduler install",b?"blocked":c.ok?"ok":"degraded",c.reasonCodes,c.ok?"Scheduler doctor selected a user-scope strategy.":"Scheduler doctor found public guidance or degraded capability.",{manifests:c.manifestPaths.length,controlCommands:c.controlCommands.length})}catch(c){o.scheduler=I("scheduler","Scheduler install","degraded",["scheduler-command-failed"],T(c))}const s=o,f=j(Object.values(s).flatMap(c=>c.reasonCodes));return{ok:Object.values(s).every(c=>c.status!=="blocked"),generatedAt:n,checks:s,reasonCodes:f,publicSafe:!0}}function w(e){if(!e)return S();const t=H(N(e));if(!t||!re(t))return S({executablePath:e});const r=$e(x(t));if(!r)return S({executablePath:t});const{packageRoot:n,pkg:o}=r,u=typeof o.name=="string"?o.name:void 0,l=typeof o.version=="string"?o.version:void 0;if(!u||!q.has(u)||!l||!he.test(l))return S({executablePath:t,packageName:u,packageVersion:l,packageRoot:n});const a=Fe(o,u);if(!a)return S({executablePath:t,packageName:u,packageVersion:l,packageRoot:n});const p=H(N(n,a));if(!p||p!==t)return S({executablePath:t,packageName:u,packageVersion:l,packageRoot:n,expectedRelativePath:a});const y=Pe(n);return u==="@neocortex/client"&&y&&y.pkg.version!==l?S({executablePath:t,packageName:u,packageVersion:l,packageRoot:n,expectedRelativePath:a}):{trusted:!0,packageName:u,packageVersion:l,packageRoot:n,executablePath:t,expectedRelativePath:a,publicSafe:!0}}function Ee(e){if(!e)return[];const t=[e.continuityRunnerDirectives,e.runnerDirectives,e.continuityDirectives];for(const r of t)if(Array.isArray(r))return r.filter(E).map(Te).filter(je);return[]}function Re(e,t){if(!E(e))throw new k("Directive is not a public record.");if(e.publicSafe!==!0)throw new k("Directive is not marked public-safe.");const r=typeof e.kind=="string"?e.kind:typeof e.type=="string"?e.type:"";if(!fe.has(r))throw new k("Directive kind is not allowlisted.");const n=typeof e.commandClass=="string"?e.commandClass:"runner";if(!pe.has(n))throw new k("Directive command class is not allowlisted.");if((typeof e.jobId=="string"?e.jobId:t)!==t)throw new k("Directive job ID does not match the leased job.");P(e,"directive")}async function Ye(e,t={}){const r=ve(e);if(r.command==="help")return process.stdout.write(`${Ce}
2
- `),0;if(r.command==="version"){const n=w(t.executablePath??process.argv[1]);return process.stdout.write(`${n.packageVersion??"0.0.0"}
3
- `),n.trusted?0:1}if(r.command==="doctor")try{const n=await ge({...t,projectRoot:r.projectRoot??t.projectRoot,executablePath:t.executablePath??process.argv[1],scheduler:{...t.scheduler,strategy:r.strategy??t.scheduler?.strategy,allowCronFallback:r.allowCronFallback??t.scheduler?.allowCronFallback,executablePath:t.scheduler?.executablePath??t.executablePath??process.argv[1]}});return process.stdout.write(JSON.stringify(n)+`
4
- `),n.ok?0:1}catch(n){return process.stderr.write(JSON.stringify({error_code:"runner-doctor-failed",message:T(n)})+`
5
- `),1}if(Q(r.command))try{const n=await V({command:r.command,projectRoot:r.projectRoot??t.projectRoot,executablePath:t.scheduler?.executablePath??t.executablePath??process.argv[1],platform:t.scheduler?.platform,env:t.scheduler?.env,dryRun:r.dryRun??t.scheduler?.dryRun,intervalSeconds:r.intervalSeconds??t.scheduler?.intervalSeconds,strategy:r.strategy??t.scheduler?.strategy,allowCronFallback:r.allowCronFallback??t.scheduler?.allowCronFallback,trustCheck:t.scheduler?.trustCheck,uid:t.scheduler?.uid,commandAvailable:t.scheduler?.commandAvailable,commandRunner:t.scheduler?.commandRunner,trustChecker:t.scheduler?.trustChecker??w});return process.stdout.write(JSON.stringify(n)+`
6
- `),n.ok?0:1}catch(n){return process.stderr.write(JSON.stringify({error_code:"scheduler-command-failed",message:T(n)})+`
1
+ import{createHash as z,randomBytes as H}from"node:crypto";import{resolve as K}from"node:path";import{openContinuitySqliteStore as P}from"../continuity/sqlite-store.js";import{invoke as W}from"../commands/invoke.js";import{checkRunnerBinaryTrust as v}from"./binary.js";import{runRunnerSchedulerCommand as M}from"./scheduler.js";import{RUNNER_BINARY_REASON_CODES as xe,checkRunnerBinaryTrust as Fe,runnerTrustRelativePath as Ke}from"./binary.js";const i=Object.freeze({OK:"continuity-ok",LEASE_CONFLICT:"lease-conflict",LEASE_EXPIRED:"lease-expired",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted",RUNNER_DIRECTIVE_UNTRUSTED:"runner-directive-untrusted",RUNNER_SERVER_INVOKE_FAILED:"runner-server-invoke-failed",SQLITE_ADAPTER_UNAVAILABLE:"sqlite-adapter-unavailable",SQLITE_INTEGRITY_FAILED:"sqlite-integrity-failed",BACKOFF_SCHEDULED:"backoff-scheduled",MISSED_RUN_CATCHUP:"missed-run-catchup"}),G=300*1e3,X=30*1e3,Z=30*1e3,ee=1,te=10,re=new Set(["append_event","append_receipt","update_job_status","schedule_next_tick","release_lease","noop"]),ne=new Set(["goal-tick","loop-tick","jobs","runner"]),oe=new Set(["accepted","applied","ignored","failed","deferred"]),ae=new Set(["draft","planned","active","running","waiting_external","waiting_human","backoff","paused","blocked","completed","aborted","cancelled"]),se=/(raw[_-]?logs?|prompt(?:[_-]?(?:body|text))?|private[_-]?urls?|secret|token|password|protected(?:[_-]?(?:field|body|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|authorization|api[_-]?key|license[_-]?key)/i,j=/(https?:\/\/\S+|ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|-----BEGIN [A-Z ]*PRIVATE KEY-----|authorization\s*:|password\s*=|token\s*=|api[_-]?key\s*=|license[_-]?key\s*=|raw[_-]?log|transcript|stack trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY)/i;async function de(e){const t=await W({args:e.args,projectRoot:e.projectRoot,format:"json",platformTarget:"runner",serverUrl:e.serverUrl});return{success:t.success,instructions:t.instructions,metadata:t.metadata,error:t.error,exitCode:t.exitCode}}async function ce(e={}){const t=K(e.projectRoot??process.cwd()),r=O(e.runnerId??ke(t)),n=e.now??(()=>new Date().toISOString()),o=U(e.dueJobLimit??ee,1,te),l=U(e.leaseMs??G,1e3,3600*1e3),f=U(e.staleLeaseAfterMs??X,0,1440*60*1e3),d=e.idFactory??Ee,m=[],b=[];if(e.trustCheck!==!1){const a=v(e.executablePath??process.argv[1]);if(!a.trusted)return{ok:!1,runnerId:r,processedJobCount:0,dueJobCount:0,recoveredLeaseIds:[],receipts:[],reasonCodes:[a.reasonCode??i.RUNNER_BINARY_UNTRUSTED],publicSafe:!0}}const c=await P({projectRoot:t,adapter:e.adapter,adapterLoader:e.adapterLoader,now:n});try{const a=c.recoverStaleLeases({nowIso:n(),staleAfterMs:f,limit:o*2});if(a.recoveredLeaseIds.length>0){m.push(i.LEASE_EXPIRED);for(const s of a.recoveredLeaseIds);}const u=c.listDueJobs({nowIso:n(),limit:o});if(u.length===0)return{ok:!0,runnerId:r,processedJobCount:0,dueJobCount:0,recoveredLeaseIds:a.recoveredLeaseIds,receipts:b,reasonCodes:T(m.length>0?m:[i.OK]),publicSafe:!0};for(const s of u){const y=await fe({store:c,job:s,projectRoot:t,runnerId:r,leaseMs:l,now:n,idFactory:d,serverUrl:e.serverUrl,serverInvoker:e.serverInvoker??de});b.push(y),m.push(y.reasonCode)}return{ok:b.every(s=>s.outcome!=="failed"),runnerId:r,processedJobCount:b.length,dueJobCount:u.length,recoveredLeaseIds:a.recoveredLeaseIds,receipts:b,reasonCodes:T(m.length>0?m:[i.OK]),publicSafe:!0}}finally{c.close()}}async function ie(e={}){const t=K(e.projectRoot??process.cwd()),r=e.now??(()=>new Date().toISOString()),n=r(),o={};let l=null,f=null;try{f=await P({projectRoot:t,adapter:e.adapter,adapterLoader:e.adapterLoader,now:r}),l=f.collectSnapshotRows({nowIso:n,jobLimit:10,staleLeaseLimit:10,receiptLimit:10,eventLimit:10,snapshotLimit:5});const s=String(f.pragmaValue("journal_mode")??"").toLowerCase();o["db-integrity"]=I("db-integrity","DB integrity","ok",[i.OK],"Continuity SQLite integrity check completed.",{jobs:E(l.counts,"jobs"),receipts:E(l.counts,"receipts"),events:E(l.counts,"events")}),o["sqlite-wal"]=I("sqlite-wal","SQLite WAL",s==="wal"?"ok":"blocked",s==="wal"?[i.OK]:[i.SQLITE_INTEGRITY_FAILED],s==="wal"?"SQLite journal mode is WAL.":"SQLite journal mode is not WAL."),o.migrations=I("migrations","Migrations",l.schemaVersion>=1?"ok":"blocked",l.schemaVersion>=1?[i.OK]:[i.SQLITE_INTEGRITY_FAILED],`Continuity schema version ${l.schemaVersion} is readable.`)}catch(s){const y=B(s);o["db-integrity"]=I("db-integrity","DB integrity","blocked",[y],"Continuity SQLite could not be opened safely."),o["sqlite-wal"]=I("sqlite-wal","SQLite WAL","blocked",[y],"SQLite WAL could not be verified."),o.migrations=I("migrations","Migrations","blocked",[y],"Continuity migrations could not be verified.")}finally{if(f)try{f.close()}catch{}}const d=l?E(l.counts,"staleLeases"):0;o.leases=I("leases","Lease health",d>0?"degraded":"ok",d>0?[i.LEASE_EXPIRED]:[i.OK],d>0?"Stale leases are eligible for bounded recovery.":"No stale leases reported.",{staleLeases:d});const m=l?.outboxCounts??{},b=E(m,"failed")+E(m,"dead_letter");o.outbox=I("outbox","Outbox state",b>0?"degraded":"ok",b>0?[i.BACKOFF_SCHEDULED]:[i.OK],b>0?"Failed/dead-letter outbox entries can be retried with dedupe.":"Outbox has no failed/dead-letter entries.",{pending:E(m,"pending"),failed:E(m,"failed"),deadLetter:E(m,"dead_letter")}),o.metering=I("metering","Metering receipts","ok",[i.OK],"Metering evidence is represented by public job receipts and counts only.",{receipts:l?E(l.counts,"receipts"):0}),o["portal-sync"]=I("portal-sync","Portal sync",b>0?"degraded":"ok",b>0?[i.BACKOFF_SCHEDULED]:[i.OK],b>0?"Portal sync has retryable outbox debt.":"Portal sync outbox has no failed/dead-letter entries.");const c=e.trustCheck===!1?{trusted:!0,publicSafe:!0}:v(e.executablePath??process.argv[1]);o.runner=I("runner","Runner health",c.trusted?"ok":"blocked",c.trusted?[i.OK]:[c.reasonCode??i.RUNNER_BINARY_UNTRUSTED],c.trusted?"Runner binary trust check passed.":"Runner binary trust check failed.");try{const s=await M({command:"doctor",projectRoot:t,executablePath:e.scheduler?.executablePath??e.executablePath??process.argv[1],platform:e.scheduler?.platform,env:e.scheduler?.env,dryRun:!0,intervalSeconds:e.scheduler?.intervalSeconds,strategy:e.scheduler?.strategy,allowCronFallback:e.scheduler?.allowCronFallback,trustCheck:e.scheduler?.trustCheck??e.trustCheck,uid:e.scheduler?.uid,commandAvailable:e.scheduler?.commandAvailable,commandRunner:e.scheduler?.commandRunner,trustChecker:e.scheduler?.trustChecker??v}),y=s.reasonCodes.includes(i.RUNNER_BINARY_UNTRUSTED)||s.reasonCodes.some(w=>w.startsWith("runner-binary-"))||s.reasonCodes.includes("scheduler-install-unsafe");o.scheduler=I("scheduler","Scheduler install",y?"blocked":s.ok?"ok":"degraded",s.reasonCodes,s.ok?"Scheduler doctor selected a user-scope strategy.":"Scheduler doctor found public guidance or degraded capability.",{manifests:s.manifestPaths.length,controlCommands:s.controlCommands.length,legacyEntries:s.legacyEntries.length})}catch(s){o.scheduler=I("scheduler","Scheduler install","degraded",["scheduler-command-failed"],N(s))}const a=o,u=T(Object.values(a).flatMap(s=>s.reasonCodes));return{ok:Object.values(a).every(s=>s.status!=="blocked"),generatedAt:n,checks:a,reasonCodes:u,publicSafe:!0}}function ue(e){if(!e)return[];const t=[e.continuityRunnerDirectives,e.runnerDirectives,e.continuityDirectives];for(const r of t)if(Array.isArray(r))return r.filter(R).map(Re).filter(Se);return[]}function le(e,t){if(!R(e))throw new k("Directive is not a public record.");if(e.publicSafe!==!0)throw new k("Directive is not marked public-safe.");const r=typeof e.kind=="string"?e.kind:typeof e.type=="string"?e.type:"";if(!re.has(r))throw new k("Directive kind is not allowlisted.");const n=typeof e.commandClass=="string"?e.commandClass:"runner";if(!ne.has(n))throw new k("Directive command class is not allowlisted.");if((typeof e.jobId=="string"?e.jobId:t)!==t)throw new k("Directive job ID does not match the leased job.");$(e,"directive")}async function Oe(e,t={}){const r=ye(e);if(r.command==="help")return process.stdout.write(`${be}
2
+ `),0;if(r.command==="version"){const n=v(t.executablePath??process.argv[1]);return process.stdout.write(`${n.packageVersion??"0.0.0"}
3
+ `),n.trusted?0:1}if(r.command==="doctor")try{const n=await ie({...t,projectRoot:r.projectRoot??t.projectRoot,executablePath:t.executablePath??process.argv[1],scheduler:{...t.scheduler,strategy:r.strategy??t.scheduler?.strategy,allowCronFallback:r.allowCronFallback??t.scheduler?.allowCronFallback,executablePath:t.scheduler?.executablePath??t.executablePath??process.argv[1]}});return process.stdout.write(JSON.stringify(n)+`
4
+ `),n.ok?0:1}catch(n){return process.stderr.write(JSON.stringify({error_code:"runner-doctor-failed",message:N(n)})+`
5
+ `),1}if(J(r.command))try{const n=await M({command:r.command,projectRoot:r.projectRoot??t.projectRoot,executablePath:t.scheduler?.executablePath??t.executablePath??process.argv[1],platform:t.scheduler?.platform,env:t.scheduler?.env,dryRun:r.dryRun??t.scheduler?.dryRun,intervalSeconds:r.intervalSeconds??t.scheduler?.intervalSeconds,strategy:r.strategy??t.scheduler?.strategy,allowCronFallback:r.allowCronFallback??t.scheduler?.allowCronFallback,trustCheck:t.scheduler?.trustCheck,uid:t.scheduler?.uid,commandAvailable:t.scheduler?.commandAvailable,commandRunner:t.scheduler?.commandRunner,trustChecker:t.scheduler?.trustChecker??v});return process.stdout.write(JSON.stringify(Ie(n))+`
6
+ `),n.ok?0:1}catch(n){return process.stderr.write(JSON.stringify({error_code:"scheduler-command-failed",message:N(n)})+`
7
7
  `),1}if(r.command!=="tick")return process.stderr.write(JSON.stringify({error_code:"runner-command-unknown",message:"Unknown neocortex-runner command."})+`
8
- `),1;try{const n=await ke({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,dueJobLimit:r.limit??t.dueJobLimit,leaseMs:r.leaseMs??t.leaseMs,staleLeaseAfterMs:r.staleLeaseAfterMs??t.staleLeaseAfterMs,serverUrl:r.serverUrl??t.serverUrl});return process.stdout.write(JSON.stringify(n)+`
9
- `),n.ok?0:1}catch(n){const o=Y(n);return process.stderr.write(JSON.stringify({error_code:o,message:T(n)})+`
10
- `),1}}async function Se(e){const{store:t,job:r,projectRoot:n,runnerId:o,leaseMs:u,now:l,idFactory:a,serverUrl:p,serverInvoker:y}=e,i=r.job_id,s=a("tick",i),f=a("lease",i),c=l(),b=new Date(Date.parse(c)+u).toISOString();let K=!1,M=!1,h=d.OK,v="applied",R=[];if(!t.acquireLease({leaseId:f,jobId:i,runnerId:o,acquiredAt:c,expiresAt:b,operationId:`${s}:acquire`,idempotencyKey:`${s}:acquire`,metadata:A({jobId:i,operationId:s,runnerId:o,leaseId:f,status:"running",reasonCode:d.OK})}).inserted)return D(t,{jobId:i,tickId:s,leaseId:f,status:"ignored",reasonCode:d.LEASE_CONFLICT,createdAt:l(),redactionSummary:R});K=!0;try{t.appendEvent({eventId:`${s}:started`,jobId:i,operationId:`${s}:event:started`,idempotencyKey:`${s}:event:started`,type:"runner_tick_started",summary:`Runner tick started for ${i}.`,reasonCode:d.OK,createdAt:c,metadata:A({jobId:i,operationId:s,runnerId:o,leaseId:f,status:"running",reasonCode:d.OK})});const W=r.kind==="loop"?`*loop tick @${i} --tick-id ${s} --lease-id ${f} --runner-id ${o}`:r.kind==="goal"?`*goal tick @${i} --tick-id ${s} --lease-id ${f} --runner-id ${o}`:`*runner tick --job-id ${i} --tick-id ${s} --lease-id ${f} --runner-id ${o}`,L=await y({projectRoot:n,args:W,jobId:i,tickId:s,leaseId:f,runnerId:o,serverUrl:p});if(!L.success){h=d.RUNNER_SERVER_INVOKE_FAILED,v="failed";const _=l();return t.updateJobStatus({jobId:i,status:"backoff",updatedAt:_,reasonCode:d.BACKOFF_SCHEDULED,nextRunAt:De(_,ie)}),t.appendEvent({eventId:`${s}:server-failed`,jobId:i,operationId:`${s}:event:server-failed`,idempotencyKey:`${s}:event:server-failed`,type:"runner_tick_failed",summary:"Runner server tick invocation failed with public reason code.",reasonCode:h,createdAt:_,metadata:A({jobId:i,operationId:s,runnerId:o,leaseId:f,status:"failed",reasonCode:h})}),D(t,{jobId:i,tickId:s,leaseId:f,status:v,reasonCode:h,createdAt:l(),redactionSummary:R})}const X=Ee(L.metadata);let C={appliedCount:0,releasedLease:!1,changedStatus:!1,redactionSummary:[]};try{C=_e(t,X,{jobId:i,tickId:s,leaseId:f,runnerId:o,now:l}),M=C.releasedLease,R=[...C.redactionSummary],h=Ae(L.metadata)??h}catch(_){return h=d.RUNNER_DIRECTIVE_UNTRUSTED,v="failed",R=[_ instanceof Error?_.message:"Directive rejected."],t.updateJobStatus({jobId:i,status:"blocked",updatedAt:l(),reasonCode:h}),t.appendEvent({eventId:`${s}:directive-rejected`,jobId:i,operationId:`${s}:event:directive-rejected`,idempotencyKey:`${s}:event:directive-rejected`,type:"runner_directive_rejected",summary:"Runner rejected an untrusted continuity directive.",reasonCode:h,createdAt:l(),metadata:A({jobId:i,operationId:s,runnerId:o,leaseId:f,status:"failed",reasonCode:h,redactionSummary:R})}),D(t,{jobId:i,tickId:s,leaseId:f,status:v,reasonCode:h,createdAt:l(),redactionSummary:R})}const Z=!!L.metadata?.continuityStateUpdate;return!C.changedStatus&&!Z&&t.updateJobStatus({jobId:i,status:"active",updatedAt:l(),reasonCode:d.OK}),t.appendEvent({eventId:`${s}:completed`,jobId:i,operationId:`${s}:event:completed`,idempotencyKey:`${s}:event:completed`,type:"runner_tick_completed",summary:`Runner tick completed with ${C.appliedCount} public directive(s).`,reasonCode:h,createdAt:l(),metadata:A({jobId:i,operationId:s,runnerId:o,leaseId:f,status:"applied",reasonCode:h})}),D(t,{jobId:i,tickId:s,leaseId:f,status:v,reasonCode:h,createdAt:l(),redactionSummary:R})}finally{if(K&&!M)try{t.releaseLease({leaseId:f,releasedAt:l(),reasonCode:h})}catch{}}}function _e(e,t,r){let n=0,o=!1,u=!1;const l=[];for(const a of t){switch(Re(a,r.jobId),a.kind){case"noop":n+=1;break;case"append_event":e.appendEvent({eventId:m(a,"eventId")??`${r.tickId}:directive:${n}:event`,jobId:r.jobId,operationId:m(a,"operationId")??`${r.tickId}:directive:${n}:event`,idempotencyKey:m(a,"idempotencyKey")??`${r.tickId}:directive:${n}:event`,type:m(a,"eventType")??"runner_directive_event",summary:m(a,"summary")??"Runner applied public continuity event directive.",reasonCode:m(a,"reasonCode")??d.OK,createdAt:m(a,"createdAt")??r.now(),metadata:z(a)}),n+=1;break;case"append_receipt":e.appendReceipt({receiptId:m(a,"receiptId")??`${r.tickId}:directive:${n}:receipt`,jobId:r.jobId,operationId:m(a,"operationId")??`${r.tickId}:directive:${n}:receipt`,idempotencyKey:m(a,"idempotencyKey")??`${r.tickId}:directive:${n}:receipt`,status:Oe(m(a,"status")),reasonCode:m(a,"reasonCode")??d.OK,createdAt:m(a,"createdAt")??r.now(),metadata:z(a)}),n+=1;break;case"update_job_status":e.updateJobStatus({jobId:r.jobId,status:Ue(m(a,"status")),updatedAt:m(a,"updatedAt")??r.now(),reasonCode:m(a,"reasonCode")??d.OK,nextRunAt:m(a,"nextRunAt")}),n+=1,u=!0;break;case"schedule_next_tick":e.scheduleNextTick({jobId:r.jobId,scheduledAt:xe(a,"scheduledAt"),updatedAt:m(a,"updatedAt")??r.now(),reasonCode:m(a,"reasonCode")??d.OK}),n+=1,u=!0;break;case"release_lease":e.releaseLease({leaseId:m(a,"leaseId")??r.leaseId,releasedAt:m(a,"releasedAt")??r.now(),reasonCode:m(a,"reasonCode")??d.OK}),n+=1,o=!0;break}const p=a.redactionSummary;Array.isArray(p)&&l.push(...p.filter(y=>typeof y=="string").slice(0,5))}return{appliedCount:n,releasedLease:o,changedStatus:u,redactionSummary:l}}function D(e,t){const r={receiptId:`receipt-${U(t.tickId)}`,jobId:t.jobId,operationId:t.tickId,idempotencyKey:t.tickId,status:t.status,reasonCode:t.reasonCode,appliedOperationIds:t.status==="applied"?[t.tickId]:void 0,ignoredOperationIds:t.status==="ignored"?[t.tickId]:void 0,createdAt:t.createdAt,metadata:A({jobId:t.jobId,operationId:t.tickId,leaseId:t.leaseId,status:t.status,reasonCode:t.reasonCode,redactionSummary:t.redactionSummary})};return e.appendReceipt(r),{jobId:t.jobId,tickId:t.tickId,leaseId:t.leaseId,outcome:t.status,reasonCode:t.reasonCode,timestamp:t.createdAt,redactionSummary:t.redactionSummary,publicSafe:!0}}function A(e){return{schemaVersion:1,contractVersion:"continuity-v1",jobId:e.jobId,operationId:e.operationId,...e.runnerId?{runnerId:e.runnerId}:{},...e.leaseId?{leaseId:e.leaseId}:{},status:e.status,reasonCode:e.reasonCode,redactionEvidence:(e.redactionSummary??[]).slice(0,20).map(t=>({field:F(t,80),reason:"unsafe_key",evidence:"operation-denied",publicSafe:!0}))}}function Ae(e){if(!e)return null;const t=E(e.continuity)?e.continuity:void 0,n=[(t&&E(t.loop)?t.loop:void 0)?.reasonCode,t?.reasonCode];for(const o of n)if(typeof o=="string"&&/^[a-z0-9][a-z0-9-]{0,79}$/.test(o)&&!O.test(o))return o;return null}function ve(e){const t=e[0];if(!t||t==="--help"||t==="-h"||t==="help")return{command:"help"};if(t==="--version"||t==="-v"||t==="version")return{command:"version"};if(t!=="tick"&&!Q(t))return{command:"unknown"};let r,n,o,u,l,a,p,y,i,s;for(let f=1;f<e.length;f++){const c=e[f],b=e[f+1];if(c==="--project-root"){r=b,f+=1;continue}if(c==="--runner-id"){n=b,f+=1;continue}if(c==="--server-url"){o=b,f+=1;continue}if(c==="--limit"){u=Number(b),f+=1;continue}if(c==="--lease-ms"){l=Number(b),f+=1;continue}if(c==="--stale-lease-after-ms"){a=Number(b),f+=1;continue}if(c==="--dry-run"){p=!0;continue}if(c==="--interval-seconds"){y=Number(b),f+=1;continue}if(c==="--strategy"&&we(b)){i=b,f+=1;continue}if(c==="--allow-cron-fallback"){s=!0;continue}if(c==="--no-cron-fallback"){s=!1;continue}}return{command:t,projectRoot:r,runnerId:n,serverUrl:o,limit:u,leaseMs:l,staleLeaseAfterMs:a,dryRun:p,intervalSeconds:y,strategy:i,allowCronFallback:s}}const Ce=`
8
+ `),1;try{const n=await ce({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,dueJobLimit:r.limit??t.dueJobLimit,leaseMs:r.leaseMs??t.leaseMs,staleLeaseAfterMs:r.staleLeaseAfterMs??t.staleLeaseAfterMs,serverUrl:r.serverUrl??t.serverUrl});return process.stdout.write(JSON.stringify(n)+`
9
+ `),n.ok?0:1}catch(n){const o=B(n);return process.stderr.write(JSON.stringify({error_code:o,message:N(n)})+`
10
+ `),1}}async function fe(e){const{store:t,job:r,projectRoot:n,runnerId:o,leaseMs:l,now:f,idFactory:d,serverUrl:m,serverInvoker:b}=e,c=r.job_id,a=d("tick",c),u=d("lease",c),s=f(),y=new Date(Date.parse(s)+l).toISOString();let w=!1,F=!1,h=i.OK,C="applied",g=[];if(!t.acquireLease({leaseId:u,jobId:c,runnerId:o,acquiredAt:s,expiresAt:y,operationId:`${a}:acquire`,idempotencyKey:`${a}:acquire`,metadata:_({jobId:c,operationId:a,runnerId:o,leaseId:u,status:"running",reasonCode:i.OK})}).inserted)return D(t,{jobId:c,tickId:a,leaseId:u,status:"ignored",reasonCode:i.LEASE_CONFLICT,createdAt:f(),redactionSummary:g});w=!0;try{t.appendEvent({eventId:`${a}:started`,jobId:c,operationId:`${a}:event:started`,idempotencyKey:`${a}:event:started`,type:"runner_tick_started",summary:`Runner tick started for ${c}.`,reasonCode:i.OK,createdAt:s,metadata:_({jobId:c,operationId:a,runnerId:o,leaseId:u,status:"running",reasonCode:i.OK})});const q=r.kind==="loop"?`*loop tick @${c} --tick-id ${a} --lease-id ${u} --runner-id ${o}`:r.kind==="goal"?`*goal tick @${c} --tick-id ${a} --lease-id ${u} --runner-id ${o}`:`*runner tick --job-id ${c} --tick-id ${a} --lease-id ${u} --runner-id ${o}`,L=await b({projectRoot:n,args:q,jobId:c,tickId:a,leaseId:u,runnerId:o,serverUrl:m});if(!L.success){h=i.RUNNER_SERVER_INVOKE_FAILED,C="failed";const S=f();return t.updateJobStatus({jobId:c,status:"backoff",updatedAt:S,reasonCode:i.BACKOFF_SCHEDULED,nextRunAt:ge(S,Z)}),t.appendEvent({eventId:`${a}:server-failed`,jobId:c,operationId:`${a}:event:server-failed`,idempotencyKey:`${a}:event:server-failed`,type:"runner_tick_failed",summary:"Runner server tick invocation failed with public reason code.",reasonCode:h,createdAt:S,metadata:_({jobId:c,operationId:a,runnerId:o,leaseId:u,status:"failed",reasonCode:h})}),D(t,{jobId:c,tickId:a,leaseId:u,status:C,reasonCode:h,createdAt:f(),redactionSummary:g})}const Q=ue(L.metadata);let A={appliedCount:0,releasedLease:!1,changedStatus:!1,redactionSummary:[]};try{A=pe(t,Q,{jobId:c,tickId:a,leaseId:u,runnerId:o,now:f}),F=A.releasedLease,g=[...A.redactionSummary],h=me(L.metadata)??h}catch(S){return h=i.RUNNER_DIRECTIVE_UNTRUSTED,C="failed",g=[S instanceof Error?S.message:"Directive rejected."],t.updateJobStatus({jobId:c,status:"blocked",updatedAt:f(),reasonCode:h}),t.appendEvent({eventId:`${a}:directive-rejected`,jobId:c,operationId:`${a}:event:directive-rejected`,idempotencyKey:`${a}:event:directive-rejected`,type:"runner_directive_rejected",summary:"Runner rejected an untrusted continuity directive.",reasonCode:h,createdAt:f(),metadata:_({jobId:c,operationId:a,runnerId:o,leaseId:u,status:"failed",reasonCode:h,redactionSummary:g})}),D(t,{jobId:c,tickId:a,leaseId:u,status:C,reasonCode:h,createdAt:f(),redactionSummary:g})}const Y=!!L.metadata?.continuityStateUpdate;return!A.changedStatus&&!Y&&t.updateJobStatus({jobId:c,status:"active",updatedAt:f(),reasonCode:i.OK}),t.appendEvent({eventId:`${a}:completed`,jobId:c,operationId:`${a}:event:completed`,idempotencyKey:`${a}:event:completed`,type:"runner_tick_completed",summary:`Runner tick completed with ${A.appliedCount} public directive(s).`,reasonCode:h,createdAt:f(),metadata:_({jobId:c,operationId:a,runnerId:o,leaseId:u,status:"applied",reasonCode:h})}),D(t,{jobId:c,tickId:a,leaseId:u,status:C,reasonCode:h,createdAt:f(),redactionSummary:g})}finally{if(w&&!F)try{t.releaseLease({leaseId:u,releasedAt:f(),reasonCode:h})}catch{}}}function pe(e,t,r){let n=0,o=!1,l=!1;const f=[];for(const d of t){switch(le(d,r.jobId),d.kind){case"noop":n+=1;break;case"append_event":e.appendEvent({eventId:p(d,"eventId")??`${r.tickId}:directive:${n}:event`,jobId:r.jobId,operationId:p(d,"operationId")??`${r.tickId}:directive:${n}:event`,idempotencyKey:p(d,"idempotencyKey")??`${r.tickId}:directive:${n}:event`,type:p(d,"eventType")??"runner_directive_event",summary:p(d,"summary")??"Runner applied public continuity event directive.",reasonCode:p(d,"reasonCode")??i.OK,createdAt:p(d,"createdAt")??r.now(),metadata:V(d)}),n+=1;break;case"append_receipt":e.appendReceipt({receiptId:p(d,"receiptId")??`${r.tickId}:directive:${n}:receipt`,jobId:r.jobId,operationId:p(d,"operationId")??`${r.tickId}:directive:${n}:receipt`,idempotencyKey:p(d,"idempotencyKey")??`${r.tickId}:directive:${n}:receipt`,status:Ce(p(d,"status")),reasonCode:p(d,"reasonCode")??i.OK,createdAt:p(d,"createdAt")??r.now(),metadata:V(d)}),n+=1;break;case"update_job_status":e.updateJobStatus({jobId:r.jobId,status:Ae(p(d,"status")),updatedAt:p(d,"updatedAt")??r.now(),reasonCode:p(d,"reasonCode")??i.OK,nextRunAt:p(d,"nextRunAt")}),n+=1,l=!0;break;case"schedule_next_tick":e.scheduleNextTick({jobId:r.jobId,scheduledAt:_e(d,"scheduledAt"),updatedAt:p(d,"updatedAt")??r.now(),reasonCode:p(d,"reasonCode")??i.OK}),n+=1,l=!0;break;case"release_lease":e.releaseLease({leaseId:p(d,"leaseId")??r.leaseId,releasedAt:p(d,"releasedAt")??r.now(),reasonCode:p(d,"reasonCode")??i.OK}),n+=1,o=!0;break}const m=d.redactionSummary;Array.isArray(m)&&f.push(...m.filter(b=>typeof b=="string").slice(0,5))}return{appliedCount:n,releasedLease:o,changedStatus:l,redactionSummary:f}}function D(e,t){const r={receiptId:`receipt-${O(t.tickId)}`,jobId:t.jobId,operationId:t.tickId,idempotencyKey:t.tickId,status:t.status,reasonCode:t.reasonCode,appliedOperationIds:t.status==="applied"?[t.tickId]:void 0,ignoredOperationIds:t.status==="ignored"?[t.tickId]:void 0,createdAt:t.createdAt,metadata:_({jobId:t.jobId,operationId:t.tickId,leaseId:t.leaseId,status:t.status,reasonCode:t.reasonCode,redactionSummary:t.redactionSummary})};return e.appendReceipt(r),{jobId:t.jobId,tickId:t.tickId,leaseId:t.leaseId,outcome:t.status,reasonCode:t.reasonCode,timestamp:t.createdAt,redactionSummary:t.redactionSummary,publicSafe:!0}}function _(e){return{schemaVersion:1,contractVersion:"continuity-v1",jobId:e.jobId,operationId:e.operationId,...e.runnerId?{runnerId:e.runnerId}:{},...e.leaseId?{leaseId:e.leaseId}:{},status:e.status,reasonCode:e.reasonCode,redactionEvidence:(e.redactionSummary??[]).slice(0,20).map(t=>({field:x(t,80),reason:"unsafe_key",evidence:"operation-denied",publicSafe:!0}))}}function me(e){if(!e)return null;const t=R(e.continuity)?e.continuity:void 0,n=[(t&&R(t.loop)?t.loop:void 0)?.reasonCode,t?.reasonCode];for(const o of n)if(typeof o=="string"&&/^[a-z0-9][a-z0-9-]{0,79}$/.test(o)&&!j.test(o))return o;return null}function ye(e){const t=e[0];if(!t||t==="--help"||t==="-h"||t==="help")return{command:"help"};if(t==="--version"||t==="-v"||t==="version")return{command:"version"};if(t!=="tick"&&!J(t))return{command:"unknown"};let r,n,o,l,f,d,m,b,c,a;for(let u=1;u<e.length;u++){const s=e[u],y=e[u+1];if(s==="--project-root"){r=y,u+=1;continue}if(s==="--runner-id"){n=y,u+=1;continue}if(s==="--server-url"){o=y,u+=1;continue}if(s==="--limit"){l=Number(y),u+=1;continue}if(s==="--lease-ms"){f=Number(y),u+=1;continue}if(s==="--stale-lease-after-ms"){d=Number(y),u+=1;continue}if(s==="--dry-run"){m=!0;continue}if(s==="--interval-seconds"){b=Number(y),u+=1;continue}if(s==="--strategy"&&he(y)){c=y,u+=1;continue}if(s==="--allow-cron-fallback"){a=!0;continue}if(s==="--no-cron-fallback"){a=!1;continue}}return{command:t,projectRoot:r,runnerId:n,serverUrl:o,limit:l,leaseMs:f,staleLeaseAfterMs:d,dryRun:m,intervalSeconds:b,strategy:c,allowCronFallback:a}}const be=`
11
11
  neocortex-runner - Enterprise continuity local runner
12
12
 
13
13
  Usage:
@@ -17,4 +17,4 @@ Usage:
17
17
  neocortex-runner tick [--project-root <path>] [--limit <n>] [--lease-ms <ms>] [--stale-lease-after-ms <ms>]
18
18
  neocortex-runner --version
19
19
  neocortex-runner --help
20
- `.trim();function Q(e){return e==="install"||e==="start"||e==="stop"||e==="status"||e==="doctor"}function we(e){return e==="systemd-user"||e==="launchd-user"||e==="windows-task-scheduler"||e==="cron-fallback"}class k extends Error{constructor(t){super(t),this.name="RunnerDirectiveError"}}function Y(e){if(E(e)){const r=typeof e.reasonCode=="string"?e.reasonCode:typeof e.code=="string"?e.code:void 0;if(r===d.SQLITE_ADAPTER_UNAVAILABLE||r===d.SQLITE_INTEGRITY_FAILED)return r}const t=e instanceof Error?e.message:String(e);return/sqlite-adapter-unavailable/i.test(t)?d.SQLITE_ADAPTER_UNAVAILABLE:/sqlite-integrity-failed|not a database|file is not a database|database disk image is malformed|malformed/i.test(t)?d.SQLITE_INTEGRITY_FAILED:"runner-tick-failed"}function T(e){return F(e instanceof Error?e.message:String(e),240)}function Le(e){return`runner-${ee("sha256").update(e).update(process.pid.toString()).digest("hex").slice(0,12)}`}function Ne(e,t){const r=te(4).toString("hex");return`${e}-${U(t)}-${Date.now()}-${r}`}function U(e){return e.replace(/[^a-z0-9_.:-]+/gi,"-").slice(0,120)}function $(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,Math.floor(e))):t}function De(e,t){const r=Date.parse(e);return new Date((Number.isFinite(r)?r:Date.now())+t).toISOString()}function Te(e){return typeof e.kind=="string"?e:{...e,kind:e.type}}function je(e){return typeof e.kind=="string"&&e.publicSafe===!0}function P(e,t){if(typeof e=="string"){if(O.test(e))throw new k(`Unsafe directive value at ${t}.`);return}if(!(e===null||typeof e=="number"||typeof e=="boolean")){if(Array.isArray(e)){e.forEach((r,n)=>P(r,`${t}[${n}]`));return}if(E(e)){for(const[r,n]of Object.entries(e)){if(be.test(r))throw new k(`Unsafe directive key at ${t}.${r}.`);P(n,`${t}.${r}`)}return}throw new k(`Unsupported directive value at ${t}.`)}}function m(e,t){const r=e[t];return typeof r=="string"&&r.length>0?r:void 0}function xe(e,t){const r=m(e,t);if(!r)throw new k(`Directive missing ${t}.`);return r}function z(e){const t=e.metadata;return E(t)?t:void 0}function Oe(e){return e&&me.has(e)?e:"applied"}function Ue(e){if(!e||!ye.has(e))throw new k("Directive status is not allowlisted.");return e}function E(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function j(e){return Array.from(new Set(e))}function g(e,t){return typeof e[t]=="number"?e[t]:0}function I(e,t,r,n,o,u){return{id:e,label:t,status:r,reasonCodes:j(n.length>0?n:[d.OK]),summary:F(o,180),...u?{counts:u}:{},publicSafe:!0}}function F(e,t){const r=O.test(e)?"[REDACTED]":e;return r.length<=t?r:`${r.slice(0,t)}\u2026[TRUNCATED:${r.length-t}]`}function H(e){try{return oe(e)}catch{return null}}function $e(e){let t=e;for(let r=0;r<8;r++){const n=G(J(t,"package.json"));if(n&&typeof n.name=="string"&&q.has(n.name))return{packageRoot:t,pkg:n};const o=x(t);if(o===t)break;t=o}return null}function Pe(e){let t=e;for(let r=0;r<8;r++){const n=G(J(t,"package.json"));if(n?.name==="@ornexus/neocortex")return{packageRoot:t,pkg:n};const o=x(t);if(o===t)break;t=o}return null}function G(e){try{return JSON.parse(ne(e,"utf8"))}catch{return null}}function Fe(e,t){const r=E(e.bin)?e.bin["neocortex-runner"]:void 0;if(typeof r!="string"||r.length===0)return null;const n=r.replace(/^\.\//,"");return t==="@ornexus/neocortex"&&n!=="packages/client/dist/runner-cli.js"||t==="@neocortex/client"&&n!=="dist/runner-cli.js"?null:n}function S(e={}){return{trusted:!1,reasonCode:d.RUNNER_BINARY_UNTRUSTED,publicSafe:!0,...e}}function ze(e,t){return ae(e,t).split("\\").join("/")}export{ue as DEFAULT_DUE_JOB_LIMIT,ie as DEFAULT_RUNNER_BACKOFF_MS,ce as DEFAULT_RUNNER_LEASE_MS,de as DEFAULT_STALE_LEASE_AFTER_MS,le as MAX_DUE_JOB_LIMIT,d as RUNNER_REASON_CODES,Re as assertRunnerDirectiveTrusted,w as checkRunnerBinaryTrust,Ie as defaultRunnerServerInvoker,Ee as extractRunnerDirectives,Ye as runRunnerCli,ge as runRunnerDoctor,ke as runRunnerTick,ze as runnerTrustRelativePath};
20
+ `.trim();function J(e){return e==="install"||e==="start"||e==="stop"||e==="status"||e==="doctor"}function he(e){return e==="systemd-user"||e==="launchd-user"||e==="windows-task-scheduler"||e==="cron-fallback"}class k extends Error{constructor(t){super(t),this.name="RunnerDirectiveError"}}function B(e){if(R(e)){const r=typeof e.reasonCode=="string"?e.reasonCode:typeof e.code=="string"?e.code:void 0;if(r===i.SQLITE_ADAPTER_UNAVAILABLE||r===i.SQLITE_INTEGRITY_FAILED)return r}const t=e instanceof Error?e.message:String(e);return/sqlite-adapter-unavailable/i.test(t)?i.SQLITE_ADAPTER_UNAVAILABLE:/sqlite-integrity-failed|not a database|file is not a database|database disk image is malformed|malformed/i.test(t)?i.SQLITE_INTEGRITY_FAILED:"runner-tick-failed"}function N(e){return x(e instanceof Error?e.message:String(e),240)}function Ie(e){return e.manifests.length===0?e:{...e,manifests:e.manifests.map(t=>({...t,content:`[redacted ${t.kind} for project ${e.identity.projectKey}]`}))}}function ke(e){return`runner-${z("sha256").update(e).update(process.pid.toString()).digest("hex").slice(0,12)}`}function Ee(e,t){const r=H(4).toString("hex");return`${e}-${O(t)}-${Date.now()}-${r}`}function O(e){return e.replace(/[^a-z0-9_.:-]+/gi,"-").slice(0,120)}function U(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,Math.floor(e))):t}function ge(e,t){const r=Date.parse(e);return new Date((Number.isFinite(r)?r:Date.now())+t).toISOString()}function Re(e){return typeof e.kind=="string"?e:{...e,kind:e.type}}function Se(e){return typeof e.kind=="string"&&e.publicSafe===!0}function $(e,t){if(typeof e=="string"){if(j.test(e))throw new k(`Unsafe directive value at ${t}.`);return}if(!(e===null||typeof e=="number"||typeof e=="boolean")){if(Array.isArray(e)){e.forEach((r,n)=>$(r,`${t}[${n}]`));return}if(R(e)){for(const[r,n]of Object.entries(e)){if(se.test(r))throw new k(`Unsafe directive key at ${t}.${r}.`);$(n,`${t}.${r}`)}return}throw new k(`Unsupported directive value at ${t}.`)}}function p(e,t){const r=e[t];return typeof r=="string"&&r.length>0?r:void 0}function _e(e,t){const r=p(e,t);if(!r)throw new k(`Directive missing ${t}.`);return r}function V(e){const t=e.metadata;return R(t)?t:void 0}function Ce(e){return e&&oe.has(e)?e:"applied"}function Ae(e){if(!e||!ae.has(e))throw new k("Directive status is not allowlisted.");return e}function R(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function T(e){return Array.from(new Set(e))}function E(e,t){return typeof e[t]=="number"?e[t]:0}function I(e,t,r,n,o,l){return{id:e,label:t,status:r,reasonCodes:T(n.length>0?n:[i.OK]),summary:x(o,180),...l?{counts:l}:{},publicSafe:!0}}function x(e,t){const r=j.test(e)?"[REDACTED]":e;return r.length<=t?r:`${r.slice(0,t)}\u2026[TRUNCATED:${r.length-t}]`}export{ee as DEFAULT_DUE_JOB_LIMIT,Z as DEFAULT_RUNNER_BACKOFF_MS,G as DEFAULT_RUNNER_LEASE_MS,X as DEFAULT_STALE_LEASE_AFTER_MS,te as MAX_DUE_JOB_LIMIT,xe as RUNNER_BINARY_REASON_CODES,i as RUNNER_REASON_CODES,le as assertRunnerDirectiveTrusted,Fe as checkRunnerBinaryTrust,de as defaultRunnerServerInvoker,ue as extractRunnerDirectives,Oe as runRunnerCli,ie as runRunnerDoctor,ce as runRunnerTick,Ke as runnerTrustRelativePath};
@@ -5,6 +5,7 @@
5
5
  * P180.07 -- user-scope scheduler install/start/stop/status/doctor for
6
6
  * `neocortex-runner`.
7
7
  */
8
+ import { type RunnerBinaryResolveOptions, type RunnerBinaryResolution } from './binary.js';
8
9
  export declare const SCHEDULER_REASON_CODES: Readonly<{
9
10
  readonly OK: "continuity-ok";
10
11
  readonly SCHEDULER_INSTALL_UNSAFE: "scheduler-install-unsafe";
@@ -14,17 +15,39 @@ export declare const SCHEDULER_REASON_CODES: Readonly<{
14
15
  readonly SCHEDULER_UNAVAILABLE: "scheduler-unavailable";
15
16
  readonly SCHEDULER_COMMAND_FAILED: "scheduler-command-failed";
16
17
  readonly RUNNER_BINARY_UNTRUSTED: "runner-binary-untrusted";
18
+ readonly LEGACY_GLOBAL_SCHEDULER_DETECTED: "legacy-global-scheduler-detected";
19
+ readonly LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS: "legacy-global-scheduler-ambiguous";
20
+ readonly LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT: "legacy-global-scheduler-other-project";
21
+ }>;
22
+ export declare const RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES: Readonly<{
23
+ readonly OK: "runner-bootstrap-ok";
24
+ readonly ALREADY_ACTIVE: "runner-bootstrap-already-active";
25
+ readonly BINARY_UNAVAILABLE: "runner-bootstrap-binary-unavailable";
26
+ readonly INSTALL_FAILED: "runner-bootstrap-install-failed";
27
+ readonly START_FAILED: "runner-bootstrap-start-failed";
28
+ readonly UNEXPECTED_ERROR: "runner-bootstrap-unexpected-error";
17
29
  }>;
18
30
  export type SchedulerReasonCode = (typeof SCHEDULER_REASON_CODES)[keyof typeof SCHEDULER_REASON_CODES] | string;
31
+ export type RunnerSchedulerBootstrapReasonCode = (typeof RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES)[keyof typeof RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES] | SchedulerReasonCode;
19
32
  export type SchedulerCommand = 'install' | 'start' | 'stop' | 'status' | 'doctor';
20
33
  export type SchedulerStrategy = 'systemd-user' | 'launchd-user' | 'windows-task-scheduler' | 'cron-fallback';
21
34
  export interface SchedulerBinaryTrustResult {
22
35
  readonly trusted: boolean;
23
36
  readonly reasonCode?: string;
37
+ readonly reasonCodes?: readonly string[];
24
38
  readonly packageName?: string;
25
39
  readonly packageVersion?: string;
40
+ readonly packageRoot?: string;
26
41
  readonly executablePath?: string;
27
42
  readonly expectedRelativePath?: string;
43
+ readonly provenance?: string;
44
+ readonly publicSafe: true;
45
+ }
46
+ export interface SchedulerRunnerCommand {
47
+ readonly command: string;
48
+ readonly args: readonly string[];
49
+ readonly executablePath: string;
50
+ readonly provenance?: string;
28
51
  readonly publicSafe: true;
29
52
  }
30
53
  export interface SchedulerManifest {
@@ -40,6 +63,32 @@ export interface SchedulerControlCommand {
40
63
  readonly safeUserScope: true;
41
64
  readonly manualOnly?: boolean;
42
65
  }
66
+ export interface SchedulerProjectIdentity {
67
+ readonly projectKey: string;
68
+ readonly projectBasename: string;
69
+ readonly systemdServiceName: string;
70
+ readonly systemdTimerName: string;
71
+ readonly systemdServiceFile: string;
72
+ readonly systemdTimerFile: string;
73
+ readonly launchdLabel: string;
74
+ readonly launchdFile: string;
75
+ readonly windowsTaskName: string;
76
+ readonly windowsXmlFile: string;
77
+ readonly cronFile: string;
78
+ readonly cronMarkerStart: string;
79
+ readonly cronMarkerEnd: string;
80
+ readonly publicSafe: true;
81
+ }
82
+ export type SchedulerLegacyRelation = 'current-project' | 'ambiguous' | 'other-project';
83
+ export interface SchedulerLegacyEntry {
84
+ readonly strategy: SchedulerStrategy;
85
+ readonly kind: SchedulerManifest['kind'];
86
+ readonly name: string;
87
+ readonly relation: SchedulerLegacyRelation;
88
+ readonly reasonCodes: readonly SchedulerReasonCode[];
89
+ readonly remediation: 'stop-safe' | 'manual-review-only' | 'report-only';
90
+ readonly publicSafe: true;
91
+ }
43
92
  export interface SchedulerCommandRunResult {
44
93
  readonly ok: boolean;
45
94
  readonly code?: number | null;
@@ -73,6 +122,7 @@ export interface RunnerSchedulerCommandOptions {
73
122
  readonly commandAvailable?: (command: string) => boolean;
74
123
  readonly commandRunner?: (command: SchedulerControlCommand) => SchedulerCommandRunResult;
75
124
  readonly trustChecker?: (executablePath: string | undefined) => SchedulerBinaryTrustResult;
125
+ readonly binaryResolver?: (options: RunnerBinaryResolveOptions) => RunnerBinaryResolution;
76
126
  readonly now?: () => string;
77
127
  }
78
128
  export interface RunnerSchedulerCommandResult {
@@ -83,6 +133,8 @@ export interface RunnerSchedulerCommandResult {
83
133
  readonly dryRun: boolean;
84
134
  readonly manifestPaths: readonly string[];
85
135
  readonly manifests: readonly SchedulerManifest[];
136
+ readonly identity: SchedulerProjectIdentity;
137
+ readonly legacyEntries: readonly SchedulerLegacyEntry[];
86
138
  readonly controlCommands: readonly SchedulerControlCommand[];
87
139
  readonly uninstallGuidance: readonly string[];
88
140
  readonly capability: SchedulerCapabilityReport;
@@ -90,6 +142,22 @@ export interface RunnerSchedulerCommandResult {
90
142
  readonly applied: boolean;
91
143
  readonly publicSafe: true;
92
144
  }
145
+ export type RunnerSchedulerBootstrapOptions = Omit<RunnerSchedulerCommandOptions, 'command'>;
146
+ export interface RunnerSchedulerBootstrapResult {
147
+ readonly ok: boolean;
148
+ readonly attempted: boolean;
149
+ readonly installed: boolean;
150
+ readonly started: boolean;
151
+ readonly cached: boolean;
152
+ readonly projectKey: string;
153
+ readonly strategy?: SchedulerStrategy;
154
+ readonly reasonCodes: readonly RunnerSchedulerBootstrapReasonCode[];
155
+ readonly publicSummary: string;
156
+ readonly publicSafe: true;
157
+ }
158
+ export declare function createRunnerSchedulerIdentity(canonicalProjectRoot: string): SchedulerProjectIdentity;
159
+ export declare function __resetRunnerSchedulerBootstrapCacheForTests(): void;
160
+ export declare function ensureRunnerSchedulerBootstrap(options?: RunnerSchedulerBootstrapOptions): Promise<RunnerSchedulerBootstrapResult>;
93
161
  export declare function runRunnerSchedulerCommand(options: RunnerSchedulerCommandOptions): Promise<RunnerSchedulerCommandResult>;
94
162
  export declare function detectSchedulerCapability(input?: {
95
163
  readonly platform?: NodeJS.Platform;
@@ -104,7 +172,9 @@ export declare function renderSchedulerManifests(input: {
104
172
  readonly paths: SchedulerPaths;
105
173
  readonly projectRoot: string;
106
174
  readonly executablePath: string;
175
+ readonly runnerCommand?: SchedulerRunnerCommand;
107
176
  readonly intervalSeconds: number;
177
+ readonly identity?: SchedulerProjectIdentity;
108
178
  }): readonly SchedulerManifest[];
109
179
  interface SchedulerPaths {
110
180
  readonly systemdServicePath: string;
@@ -1,6 +1,7 @@
1
- import{spawnSync as W}from"node:child_process";import{existsSync as w,mkdirSync as K,writeFileSync as X}from"node:fs";import{delimiter as V,dirname as Y,isAbsolute as _,join as u,resolve as G}from"node:path";const s=Object.freeze({OK:"continuity-ok",SCHEDULER_INSTALL_UNSAFE:"scheduler-install-unsafe",PRIMARY_USER_SCHEDULER_UNAVAILABLE:"primary-user-scheduler-unavailable",CRON_FALLBACK_SELECTED:"cron-fallback-selected",CRON_FALLBACK_NOT_ALLOWED:"cron-fallback-primary-scheduler-available",SCHEDULER_UNAVAILABLE:"scheduler-unavailable",SCHEDULER_COMMAND_FAILED:"scheduler-command-failed",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted"}),F="neocortex-runner",$=`${F}.service`,E=`${F}.timer`,T="com.ornexus.neocortex.runner",Q=`${T}.plist`,k="NeocortexRunner",q="neocortex-runner-task.xml",z="runner.cron",Z=60;async function ge(e){const t=e.env??process.env,r=e.platform??process.platform,a=e.dryRun===!0,c=y(e.projectRoot??process.cwd()),n=y(e.executablePath??process.argv[1]),m=e.commandAvailable??(p=>H(p,t)),f=Ee(e.intervalSeconds??Z,10,1440*60),h=J({platform:r,env:t,strategy:e.strategy,allowCronFallback:e.allowCronFallback,commandAvailable:m,uid:e.uid}),d=me(e,n),i=[...h.blockers];(!c||!n)&&i.push(s.SCHEDULER_INSTALL_UNSAFE),d.trusted||i.push(s.SCHEDULER_INSTALL_UNSAFE,s.RUNNER_BINARY_UNTRUSTED);const l=h.selectedStrategy;l||i.push(s.SCHEDULER_UNAVAILABLE);const g=(e.command==="install"||e.command==="start"||e.command==="stop")&&i.length>0,U=A([...h.reasonCodes,...i,g?s.SCHEDULER_INSTALL_UNSAFE:s.OK]);if(g||!l||!c||!n)return{ok:!g&&!!l,command:e.command,platform:r,strategy:l,dryRun:a,manifestPaths:[],manifests:[],controlCommands:[],uninstallGuidance:l?v(l,M(l,t)):[],capability:j(h,i),reasonCodes:U,applied:!1,publicSafe:!0};const C=M(l,t),L=e.command==="install"?ee({strategy:l,paths:C,projectRoot:c,executablePath:n,intervalSeconds:f}):[],R=te(e.command,l,C);let b=!1,D=!0;const I=[];if(e.command==="install"&&!a){for(const p of L)K(Y(p.path),{recursive:!0}),X(p.path,p.content,"utf8");b=L.length>0}if(!a&&R.length>0){const p=e.commandRunner??pe;for(const O of R){if(O.manualOnly)continue;const x=p(O);x.ok?b=!0:(D=!1,I.push(x.reasonCode??s.SCHEDULER_COMMAND_FAILED))}}return{ok:D,command:e.command,platform:r,strategy:l,dryRun:a,manifestPaths:L.map(p=>p.path),manifests:L,controlCommands:R,uninstallGuidance:v(l,C),capability:j(h,i),reasonCodes:A([...U,...I,D?s.OK:s.SCHEDULER_COMMAND_FAILED]),applied:b,publicSafe:!0}}function J(e={}){const t=e.env??process.env,r=e.platform??process.platform,a=e.commandAvailable??(l=>H(l,t)),c=fe(r,t,e.uid),n=de(r),m=n?B(n,a):!1,f=r!=="win32"&&a("crontab"),h=e.allowCronFallback!==!1;let d=e.strategy;const i=[];return d||(n&&m?d=n:h&&f&&(d="cron-fallback",i.push(s.PRIMARY_USER_SCHEDULER_UNAVAILABLE,s.CRON_FALLBACK_SELECTED))),d==="cron-fallback"&&m&&(d=void 0,i.push(s.CRON_FALLBACK_NOT_ALLOWED)),d&&!B(d,a)&&(d!=="cron-fallback"||!f)&&(d=void 0),d||i.push(s.SCHEDULER_UNAVAILABLE),c.length>0&&i.push(...c),i.length===0&&i.push(s.OK),{platform:r,primaryStrategy:n,selectedStrategy:d,fallbackStrategy:f?"cron-fallback":void 0,primaryAvailable:m,cronFallbackAvailable:f,safeToInstall:c.length===0,blockers:c,reasonCodes:A(i),publicSafe:!0}}function ee(e){switch(e.strategy){case"systemd-user":return[{kind:"systemd-service",path:e.paths.systemdServicePath,content:oe(e.executablePath,e.projectRoot),publicSafe:!0},{kind:"systemd-timer",path:e.paths.systemdTimerPath,content:ce(e.intervalSeconds),publicSafe:!0}];case"launchd-user":return[{kind:"launchd-plist",path:e.paths.launchdPlistPath,content:ie(e.executablePath,e.projectRoot,e.intervalSeconds),publicSafe:!0}];case"windows-task-scheduler":return[{kind:"windows-task-xml",path:e.paths.windowsTaskXmlPath,content:le(e.executablePath,e.projectRoot,e.intervalSeconds),publicSafe:!0}];case"cron-fallback":return[{kind:"cron-snippet",path:e.paths.cronSnippetPath,content:ue(e.executablePath,e.projectRoot),publicSafe:!0}]}}function M(e,t){const r=he(t),a=y(t.XDG_CONFIG_HOME)??u(r,".config"),c=u(a,"systemd","user"),n=u(r,"Library","LaunchAgents"),m=y(t.APPDATA)??u(y(t.USERPROFILE)??r,"AppData","Roaming"),f=u(m,"Neocortex","Runner"),h=u(a,"neocortex");return{systemdServicePath:u(c,$),systemdTimerPath:u(c,E),launchdPlistPath:u(n,Q),windowsTaskXmlPath:u(f,q),cronSnippetPath:u(h,z)}}function te(e,t,r){return e==="doctor"?[]:e==="install"?re(t,r):e==="start"?ne(t,r):e==="stop"?se(t,r):ae(t,r)}function re(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","daemon-reload"]),o("systemctl",["--user","enable","--now",E])];case"launchd-user":return[o("launchctl",["load","-w",t.launchdPlistPath])];case"windows-task-scheduler":return[o("schtasks",["/Create","/TN",k,"/XML",t.windowsTaskXmlPath,"/F"])];case"cron-fallback":return[o("crontab",["-l","# append snippet from",t.cronSnippetPath],!0)]}}function ne(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","start",E])];case"launchd-user":return[o("launchctl",["load","-w",t.launchdPlistPath])];case"windows-task-scheduler":return[o("schtasks",["/Run","/TN",k])];case"cron-fallback":return[o("crontab",["-l","# ensure snippet from",t.cronSnippetPath,"is installed"],!0)]}}function se(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","stop",E])];case"launchd-user":return[o("launchctl",["unload","-w",t.launchdPlistPath])];case"windows-task-scheduler":return[o("schtasks",["/End","/TN",k])];case"cron-fallback":return[o("crontab",["-l","# remove neocortex-runner snippet"],!0)]}}function ae(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","status",E,"--no-pager"])];case"launchd-user":return[o("launchctl",["list",T])];case"windows-task-scheduler":return[o("schtasks",["/Query","/TN",k,"/FO","LIST"])];case"cron-fallback":return[o("crontab",["-l","# look for neocortex-runner snippet from",t.cronSnippetPath],!0)]}}function v(e,t){switch(e){case"systemd-user":return[`systemctl --user disable --now ${E}`,`rm ${t.systemdServicePath}`,`rm ${t.systemdTimerPath}`];case"launchd-user":return[`launchctl unload -w ${t.launchdPlistPath}`,`rm ${t.launchdPlistPath}`];case"windows-task-scheduler":return[`schtasks /Delete /TN ${k} /F`,`Remove-Item ${t.windowsTaskXmlPath}`];case"cron-fallback":return["Remove the # neocortex-runner snippet from the user crontab.",`rm ${t.cronSnippetPath}`]}}function oe(e,t){return["[Unit]","Description=Neocortex Enterprise Continuity Runner (user scope)","After=network-online.target","","[Service]","Type=oneshot",`WorkingDirectory=${N(t)}`,`ExecStart=${N(e)} tick --project-root ${N(t)}`,"","[Install]","WantedBy=default.target",""].join(`
2
- `)}function ce(e){return["[Unit]","Description=Run Neocortex Enterprise Continuity Runner periodically (user scope)","","[Timer]","OnBootSec=60s",`OnUnitActiveSec=${e}s`,`Unit=${$}`,"","[Install]","WantedBy=timers.target",""].join(`
3
- `)}function ie(e,t,r){return['<?xml version="1.0" encoding="UTF-8"?>','<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">','<plist version="1.0">',"<dict>"," <key>Label</key>",` <string>${S(T)}</string>`," <key>ProgramArguments</key>"," <array>",` <string>${S(e)}</string>`," <string>tick</string>"," <string>--project-root</string>",` <string>${S(t)}</string>`," </array>"," <key>WorkingDirectory</key>",` <string>${S(t)}</string>`," <key>StartInterval</key>",` <integer>${r}</integer>`," <key>RunAtLoad</key>"," <true/>","</dict>","</plist>",""].join(`
4
- `)}function le(e,t,r){return['<?xml version="1.0" encoding="UTF-16"?>','<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">'," <RegistrationInfo>"," <Description>Neocortex Enterprise Continuity Runner (user scope)</Description>"," </RegistrationInfo>"," <Triggers>"," <TimeTrigger>"," <Repetition>",` <Interval>PT${r}S</Interval>`," <StopAtDurationEnd>false</StopAtDurationEnd>"," </Repetition>"," <Enabled>true</Enabled>"," </TimeTrigger>"," </Triggers>"," <Principals>",' <Principal id="Author">'," <LogonType>InteractiveToken</LogonType>"," <RunLevel>LeastPrivilege</RunLevel>"," </Principal>"," </Principals>"," <Settings>"," <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>"," <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>"," <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>"," <Enabled>true</Enabled>"," </Settings>",' <Actions Context="Author">'," <Exec>",` <Command>${S(e)}</Command>`,` <Arguments>tick --project-root ${S(Se(t))}</Arguments>`,` <WorkingDirectory>${S(t)}</WorkingDirectory>`," </Exec>"," </Actions>","</Task>",""].join(`
5
- `)}function ue(e,t){return["# neocortex-runner user-scope cron fallback","# Reason: primary-user-scheduler-unavailable",`* * * * * ${P(e)} tick --project-root ${P(t)} # neocortex-runner`,""].join(`
6
- `)}function de(e){if(e==="linux")return"systemd-user";if(e==="darwin")return"launchd-user";if(e==="win32")return"windows-task-scheduler"}function B(e,t){switch(e){case"systemd-user":return t("systemctl");case"launchd-user":return t("launchctl");case"windows-task-scheduler":return t("schtasks")||t("schtasks.exe");case"cron-fallback":return t("crontab")}}function fe(e,t,r){const a=[],c=r??(typeof process.getuid=="function"?process.getuid():null);e!=="win32"&&c===0&&a.push(s.SCHEDULER_INSTALL_UNSAFE),e!=="win32"&&(t.SUDO_USER||t.SUDO_UID||t.SUDO_COMMAND)&&a.push(s.SCHEDULER_INSTALL_UNSAFE);const n=t.HOME??t.USERPROFILE;return(!n||!_(n)||!y(n))&&a.push(s.SCHEDULER_INSTALL_UNSAFE),A(a)}function me(e,t){return e.trustCheck===!1?{trusted:!0,executablePath:t??void 0,publicSafe:!0}:e.trustChecker?e.trustChecker(t??void 0):{trusted:!1,reasonCode:s.RUNNER_BINARY_UNTRUSTED,executablePath:t??void 0,publicSafe:!0}}function he(e){return e.HOME??e.USERPROFILE??process.env.HOME??process.cwd()}function y(e){if(!e||/[\r\n\0]/.test(e))return null;const t=_(e)?e:G(e);return _(t)?t:null}function o(e,t,r=!1){return{command:e,args:t,preview:[e,...t.map(P)].join(" "),safeUserScope:!0,...r?{manualOnly:!0}:{}}}function pe(e){const t=W(e.command,[...e.args],{stdio:"ignore",shell:!1});return{ok:t.status===0,code:t.status,signal:t.signal,reasonCode:t.status===0?s.OK:s.SCHEDULER_COMMAND_FAILED}}function H(e,t){const r=t.PATH??process.env.PATH??"",a=(t.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean),c=r.split(V).filter(Boolean);for(const n of c){const m=u(n,e);if(w(m))return!0;for(const f of a)if(w(u(n,`${e}${f.toLowerCase()}`))||w(u(n,`${e}${f.toUpperCase()}`)))return!0}return!1}function j(e,t){const r=A([...e.blockers,...t]);return{...e,safeToInstall:r.length===0,blockers:r,reasonCodes:A([...e.reasonCodes,...r])}}function N(e){return/[\s"'\\]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e}function P(e){return/^[A-Za-z0-9_./:=@%+-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function Se(e){return/[\s"]/.test(e)?`"${e.replace(/"/g,'\\"')}"`:e}function S(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Ee(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,Math.floor(e))):t}function A(e){return Array.from(new Set(e))}export{s as SCHEDULER_REASON_CODES,J as detectSchedulerCapability,ee as renderSchedulerManifests,ge as runRunnerSchedulerCommand};
1
+ import{spawnSync as ce}from"node:child_process";import{createHash as le}from"node:crypto";import{existsSync as j,mkdirSync as ue,readFileSync as ie,writeFileSync as de}from"node:fs";import{delimiter as me,dirname as pe,isAbsolute as F,join as c,resolve as Q}from"node:path";import{checkRunnerBinaryTrust as fe,resolveTrustedRunnerBinary as J}from"./binary.js";const i=Object.freeze({OK:"continuity-ok",SCHEDULER_INSTALL_UNSAFE:"scheduler-install-unsafe",PRIMARY_USER_SCHEDULER_UNAVAILABLE:"primary-user-scheduler-unavailable",CRON_FALLBACK_SELECTED:"cron-fallback-selected",CRON_FALLBACK_NOT_ALLOWED:"cron-fallback-primary-scheduler-available",SCHEDULER_UNAVAILABLE:"scheduler-unavailable",SCHEDULER_COMMAND_FAILED:"scheduler-command-failed",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted",LEGACY_GLOBAL_SCHEDULER_DETECTED:"legacy-global-scheduler-detected",LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS:"legacy-global-scheduler-ambiguous",LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT:"legacy-global-scheduler-other-project"}),A=Object.freeze({OK:"runner-bootstrap-ok",ALREADY_ACTIVE:"runner-bootstrap-already-active",BINARY_UNAVAILABLE:"runner-bootstrap-binary-unavailable",INSTALL_FAILED:"runner-bootstrap-install-failed",START_FAILED:"runner-bootstrap-start-failed",UNEXPECTED_ERROR:"runner-bootstrap-unexpected-error"}),$="neocortex-runner",he=`${$}.service`,N=`${$}.timer`,B="com.ornexus.neocortex.runner",ye=`${B}.plist`,M="NeocortexRunner",Ee="neocortex-runner-task.xml",ge="runner.cron",Se=12,Ce=24,Le=60,H=new Map;function K(e){const r=g(e)??Q(e||"."),t=We(r),n=le("sha256").update(t).digest("hex").slice(0,Se),s=Qe(ze(t)),o=`${s}-${n}`,a=`${$}-${o}`,d=`com.ornexus.neocortex.runner.${o}`;return{projectKey:o,projectBasename:s,systemdServiceName:`${a}.service`,systemdTimerName:`${a}.timer`,systemdServiceFile:`${a}.service`,systemdTimerFile:`${a}.timer`,launchdLabel:d,launchdFile:`${d}.plist`,windowsTaskName:`NeocortexRunner-${o}`,windowsXmlFile:`${a}-task.xml`,cronFile:`runner-${o}.cron`,cronMarkerStart:`# BEGIN neocortex-runner:${o}`,cronMarkerEnd:`# END neocortex-runner:${o}`,publicSafe:!0}}function or(){H.clear()}async function ar(e={}){const r=e.platform??process.platform,t=g(e.projectRoot??process.cwd())??process.cwd(),n=K(t),s=`${r}:${n.projectKey}`,o=H.get(s);if(o?.ok)return{...o,attempted:!1,installed:!1,started:!1,cached:!0,reasonCodes:S([...o.reasonCodes,A.ALREADY_ACTIVE]),publicSummary:"runner scheduler bootstrap already active for project key.",publicSafe:!0};try{const a=e.binaryResolver??J,d=g(e.executablePath??process.argv[1])??process.argv[1],y=a({from:d,platform:r});if(!y.ok)return w({projectKey:n.projectKey,reasonCodes:[A.BINARY_UNAVAILABLE,...y.reasonCodes],publicSummary:"runner scheduler bootstrap could not resolve a trusted runner binary."});const u=Re(e.env??process.env),E={...e,projectRoot:t,executablePath:y.executablePath,platform:r,env:u,binaryResolver:()=>y},p=await q({...E,command:"install"});if(!p.ok)return w({projectKey:n.projectKey,strategy:p.strategy,reasonCodes:[A.INSTALL_FAILED,...p.reasonCodes],publicSummary:"runner scheduler bootstrap install failed.",attempted:!0});const f=await q({...E,command:"start"});if(!f.ok)return w({projectKey:n.projectKey,strategy:f.strategy??p.strategy,reasonCodes:[A.START_FAILED,...f.reasonCodes],publicSummary:"runner scheduler bootstrap start failed.",attempted:!0,installed:p.applied||p.ok});const L={ok:!0,attempted:!0,installed:p.applied||p.ok,started:f.applied||f.ok,cached:!1,projectKey:n.projectKey,strategy:f.strategy??p.strategy,reasonCodes:S([A.OK,...p.reasonCodes,...f.reasonCodes]),publicSummary:"runner scheduler bootstrap completed for project key.",publicSafe:!0};return H.set(s,L),L}catch{return w({projectKey:n.projectKey,reasonCodes:[A.UNEXPECTED_ERROR],publicSummary:"runner scheduler bootstrap stopped unexpectedly."})}}function w(e){return{ok:!1,attempted:e.attempted??!1,installed:e.installed??!1,started:!1,cached:!1,projectKey:e.projectKey,strategy:e.strategy,reasonCodes:S(e.reasonCodes),publicSummary:e.publicSummary,publicSafe:!0}}function Re(e){return{...e,NEOCORTEX_RUNNER_BOOTSTRAP_IN_PROGRESS:"1",NEOCORTEX_BOOTSTRAP_IN_PROGRESS:"1"}}async function q(e){const r=e.env??process.env,t=e.platform??process.platform,n=e.dryRun===!0,s=g(e.projectRoot??process.cwd()),o=g(e.executablePath??process.argv[1]),a=Xe(e,o,t),d=a.runnerCommand,y=d?.executablePath??o,u=K(s??process.cwd()),E=e.commandAvailable??(h=>ne(h,r)),p=qe(e.intervalSeconds??Le,10,1440*60),f=ke({platform:t,env:r,strategy:e.strategy,allowCronFallback:e.allowCronFallback,commandAvailable:E,uid:e.uid}),L=Ve(e,y,a.resolution),R=[...f.blockers];if((!s||!d)&&R.push(i.SCHEDULER_INSTALL_UNSAFE),!L.trusted){const h=L.reasonCodes&&L.reasonCodes.length>0?L.reasonCodes:[L.reasonCode??i.RUNNER_BINARY_UNTRUSTED];R.push(i.SCHEDULER_INSTALL_UNSAFE,i.RUNNER_BINARY_UNTRUSTED,...h)}const m=f.selectedStrategy;m||R.push(i.SCHEDULER_UNAVAILABLE);const k=m?be(m,r,u):void 0,b=m&&s&&Be(e.command)?Me({strategy:m,env:r,projectRoot:s}):[],ae=b.flatMap(h=>h.reasonCodes),v=(e.command==="install"||e.command==="start"||e.command==="stop")&&R.length>0,X=S([...f.reasonCodes,...R,...ae,v?i.SCHEDULER_INSTALL_UNSAFE:i.OK]);if(v||!m||!k||!s||!d)return{ok:!v&&!!m,command:e.command,platform:t,strategy:m,dryRun:n,manifestPaths:[],manifests:[],identity:u,legacyEntries:b,controlCommands:[],uninstallGuidance:m&&k?ee(m,k,u):[],capability:se(f,R),reasonCodes:X,applied:!1,publicSafe:!0};const T=e.command==="install"?Ae({strategy:m,paths:k,projectRoot:s,executablePath:d.command,runnerCommand:d,intervalSeconds:p,identity:u}):[],U=_e(e.command,m,k,u,b,r);let I=!1,x=!0;const V=[];if(e.command==="install"&&!n){for(const h of T)ue(pe(h.path),{recursive:!0}),de(h.path,h.content,"utf8");I=T.length>0}if(!n&&U.length>0){const h=e.commandRunner??Je;for(const W of U){if(W.manualOnly)continue;const z=h(W);z.ok?I=!0:(x=!1,V.push(z.reasonCode??i.SCHEDULER_COMMAND_FAILED))}}return{ok:x,command:e.command,platform:t,strategy:m,dryRun:n,manifestPaths:T.map(h=>h.path),manifests:T,identity:u,legacyEntries:b,controlCommands:U,uninstallGuidance:[...ee(m,k,u),...Ue(m,b)],capability:se(f,R),reasonCodes:S([...X,...V,x?i.OK:i.SCHEDULER_COMMAND_FAILED]),applied:I,publicSafe:!0}}function ke(e={}){const r=e.env??process.env,t=e.platform??process.platform,n=e.commandAvailable??(p=>ne(p,r)),s=Ye(t,r,e.uid),o=Ge(t),a=o?re(o,n):!1,d=t!=="win32"&&n("crontab"),y=e.allowCronFallback!==!1;let u=e.strategy;const E=[];return u||(o&&a?u=o:y&&d&&(u="cron-fallback",E.push(i.PRIMARY_USER_SCHEDULER_UNAVAILABLE,i.CRON_FALLBACK_SELECTED))),u==="cron-fallback"&&a&&(u=void 0,E.push(i.CRON_FALLBACK_NOT_ALLOWED)),u&&!re(u,n)&&(u!=="cron-fallback"||!d)&&(u=void 0),u||E.push(i.SCHEDULER_UNAVAILABLE),s.length>0&&E.push(...s),E.length===0&&E.push(i.OK),{platform:t,primaryStrategy:o,selectedStrategy:u,fallbackStrategy:d?"cron-fallback":void 0,primaryAvailable:a,cronFallbackAvailable:d,safeToInstall:s.length===0,blockers:s,reasonCodes:S(E),publicSafe:!0}}function Ae(e){const r=e.identity??K(e.projectRoot),t=e.runnerCommand??{command:e.executablePath,args:[],executablePath:e.executablePath,publicSafe:!0};switch(e.strategy){case"systemd-user":return[{kind:"systemd-service",path:e.paths.systemdServicePath,content:Ie(t,e.projectRoot,r),publicSafe:!0},{kind:"systemd-timer",path:e.paths.systemdTimerPath,content:xe(e.intervalSeconds,r),publicSafe:!0}];case"launchd-user":return[{kind:"launchd-plist",path:e.paths.launchdPlistPath,content:je(t,e.projectRoot,e.intervalSeconds,r),publicSafe:!0}];case"windows-task-scheduler":return[{kind:"windows-task-xml",path:e.paths.windowsTaskXmlPath,content:Fe(t,e.projectRoot,e.intervalSeconds,r),publicSafe:!0}];case"cron-fallback":return[{kind:"cron-snippet",path:e.paths.cronSnippetPath,content:$e(t,e.projectRoot,r),publicSafe:!0}]}}function be(e,r,t){const n=te(r),s=g(r.XDG_CONFIG_HOME)??c(n,".config"),o=c(s,"systemd","user"),a=c(n,"Library","LaunchAgents"),d=g(r.APPDATA)??c(g(r.USERPROFILE)??n,"AppData","Roaming"),y=c(d,"Neocortex","Runner"),u=c(s,"neocortex");return{systemdServicePath:c(o,t.systemdServiceFile),systemdTimerPath:c(o,t.systemdTimerFile),launchdPlistPath:c(a,t.launchdFile),windowsTaskXmlPath:c(y,t.windowsXmlFile),cronSnippetPath:c(u,t.cronFile)}}function Z(e,r){const t=te(r),n=g(r.XDG_CONFIG_HOME)??c(t,".config"),s=c(n,"systemd","user"),o=c(t,"Library","LaunchAgents"),a=g(r.APPDATA)??c(g(r.USERPROFILE)??t,"AppData","Roaming"),d=c(a,"Neocortex","Runner"),y=c(n,"neocortex");return{systemdServicePath:c(s,he),systemdTimerPath:c(s,N),launchdPlistPath:c(o,ye),windowsTaskXmlPath:c(d,Ee),cronSnippetPath:c(y,ge)}}function _e(e,r,t,n,s,o){return e==="doctor"?[]:[...e==="install"?Te(r,t,n):e==="start"?Ne(r,t,n):e==="stop"?we(r,t,n):De(r,t,n),...Pe(e,r,s,o)]}function Te(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","daemon-reload"]),l("systemctl",["--user","enable","--now",t.systemdTimerName])];case"launchd-user":return[l("launchctl",["load","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/Create","/TN",t.windowsTaskName,"/XML",r.windowsTaskXmlPath,"/F"])];case"cron-fallback":return[l("crontab",["-l","# append snippet from",r.cronSnippetPath],!0)]}}function Ne(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","start",t.systemdTimerName])];case"launchd-user":return[l("launchctl",["load","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/Run","/TN",t.windowsTaskName])];case"cron-fallback":return[l("crontab",["-l","# ensure snippet from",r.cronSnippetPath,"is installed"],!0)]}}function we(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","stop",t.systemdTimerName])];case"launchd-user":return[l("launchctl",["unload","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/End","/TN",t.windowsTaskName])];case"cron-fallback":return[l("crontab",["-l","# remove scoped neocortex-runner snippet"],!0)]}}function De(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","status",t.systemdTimerName,"--no-pager"])];case"launchd-user":return[l("launchctl",["list",t.launchdLabel])];case"windows-task-scheduler":return[l("schtasks",["/Query","/TN",t.windowsTaskName,"/FO","LIST"])];case"cron-fallback":return[l("crontab",["-l","# look for neocortex-runner snippet from",r.cronSnippetPath],!0)]}}function ee(e,r,t){switch(e){case"systemd-user":return[`systemctl --user disable --now ${t.systemdTimerName}`,`rm ${r.systemdServicePath}`,`rm ${r.systemdTimerPath}`];case"launchd-user":return[`launchctl unload -w ${r.launchdPlistPath}`,`rm ${r.launchdPlistPath}`];case"windows-task-scheduler":return[`schtasks /Delete /TN ${t.windowsTaskName} /F`,`Remove-Item ${r.windowsTaskXmlPath}`];case"cron-fallback":return[`Remove the ${t.cronMarkerStart} block from the user crontab.`,`rm ${r.cronSnippetPath}`]}}function Pe(e,r,t,n){if(!t.some(a=>a.relation==="current-project")||e!=="status"&&e!=="stop")return[];const o=Z(r,n);return e==="status"?Oe(r,o):ve(r,o)}function Oe(e,r){switch(e){case"systemd-user":return[l("systemctl",["--user","status",N,"--no-pager"])];case"launchd-user":return[l("launchctl",["list",B])];case"windows-task-scheduler":return[l("schtasks",["/Query","/TN",M,"/FO","LIST"])];case"cron-fallback":return[l("crontab",["-l","# look for legacy neocortex-runner snippet from",r.cronSnippetPath],!0)]}}function ve(e,r){switch(e){case"systemd-user":return[l("systemctl",["--user","stop",N])];case"launchd-user":return[l("launchctl",["unload","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/End","/TN",M])];case"cron-fallback":return[l("crontab",["-l","# remove legacy neocortex-runner snippet"],!0)]}}function Ue(e,r){if(r.length===0)return[];const t=r.filter(a=>a.relation==="current-project"),n=r.filter(a=>a.relation==="ambiguous"),s=r.filter(a=>a.relation==="other-project"),o=[];return t.length>0&&o.push(`Legacy global ${e} scheduler matches this project; stop it before relying on project-scoped runner scheduling.`),n.length>0&&o.push(`Legacy global ${e} scheduler ownership is ambiguous; inspect it manually before removal.`),s.length>0&&o.push(`Legacy global ${e} scheduler appears to belong to another project; leave it unchanged.`),o}function Ie(e,r,t){const n=[e.command,...e.args,"tick","--project-root",r].map(G).join(" ");return["[Unit]",`Description=Neocortex Enterprise Continuity Runner (${t.projectKey}, user scope)`,`# Managed by Neocortex runner for project ${t.projectKey}`,"After=network-online.target","","[Service]","Type=oneshot",`WorkingDirectory=${G(r)}`,`ExecStart=${n}`,"","[Install]","WantedBy=default.target",""].join(`
2
+ `)}function xe(e,r){return["[Unit]",`Description=Run Neocortex Enterprise Continuity Runner periodically (${r.projectKey}, user scope)`,`# Managed by Neocortex runner for project ${r.projectKey}`,"","[Timer]","OnBootSec=60s",`OnUnitActiveSec=${e}s`,`Unit=${r.systemdServiceName}`,"","[Install]","WantedBy=timers.target",""].join(`
3
+ `)}function je(e,r,t,n){const s=[e.command,...e.args,"tick","--project-root",r];return['<?xml version="1.0" encoding="UTF-8"?>','<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">','<plist version="1.0">',"<dict>",` <!-- Managed by Neocortex runner for project ${C(n.projectKey)} -->`," <key>Label</key>",` <string>${C(n.launchdLabel)}</string>`," <key>ProgramArguments</key>"," <array>",...s.map(o=>` <string>${C(o)}</string>`)," </array>"," <key>WorkingDirectory</key>",` <string>${C(r)}</string>`," <key>StartInterval</key>",` <integer>${t}</integer>`," <key>RunAtLoad</key>"," <true/>","</dict>","</plist>",""].join(`
4
+ `)}function Fe(e,r,t,n){const s=[...e.args,"tick","--project-root",r].map(oe).join(" ");return['<?xml version="1.0" encoding="UTF-16"?>','<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">'," <RegistrationInfo>",` <Description>Neocortex Enterprise Continuity Runner (${C(n.projectKey)}, user scope)</Description>`," </RegistrationInfo>"," <Triggers>"," <TimeTrigger>"," <Repetition>",` <Interval>PT${t}S</Interval>`," <StopAtDurationEnd>false</StopAtDurationEnd>"," </Repetition>"," <Enabled>true</Enabled>"," </TimeTrigger>"," </Triggers>"," <Principals>",' <Principal id="Author">'," <LogonType>InteractiveToken</LogonType>"," <RunLevel>LeastPrivilege</RunLevel>"," </Principal>"," </Principals>"," <Settings>"," <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>"," <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>"," <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>"," <Enabled>true</Enabled>"," </Settings>",' <Actions Context="Author">'," <Exec>",` <Command>${C(e.command)}</Command>`,` <Arguments>${C(s)}</Arguments>`,` <WorkingDirectory>${C(r)}</WorkingDirectory>`," </Exec>"," </Actions>","</Task>",""].join(`
5
+ `)}function $e(e,r,t){const n=[e.command,...e.args,"tick","--project-root",r].map(Y).join(" ");return[t.cronMarkerStart,`# neocortex-runner user-scope cron fallback for project ${t.projectKey}`,"# Reason: primary-user-scheduler-unavailable",`* * * * * ${n} # neocortex-runner:${t.projectKey}`,t.cronMarkerEnd,""].join(`
6
+ `)}function Be(e){return e==="status"||e==="stop"||e==="doctor"}function Me(e){const r=Z(e.strategy,e.env);switch(e.strategy){case"systemd-user":{const t=_(r.systemdServicePath),n=_(r.systemdTimerPath),s=t?O(t):!1,o=n?Ke(n):!1;if(!s&&!o)return[];const a=P([t,n].filter(Boolean).join(`
7
+ `),e.projectRoot,s);return[D(e.strategy,"systemd-timer",N,a)]}case"launchd-user":{const t=_(r.launchdPlistPath);return!t||!O(t)?[]:[D(e.strategy,"launchd-plist",B,P(t,e.projectRoot,!0))]}case"windows-task-scheduler":{const t=_(r.windowsTaskXmlPath);return!t||!O(t)?[]:[D(e.strategy,"windows-task-xml",M,P(t,e.projectRoot,!0))]}case"cron-fallback":{const t=_(r.cronSnippetPath);return!t||!O(t)?[]:[D(e.strategy,"cron-snippet","# neocortex-runner",P(t,e.projectRoot,!0))]}}}function D(e,r,t,n){const s=n==="current-project"?i.LEGACY_GLOBAL_SCHEDULER_DETECTED:n==="ambiguous"?i.LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS:i.LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT;return{strategy:e,kind:r,name:t,relation:n,reasonCodes:[s],remediation:n==="current-project"?"stop-safe":n==="ambiguous"?"manual-review-only":"report-only",publicSafe:!0}}function P(e,r,t){return He(e,r)?"current-project":t&&/--project-root|WorkingDirectory=|<key>WorkingDirectory<\/key>|<Arguments>[^<]*--project-root/i.test(e)?"other-project":"ambiguous"}function He(e,r){return S([r,G(r),Y(r),oe(r),C(r)].filter(Boolean)).some(n=>e.includes(n))}function O(e){return/neocortex-runner|com\.ornexus\.neocortex\.runner|NeocortexRunner|Neocortex Enterprise Continuity Runner/i.test(e)&&/tick|--project-root|StartInterval|OnUnitActiveSec|InteractiveToken|primary-user-scheduler-unavailable/i.test(e)}function Ke(e){return/neocortex-runner\.service|Neocortex Enterprise Continuity Runner|OnUnitActiveSec/i.test(e)}function _(e){try{return ie(e,"utf8")}catch{return null}}function Ge(e){if(e==="linux")return"systemd-user";if(e==="darwin")return"launchd-user";if(e==="win32")return"windows-task-scheduler"}function re(e,r){switch(e){case"systemd-user":return r("systemctl");case"launchd-user":return r("launchctl");case"windows-task-scheduler":return r("schtasks")||r("schtasks.exe");case"cron-fallback":return r("crontab")}}function Ye(e,r,t){const n=[],s=t??(typeof process.getuid=="function"?process.getuid():null);e!=="win32"&&s===0&&n.push(i.SCHEDULER_INSTALL_UNSAFE),e!=="win32"&&(r.SUDO_USER||r.SUDO_UID||r.SUDO_COMMAND)&&n.push(i.SCHEDULER_INSTALL_UNSAFE);const o=r.HOME??r.USERPROFILE;return(!o||!F(o)||!g(o))&&n.push(i.SCHEDULER_INSTALL_UNSAFE),S(n)}function Xe(e,r,t){if(e.trustCheck===!1||e.trustChecker)return{runnerCommand:r?{command:r,args:[],executablePath:r,publicSafe:!0}:void 0};const s=(e.binaryResolver??J)({from:r??process.argv[1],platform:t});return s.ok?{runnerCommand:{command:s.command,args:s.args,executablePath:s.executablePath,provenance:s.provenance,publicSafe:!0},resolution:s}:{runnerCommand:r?{command:r,args:[],executablePath:r,provenance:s.provenance,publicSafe:!0}:void 0,resolution:s}}function Ve(e,r,t){return e.trustCheck===!1?{trusted:!0,executablePath:r??void 0,publicSafe:!0}:e.trustChecker?e.trustChecker(r??void 0):t?t.ok?{trusted:!0,packageName:t.packageName,packageVersion:t.packageVersion,packageRoot:t.packageRoot,executablePath:t.executablePath,expectedRelativePath:t.expectedRelativePath,provenance:t.provenance,reasonCodes:t.reasonCodes,publicSafe:!0}:{trusted:!1,reasonCode:t.reasonCode,reasonCodes:t.reasonCodes,packageName:t.packageName,packageVersion:t.packageVersion,packageRoot:t.packageRoot,executablePath:t.executablePath??r??void 0,expectedRelativePath:t.expectedRelativePath,provenance:t.provenance,publicSafe:!0}:fe(r??void 0)}function te(e){return e.HOME??e.USERPROFILE??process.env.HOME??process.cwd()}function We(e){let r=e.replace(/\\/g,"/").replace(/\/+$/g,"");return r||(r="/"),r=r.replace(/^([A-Z]):\//,(t,n)=>`${n.toLowerCase()}:/`),r}function ze(e){const r=e.split("/").filter(Boolean);return r[r.length-1]??"project"}function Qe(e){return e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Ce).replace(/-+$/g,"")||"project"}function g(e){if(!e||/[\r\n\0]/.test(e))return null;const r=F(e)?e:Q(e);return F(r)?r:null}function l(e,r,t=!1){return{command:e,args:r,preview:[e,...r.map(Y)].join(" "),safeUserScope:!0,...t?{manualOnly:!0}:{}}}function Je(e){const r=ce(e.command,[...e.args],{stdio:"ignore",shell:!1});return{ok:r.status===0,code:r.status,signal:r.signal,reasonCode:r.status===0?i.OK:i.SCHEDULER_COMMAND_FAILED}}function ne(e,r){const t=r.PATH??process.env.PATH??"",n=(r.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean),s=t.split(me).filter(Boolean);for(const o of s){const a=c(o,e);if(j(a))return!0;for(const d of n)if(j(c(o,`${e}${d.toLowerCase()}`))||j(c(o,`${e}${d.toUpperCase()}`)))return!0}return!1}function se(e,r){const t=S([...e.blockers,...r]);return{...e,safeToInstall:t.length===0,blockers:t,reasonCodes:S([...e.reasonCodes,...t])}}function G(e){return/[\s"'\\]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e}function Y(e){return/^[A-Za-z0-9_./:=@%+-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function oe(e){return/[\s"]/.test(e)?`"${e.replace(/"/g,'\\"')}"`:e}function C(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function qe(e,r,t){return Number.isFinite(e)?Math.max(r,Math.min(t,Math.floor(e))):r}function S(e){return Array.from(new Set(e))}export{A as RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES,i as SCHEDULER_REASON_CODES,or as __resetRunnerSchedulerBootstrapCacheForTests,K as createRunnerSchedulerIdentity,ke as detectSchedulerCapability,ar as ensureRunnerSchedulerBootstrap,Ae as renderSchedulerManifests,q as runRunnerSchedulerCommand};
@@ -1,4 +1,4 @@
1
- # 🧠 Neocortex v4.59.1 | OrNexus Team
1
+ # 🧠 Neocortex v4.59.3 | OrNexus Team
2
2
 
3
3
  This project uses Neocortex, a Development Orchestrator.
4
4
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.59.1 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.3 | OrNexus Team"
4
4
  ---
5
5
 
6
6
  <!--
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex Root Agent'
5
5
  title: 'Development Orchestrator (Root)'
6
6
  icon: '>'
7
- version: '4.59.1'
7
+ version: '4.59.3'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex-root
3
- description: "🧠 Neocortex Root Agent v4.59.1 | OrNexus Team"
3
+ description: "🧠 Neocortex Root Agent v4.59.3 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -103,7 +103,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
103
103
  ┌────────────────────────────────────────────────────────────┐
104
104
  │ │
105
105
  │ ####### N E O C O R T E X │
106
- │ ### ######## v4.59.1
106
+ │ ### ######## v4.59.3
107
107
  │ ######### ##### │
108
108
  │ ## ############## Development Orchestrator │
109
109
  │ ## ### ###### ## OrNexus Team │
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex'
5
5
  title: 'Development Orchestrator'
6
6
  icon: '>'
7
- version: '4.59.1'
7
+ version: '4.59.3'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.59.1 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.3 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -97,7 +97,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
97
97
  ┌────────────────────────────────────────────────────────────┐
98
98
  │ │
99
99
  │ ####### N E O C O R T E X │
100
- │ ### ######## v4.59.1
100
+ │ ### ######## v4.59.3
101
101
  │ ######### ##### │
102
102
  │ ## ############## Development Orchestrator │
103
103
  │ ## ### ###### ## OrNexus Team │
@@ -23,7 +23,7 @@ Codex built-in commands or actions.
23
23
 
24
24
  <!-- END: Plugin Conflict Prevention -->
25
25
 
26
- # Neocortex v4.59.1 | OrNexus Team
26
+ # Neocortex v4.59.3 | OrNexus Team
27
27
 
28
28
  You are a Development Orchestrator. All orchestration logic is delivered by the remote Neocortex server.
29
29
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.59.1 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.3 | OrNexus Team"
4
4
  model: fast
5
5
  readonly: false
6
6
  is_background: false
@@ -43,7 +43,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
43
43
  ┌────────────────────────────────────────────────────────────┐
44
44
  │ │
45
45
  │ ####### N E O C O R T E X │
46
- │ ### ######## v4.59.1
46
+ │ ### ######## v4.59.3
47
47
  │ ######### ##### │
48
48
  │ ## ############## Development Orchestrator │
49
49
  │ ## ### ###### ## OrNexus Team │
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.59.1 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.3 | OrNexus Team"
4
4
  kind: local
5
5
  tools:
6
6
  # File operations (Gemini CLI built-ins)
@@ -60,7 +60,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
60
60
  ┌────────────────────────────────────────────────────────────┐
61
61
  │ │
62
62
  │ ####### N E O C O R T E X │
63
- │ ### ######## v4.59.1
63
+ │ ### ######## v4.59.3
64
64
  │ ######### ##### │
65
65
  │ ## ############## Development Orchestrator │
66
66
  │ ## ### ###### ## OrNexus Team │
@@ -47,7 +47,7 @@ explicit server opt-in rather than a local assumption.
47
47
  ┌────────────────────────────────────────────────────────────┐
48
48
  │ │
49
49
  │ ####### N E O C O R T E X │
50
- │ ### ######## v4.59.1
50
+ │ ### ######## v4.59.3
51
51
  │ ######### ##### │
52
52
  │ ## ############## Development Orchestrator │
53
53
  │ ## ### ###### ## OrNexus Team │
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "neocortex"
3
- description: "Neocortex v4.59.1 | OrNexus Team"
3
+ description: "Neocortex v4.59.3 | OrNexus Team"
4
4
  tools:
5
5
  # Read / Edit (built-in tool sets)
6
6
  - read
@@ -61,7 +61,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
61
61
  ┌────────────────────────────────────────────────────────────┐
62
62
  │ │
63
63
  │ ####### N E O C O R T E X │
64
- │ ### ######## v4.59.1
64
+ │ ### ######## v4.59.3
65
65
  │ ######### ##### │
66
66
  │ ## ############## Development Orchestrator │
67
67
  │ ## ### ###### ## OrNexus Team │