@adhd/dispatch-core-optimizer 0.0.1
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/index.d.ts +1 -0
- package/index.js +10 -0
- package/index.mjs +901 -0
- package/lib/index.d.ts +3 -0
- package/lib/optimize/index.d.ts +1 -0
- package/lib/optimize.d.ts +36 -0
- package/lib/size-tokens.d.ts +15 -0
- package/lib/snapshot/index.d.ts +1 -0
- package/lib/snapshot.d.ts +35 -0
- package/package.json +10 -0
- package/test/fixtures.d.ts +21 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib';
|
package/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const de=new Set(["create","modify-signature","modify-body","add-export","remove-export","rename"]),me=new Set(["pending","pending-surfaced","in_progress","complete","failed","skipped"]),_e=new Set(["pending","in_progress","complete","failed","skipped"]);function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function O(e){return typeof e=="string"}function h(e,t,n){return{path:e,message:t,value:n}}function ge(e){const t=[];if(!S(e))return{valid:!1,errors:[h("","root must be an object")]};for(const o of["snapshot_at","description"])O(e[o])||t.push(h(o,"required string field missing",e[o]));O(e.plan)||t.push(h("plan","required string",e.plan));const n=e.milestones;if(!S(n))t.push(h("milestones","must be an object",n));else{const o=Object.keys(n),i=new Set(o);for(const s of o){const r=n[s];if(!S(r)){t.push(h(`milestones.${s}`,"must be an object",r));continue}const c=r.eligible,u=r.pending;c===!0&&u!==null&&u!==void 0&&t.push(h(`milestones.${s}`,"D-07 violation: eligible=true but pending not null")),typeof c!="boolean"&&t.push(h(`milestones.${s}.eligible`,"must be boolean",c));const p=r.status;(!O(p)||!me.has(p))&&t.push(h(`milestones.${s}.status`,"invalid status",p));const _=r.wave;(typeof _!="number"||!Number.isInteger(_)||_<0)&&t.push(h(`milestones.${s}.wave`,"must be non-negative integer",_));const b=r.ki_estimate;b!=null&&typeof b!="number"&&t.push(h(`milestones.${s}.ki_estimate`,"must be number|null",b));for(const v of["tokens_estimated","tokens_actual"]){const y=r[v];y!=null&&typeof y!="number"&&t.push(h(`milestones.${s}.${v}`,"must be number|null",y))}Array.isArray(r.artifacts)||t.push(h(`milestones.${s}.artifacts`,"must be an array",r.artifacts)),typeof r.si_bytes!="number"&&t.push(h(`milestones.${s}.si_bytes`,"must be a number",r.si_bytes))}const l=e.operations;if(!Array.isArray(l))t.push(h("operations","must be an array",l));else for(const s of l){if(!S(s))continue;const r=O(s.id)?s.id:"?",c=s.milestone;O(c)&&!i.has(c)&&t.push(h(`operations[${r}].milestone`,`unknown milestone "${c}"`));const u=s.status;(!O(u)||!_e.has(u))&&t.push(h(`operations[${r}].status`,"invalid operation status",u)),Array.isArray(s.dispatch_ids)||t.push(h(`operations[${r}].dispatch_ids`,"must be an array",s.dispatch_ids)),typeof s.attempt_count!="number"&&t.push(h(`operations[${r}].attempt_count`,"must be a number",s.attempt_count)),Array.isArray(s.blast_radius)||t.push(h(`operations[${r}].blast_radius`,"must be an array",s.blast_radius))}const f=e.open_questions;if(!Array.isArray(f))t.push(h("open_questions","must be an array",f));else for(const s of f){if(!S(s))continue;const r=s.blocking;(!O(r)||!i.has(r))&&t.push(h("open_questions",`unknown blocking milestone "${r}"`)),typeof s.surfaced!="boolean"&&t.push(h(`open_questions[${s.id}]`,"surfaced must be boolean",s.surfaced)),typeof s.answered!="boolean"&&t.push(h(`open_questions[${s.id}]`,"answered must be boolean",s.answered))}const a=e.dispatch_units;if(a!==void 0)if(!Array.isArray(a))t.push(h("dispatch_units","must be an array if present",a));else for(const s of a){if(!S(s))continue;const r=s.fits_context_window;typeof r!="boolean"&&t.push(h(`dispatch_units[${s.id}]`,"fits_context_window must be boolean",r));const c=s.milestones;if(Array.isArray(c))for(const u of c)O(u)&&!i.has(u)&&t.push(h(`dispatch_units[${s.id}].milestones`,`unknown milestone "${u}"`))}S(e.pairwise_overlap)||t.push(h("pairwise_overlap","must be an object",e.pairwise_overlap))}return{valid:t.length===0,errors:t}}function he(e){const t=ge(e);if(!t.valid)throw new Error(`Snapshot validation failed:
|
|
2
|
+
${t.errors.map(n=>` ${n.path}: ${n.message}`).join(`
|
|
3
|
+
`)}`)}const U={prose:5.5,md:5.5,ts:6.3,tsx:6.3,py:6.3,default:4};function N(e,t){if(e<=0)return 0;const o=U[""]??U.default??4;return Math.ceil(e/o)}function Z(e,t){if(e.length===0||t.fileSizes===void 0)return new Map;try{return t.fileSizes(e)}catch{return new Map}}const be={low:600,medium:1e3,high:2e3},ye=de;function ve(e){const t=e.properties??{};return Object.keys(t).length||Object.keys(e).length}function we(e,t){if(e.type==="tool-call")return 0;const n=e.shape;if(!n||n.kind===null)return 0;const o=n.kind;if(o==="function"||o==="interface"||o==="type"||o==="class"||o==="enum"||o==="const"||o==="script")return("ops"in n&&Array.isArray(n.ops)?n.ops:[]).length*200;if(o==="config"||o==="env"||o==="schema"||o==="manifest")return("ops"in n&&Array.isArray(n.ops)?n.ops:[]).length*100;if(o==="doc")return be[t??"medium"]??1e3;if(o==="structured-output"){const i="schema"in n&&n.schema?n.schema:{};return ve(i)*50}return 0}function ke(e,t){const n=new Set([...Object.keys(e),...Object.keys(t)]),o={};for(const i of n){const l=e[i];o[i]=l??t[i]??null}return o}function $e(e,t){const n=new Set([...Object.keys(e),...Object.keys(t)]),o={};for(const i of n){const l=e[i]??t[i];if(l===void 0)throw new TypeError(`Model tier "${i}" not found in dag or deps context_window_per_tier`);o[i]=l}return o}function ee(e){var a;const t=Object.keys(e),n=new Map,o=new Map;for(const s of t)n.has(s)||n.set(s,0),o.has(s)||o.set(s,[]);for(const s of t){const r=((a=e[s])==null?void 0:a.depends_on)??[];for(const c of r){const u=o.get(c);u!==void 0&&u.push(s),n.set(s,(n.get(s)??0)+1)}}const i=new Map,l=[];let f=t.filter(s=>(n.get(s)??0)===0).sort();for(const s of f)i.set(s,0);for(;f.length>0;){const s=[];for(const r of f){l.push(r);const c=(o.get(r)??[]).slice().sort();for(const u of c){const p=(n.get(u)??0)-1;n.set(u,p);const _=i.get(r)??0,b=i.get(u)??0;i.set(u,Math.max(b,_+1)),p===0&&s.push(u)}}f=s.sort()}if(l.length!==t.length){const s=new Set(l),r=t.filter(c=>!s.has(c));throw new Error(`snapshot(): cycle detected in milestone depends_on graph. Nodes involved: [${r.join(", ")}]`)}return{order:l,waves:i}}function te(e,t){if(t.length===0)return[];const n=new Set(t);return e.filter(o=>o.operations.some(i=>n.has(i)))}function ne(e,t){return e.filter(n=>n.operations.includes(t))}function Ae(e,t,n,o,i){const l=`${e}.guard`,f=[...n,l],a=te(o,f);for(const r of a)for(const c of r.results)if(c.op_id===l&&c.guard_result==="pass")return"complete";for(const r of a)for(const c of r.results)if(f.includes(c.op_id)&&c.status==="failed")return"failed";for(const r of a)for(const c of r.results)if(f.includes(c.op_id)&&c.status==="in_progress")return"in_progress";const s=i.length===0||i.every(r=>r==="complete");return t.pending!==null&&s?"pending-surfaced":"pending"}function Oe(e,t){const n=`${e}.guard`;let o=null,i=null,l=null;for(const f of t)if(f.operations.includes(n))for(const a of f.results)a.op_id===n&&a.guard_result!==null&&(o=a.guard_result,i=a.guard_output,a.guard_result==="pass"&&(l=a.guard_ran_at));return o!==null?{guard_result:o,guard_output:i,completed_at:l}:{guard_result:"pending",guard_output:null,completed_at:null}}function Se(e){const t=new Set;for(const n of e)n.action==="move"&&n.to_file?t.add(n.to_file):ye.has(n.action)&&n.file&&t.add(n.file);return Array.from(t)}function Me(e,t,n){const o=ne(n,e.id),i=o.map(c=>c.id);let l=null,f=null,a=null;for(const c of o)for(const u of c.results)u.op_id===e.id&&u.guard_result!==null&&(l=u.guard_result,f=u.guard_output,a=u.guard_ran_at);const s=e.ki_estimate!==null&&e.ki_estimate!==void 0?e.ki_estimate:we(e,t),r=je(e.shape);return{...e,ki_estimate:s,shape:r,dispatch_ids:i,attempt_count:0,guard_result:l,guard_output:f,guard_ran_at:a,blast_radius:[],conflict:{detected:!1,competing_op:null,op_key:null,resolution:null},tokens_actual:null}}function je(e){if(!e)return null;if(e.kind===null)return e;const t=e.kind;if(t==="function"||t==="interface"||t==="type"||t==="class"||t==="enum"||t==="const"||t==="script"||t==="config"||t==="env"||t==="schema"||t==="manifest"){const n=("ops"in e&&Array.isArray(e.ops)?e.ops:[]).map(o=>({...o,from:null,breaking:null,severity:null}));return{...e,ops:n}}return e}function Te(e,t,n,o){const i=`${e}.guard`,l=ne(o,i),f=l.map(c=>c.id);let a=null,s=null,r=null;for(const c of l)for(const u of c.results)u.op_id===i&&u.guard_result!==null&&(a=u.guard_result,s=u.guard_output,r=u.guard_ran_at);return{id:i,milestone:e,depends_on:n,type:"tool-call",action:"guard",file:null,symbol:null,provenance:null,confidence:null,audit_check:null,criteria:[],tool:null,args:null,guard:t.guard??null,to_file:null,to_symbol:null,ki_estimate:0,ki_source:null,authored_by:"synthesized",status:"pending",shape:null,dispatch_ids:f,attempt_count:0,guard_result:a,guard_output:s,guard_ran_at:r,blast_radius:[],conflict:{detected:!1,competing_op:null,op_key:null,resolution:null},tokens_actual:null}}function Ie(e,t){const n={},{write_multiplier:o,read_multiplier:i,hit_probability:l}=t;for(const[f,a]of Object.entries(e))a===null?n[f]=null:n[f]=Math.round(a*((1-l)*o+l*i));return n}function xe(e,t,n){const o=Array.from(e.keys()),i={};for(let l=0;l<o.length;l++)for(let f=l+1;f<o.length;f++){const a=o[l],s=o[f];if(a===void 0||s===void 0)continue;const[r,c]=a<s?[a,s]:[s,a],u=`${r}:${c}`,p=e.get(a)??[],_=e.get(s)??[],b=new Set(p.map(w=>w.file).filter(w=>w!==null)),v=new Set(_.map(w=>w.file).filter(w=>w!==null)),y=Array.from(b).filter(w=>v.has(w));if(y.length===0)continue;const k=t.get(a)??"pending",$=t.get(s)??"pending",M=k==="complete"&&$==="complete";let P=0;for(const w of y)P+=M?n(w):0;i[u]=P}return i}function ze(e){return(Array.isArray(e)?e:Object.values(e)).map(n=>n.type===void 0?{...n,type:"generative"}:n)}function Pe(e,t){const n=new Date().toISOString(),o=t.dispatchLog??e.dispatch_log,i=e.optimization.sentinel_fanout,l=ke(e.optimization.b_per_tier,t.bPerTier),f=$e(e.optimization.context_window_per_tier,t.contextWindowPerTier),a=Ie(l,i),{waves:s}=ee(e.milestones),r=ze(e.operations),c=new Map;for(const m of r){const d=c.get(m.milestone)??[];d.push(m),c.set(m.milestone,d)}const u=new Set;for(const m of r)m.file&&u.add(m.file),m.action==="move"&&m.to_file&&u.add(m.to_file);const p=Z(Array.from(u),t),_=m=>p.get(m)??0,b=new Map,v=Array.from(s.entries()).sort((m,d)=>m[1]-d[1]||m[0].localeCompare(d[0])).map(([m])=>m);for(const m of v){const d=e.milestones[m];if(d===void 0)continue;const j=(c.get(m)??[]).map(I=>I.id),T=d.depends_on.map(I=>b.get(I)??"pending"),x=Ae(m,d,j,o,T);b.set(m,x)}const y={},k=[];for(const m of v){const d=e.milestones[m];if(d===void 0)continue;const j=s.get(m)??0,T=c.get(m)??[],x=T.map(g=>g.id),I=b.get(m)??"pending",D=d.depends_on.map(g=>b.get(g)??"pending"),le=d.depends_on.length===0||D.every(g=>g==="complete"),ue=D.every(g=>g!=="failed"),ae=d.pending===null&&le&&ue,E=te(o,[...x,`${m}.guard`]),ce=E.length>0?E.map(g=>g.started_at).sort()[0]??null:null;let F,q,B;if(d.guard){const g=Oe(m,o);F=g.guard_result,q=g.guard_output,B=g.completed_at}else F=null,q=null,B=null;const R=Se(T),K=R.reduce((g,A)=>g+_(A),0),W=T.map(g=>Me(g,d.effort,o));let z=null,G=0,L=!1;for(const g of W){if(g.ki_estimate===null){L=!0;break}G+=g.ki_estimate}L||(z=G);let V=null;const Y=d.model;if(Y!==null&&z!==null){const g=a[Y]??null;if(g!==null){const A=N(K);V=g+A+z}}let H=null;const J=E.filter(g=>g.completed_at!==null&&g.results.length>0&&g.results.every(A=>A.status==="complete"||A.status==="skipped"));J.length>0&&(H=J.reduce((g,A)=>g+A.turns.reduce((pe,Q)=>pe+Q.input_tokens+Q.output_tokens,0),0));const fe=Te(m,d,x,o);k.push(...W,fe),y[m]={description:d.description,...d.rationale!==void 0?{rationale:d.rationale}:{},authored_by:d.authored_by,pending:d.pending,triggered_by:d.triggered_by,phase:d.phase,depends_on:d.depends_on,agent:d.agent,model:d.model,effort:d.effort,two_stage:d.two_stage,read_only:d.read_only,guard:d.guard,context:`contexts/${m}.md`,wave:j,eligible:ae,status:I,started_at:ce,completed_at:B,guard_result:F,guard_output:q,artifacts:R,si_bytes:K,ki_estimate:z,tokens_estimated:V,tokens_actual:H}}const $=xe(c,b,_),M=Ee(e,y),w={tokens_naive:(()=>{let m=0;for(const d of Object.values(y))if(d.eligible&&d.status==="pending"&&d.model!==null){const j=l[d.model]??t.bPerTier[d.model]??0;m+=j+(d.ki_estimate??0)}return m})(),sentinel_fanout:i,context_window_override:e.optimization.context_window_override,b_override:e.optimization.b_override,b_per_tier:l,b_eff_per_tier:a,context_window_per_tier:f},C={snapshot_at:n,snapshot_version:1,plan:"",schema_version:e.schema_version,plan_kind:e.plan_kind,description:e.description,problem:e.problem,approach:e.approach,executor:e.executor,...e.executor_model!==void 0?{executor_model:e.executor_model}:{},...e.executor_effort!==void 0?{executor_effort:e.executor_effort}:{},phases:[...e.phases],terminal:e.terminal,...e.assumed_baseline!==void 0?{assumed_baseline:e.assumed_baseline}:{},optimization:w,milestones:y,operations:k,pairwise_overlap:$,open_questions:M};return he(C),C}function Ee(e,t){const n=[];for(const[o,i]of Object.entries(t)){const l=e.milestones[o];if(l===void 0||l.pending===null)continue;const f=i.status==="pending-surfaced";n.push({id:`q:${o}`,text:l.pending,blocking:o,surfaced:f,raised_at_dispatch:null,raised_at_turn:null,answered:!1,answer:null})}return n}function oe(e){return Object.keys(e.milestones).filter(t=>{const n=e.milestones[t];return n!==void 0&&n.eligible===!0&&n.status==="pending"})}function Fe(e){if(e.length===0||e.every(t=>t.type==="tool-call"))return"tool-call";for(const t of e){if(t.type!=="generative"||!t.shape||t.shape.kind===null)continue;const n=t.shape.kind;if(n==="function"||n==="interface"||n==="type"||n==="class"||n==="enum"||n==="const"||n==="script"||n==="config"||n==="env"||n==="schema"||n==="manifest")return"code-config";if(n==="doc")return"doc";if(n==="structured-output")return"structured"}return"code-config"}function qe(e){if(!e)return"";const t=e.indexOf(":");return t>=0?e.slice(t+1):e}function Be(e,t,n){let o=!0;const i=[];for(const l of e){const f=t[l];if(f===void 0)continue;const a=n.filter(r=>r.milestone===l&&r.action!=="guard");a.some(r=>r.type==="generative")&&(o=!1),i.push(`## Milestone: ${l}`),i.push(f.description),f.rationale&&i.push(`
|
|
4
|
+
*Rationale:* ${f.rationale}`),i.push(`
|
|
5
|
+
### Operations:`);for(const r of a){const c=r.file?` ${r.file}`:"",u=r.symbol?` (${r.symbol})`:"";if(i.push(`- [${r.id}] ${r.action}${c}${u}`),r.shape&&r.shape.kind!==null){const p=r.shape;if(p.kind==="doc")i.push(` Description: ${p.description}`),i.push(` Objective: ${p.objective}`),p.required_sections&&p.required_sections.length>0&&i.push(` Required sections: ${p.required_sections.join(", ")}`);else if(p.kind==="structured-output")i.push(` Schema:
|
|
6
|
+
`+JSON.stringify(p.schema,null,2).split(`
|
|
7
|
+
`).map(_=>` ${_}`).join(`
|
|
8
|
+
`));else if("ops"in p&&Array.isArray(p.ops))for(const _ of p.ops){const b=_.to!==null?` → ${_.to}`:"",v=_.target!==null?` "${_.target}"`:"";i.push(` - ${_.op}${v}${b}`)}}}const s=f.guard;i.push(`
|
|
9
|
+
### Guard: ${s??"none"}`),i.push("")}return o?null:i.join(`
|
|
10
|
+
`)}function se(e,t,n){if(e===null)return null;const o=t.optimization.b_eff_per_tier[e];if(o!=null)return o;const i=t.optimization.b_per_tier[e];if(i!=null)return i;const l=n.bPerTier[e];return l!==void 0?l:null}function ie(e,t,n){if(e===null)return Number.POSITIVE_INFINITY;const o=t.optimization.context_window_per_tier[e];if(o!==void 0)return o;const i=n.contextWindowPerTier[e];return i!==void 0?i:Number.POSITIVE_INFINITY}function re(e,t){const n=new Set;for(const o of e){const i=t.snapshot.milestones[o];if(i!==void 0){n.add(i.context);for(const l of i.read_only)n.add(l);for(const l of t.opsByMilestone.get(o)??[])l.file&&n.add(l.file)}}return Array.from(n)}function X(e,t,n){const o=se(t,n.snapshot,n.deps);if(o===null)return null;const l=re(e,n).reduce((s,r)=>s+(n.sizeMap.get(r)??0),0),f=N(l),a=e.reduce((s,r)=>{var c;return s+(((c=n.snapshot.milestones[r])==null?void 0:c.ki_estimate)??0)},0);return o+f+a}function Ne(e,t,n){const o=ie(t,n.snapshot,n.deps),i=[...e].sort((a,s)=>{var u,p;const r=((u=n.snapshot.milestones[a])==null?void 0:u.ki_estimate)??0,c=((p=n.snapshot.milestones[s])==null?void 0:p.ki_estimate)??0;return r-c||a.localeCompare(s)}),l=[];let f=[];for(const a of i){const s=[...f,a],r=X(s,t,n);r!==null&&r>o&&f.length>0?(l.push(f),f=[a]):f=s}return f.length>0&&l.push(f),l.filter(a=>{const s=X(a,t,n);return s===null||s<=o})}function Ce(e,t,n,o){const i=e[0]??"",l=o.snapshot.milestones[i],f=(l==null?void 0:l.effort)??null,a=[];for(const k of e)for(const $ of o.opsByMilestone.get(k)??[])a.push($.id);const s=re(e,o),r=s.reduce((k,$)=>k+(o.sizeMap.get($)??0),0),c=se(n,o.snapshot,o.deps),u=e.reduce((k,$)=>{var M;return k+(((M=o.snapshot.milestones[$])==null?void 0:M.ki_estimate)??0)},0),p=c!==null?c+N(r)+u:null,_=ie(n,o.snapshot,o.deps),b=p!==null?p<=_:!0,v=qe((l==null?void 0:l.agent)??null),y=Be(e,o.snapshot.milestones,o.snapshot.operations);return{id:`${i}.dispatch.${t}`,milestones:e,operations:a,model:n,effort:f,two_stage:(l==null?void 0:l.two_stage)??!1,provider:null,agent_name:v,mcp_servers:null,resolved_max_tokens:null,background:!0,prompt:y,context_files:s,si_bytes:r,tokens_estimated:p,fits_context_window:b,sentinel_role:null,dispatch_log_id:null,remote_task_id:null,result:null,status:"pending",started_at:null,completed_at:null,tokens_actual:null}}function De(e,t){const n=oe(e);if(n.length===0)return[];const o=new Map;for(const u of e.operations){if(u.action==="guard")continue;const p=o.get(u.milestone)??[];p.push(u),o.set(u.milestone,p)}const i=new Map;for(const u of n){const p=e.milestones[u];if(p===void 0)continue;const _=Fe(o.get(u)??[]),b=p.model??"_null",v=`${_}:${b}`,y=i.get(v)??[];y.push(u),i.set(v,y)}const l=new Set;for(const u of n){const p=e.milestones[u];if(p!==void 0){l.add(p.context);for(const _ of p.read_only)l.add(_);for(const _ of o.get(u)??[])_.file&&l.add(_.file)}}const f=Z(Array.from(l),t),a={snapshot:e,deps:t,sizeMap:f,opsByMilestone:o},s=[];let r=0;const c=Array.from(i.keys()).sort();for(const u of c){const p=i.get(u);if(p===void 0)continue;const _=u.slice(u.indexOf(":")+1),b=_!=="_null"?_:null,v=Ne(p,b,a);for(const y of v)s.push(Ce(y,r++,b,a))}return s}function Re(e,t){let n=0;for(const o of oe(e)){const i=e.milestones[o];if(i===void 0)continue;const l=Ke(i.model,e,t)??0;n+=l+(i.ki_estimate??0)}return n}function Ke(e,t,n){if(e===null)return null;const o=t.optimization.b_per_tier[e];if(o!=null)return o;const i=n.bPerTier[e];return i!==void 0?i:null}exports.computeTokensNaive=Re;exports.optimize=De;exports.snapshot=Pe;exports.topoSortMilestones=ee;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,901 @@
|
|
|
1
|
+
const pe = /* @__PURE__ */ new Set([
|
|
2
|
+
"create",
|
|
3
|
+
"modify-signature",
|
|
4
|
+
"modify-body",
|
|
5
|
+
"add-export",
|
|
6
|
+
"remove-export",
|
|
7
|
+
"rename"
|
|
8
|
+
]), de = /* @__PURE__ */ new Set([
|
|
9
|
+
"pending",
|
|
10
|
+
"pending-surfaced",
|
|
11
|
+
"in_progress",
|
|
12
|
+
"complete",
|
|
13
|
+
"failed",
|
|
14
|
+
"skipped"
|
|
15
|
+
]), _e = /* @__PURE__ */ new Set([
|
|
16
|
+
"pending",
|
|
17
|
+
"in_progress",
|
|
18
|
+
"complete",
|
|
19
|
+
"failed",
|
|
20
|
+
"skipped"
|
|
21
|
+
]);
|
|
22
|
+
function S(e) {
|
|
23
|
+
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
24
|
+
}
|
|
25
|
+
function O(e) {
|
|
26
|
+
return typeof e == "string";
|
|
27
|
+
}
|
|
28
|
+
function g(e, t, n) {
|
|
29
|
+
return { path: e, message: t, value: n };
|
|
30
|
+
}
|
|
31
|
+
function me(e) {
|
|
32
|
+
const t = [];
|
|
33
|
+
if (!S(e))
|
|
34
|
+
return { valid: !1, errors: [g("", "root must be an object")] };
|
|
35
|
+
for (const o of ["snapshot_at", "description"])
|
|
36
|
+
O(e[o]) || t.push(g(o, "required string field missing", e[o]));
|
|
37
|
+
O(e.plan) || t.push(g("plan", "required string", e.plan));
|
|
38
|
+
const n = e.milestones;
|
|
39
|
+
if (!S(n))
|
|
40
|
+
t.push(g("milestones", "must be an object", n));
|
|
41
|
+
else {
|
|
42
|
+
const o = Object.keys(n), i = new Set(o);
|
|
43
|
+
for (const s of o) {
|
|
44
|
+
const r = n[s];
|
|
45
|
+
if (!S(r)) {
|
|
46
|
+
t.push(g(`milestones.${s}`, "must be an object", r));
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const c = r.eligible, u = r.pending;
|
|
50
|
+
c === !0 && u !== null && u !== void 0 && t.push(
|
|
51
|
+
g(
|
|
52
|
+
`milestones.${s}`,
|
|
53
|
+
"D-07 violation: eligible=true but pending not null"
|
|
54
|
+
)
|
|
55
|
+
), typeof c != "boolean" && t.push(
|
|
56
|
+
g(`milestones.${s}.eligible`, "must be boolean", c)
|
|
57
|
+
);
|
|
58
|
+
const p = r.status;
|
|
59
|
+
(!O(p) || !de.has(p)) && t.push(g(`milestones.${s}.status`, "invalid status", p));
|
|
60
|
+
const m = r.wave;
|
|
61
|
+
(typeof m != "number" || !Number.isInteger(m) || m < 0) && t.push(
|
|
62
|
+
g(`milestones.${s}.wave`, "must be non-negative integer", m)
|
|
63
|
+
);
|
|
64
|
+
const b = r.ki_estimate;
|
|
65
|
+
b != null && typeof b != "number" && t.push(
|
|
66
|
+
g(`milestones.${s}.ki_estimate`, "must be number|null", b)
|
|
67
|
+
);
|
|
68
|
+
for (const v of ["tokens_estimated", "tokens_actual"]) {
|
|
69
|
+
const y = r[v];
|
|
70
|
+
y != null && typeof y != "number" && t.push(g(`milestones.${s}.${v}`, "must be number|null", y));
|
|
71
|
+
}
|
|
72
|
+
Array.isArray(r.artifacts) || t.push(
|
|
73
|
+
g(
|
|
74
|
+
`milestones.${s}.artifacts`,
|
|
75
|
+
"must be an array",
|
|
76
|
+
r.artifacts
|
|
77
|
+
)
|
|
78
|
+
), typeof r.si_bytes != "number" && t.push(
|
|
79
|
+
g(`milestones.${s}.si_bytes`, "must be a number", r.si_bytes)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
const l = e.operations;
|
|
83
|
+
if (!Array.isArray(l))
|
|
84
|
+
t.push(g("operations", "must be an array", l));
|
|
85
|
+
else
|
|
86
|
+
for (const s of l) {
|
|
87
|
+
if (!S(s))
|
|
88
|
+
continue;
|
|
89
|
+
const r = O(s.id) ? s.id : "?", c = s.milestone;
|
|
90
|
+
O(c) && !i.has(c) && t.push(
|
|
91
|
+
g(
|
|
92
|
+
`operations[${r}].milestone`,
|
|
93
|
+
`unknown milestone "${c}"`
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
const u = s.status;
|
|
97
|
+
(!O(u) || !_e.has(u)) && t.push(
|
|
98
|
+
g(
|
|
99
|
+
`operations[${r}].status`,
|
|
100
|
+
"invalid operation status",
|
|
101
|
+
u
|
|
102
|
+
)
|
|
103
|
+
), Array.isArray(s.dispatch_ids) || t.push(
|
|
104
|
+
g(
|
|
105
|
+
`operations[${r}].dispatch_ids`,
|
|
106
|
+
"must be an array",
|
|
107
|
+
s.dispatch_ids
|
|
108
|
+
)
|
|
109
|
+
), typeof s.attempt_count != "number" && t.push(
|
|
110
|
+
g(
|
|
111
|
+
`operations[${r}].attempt_count`,
|
|
112
|
+
"must be a number",
|
|
113
|
+
s.attempt_count
|
|
114
|
+
)
|
|
115
|
+
), Array.isArray(s.blast_radius) || t.push(
|
|
116
|
+
g(
|
|
117
|
+
`operations[${r}].blast_radius`,
|
|
118
|
+
"must be an array",
|
|
119
|
+
s.blast_radius
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const f = e.open_questions;
|
|
124
|
+
if (!Array.isArray(f))
|
|
125
|
+
t.push(g("open_questions", "must be an array", f));
|
|
126
|
+
else
|
|
127
|
+
for (const s of f) {
|
|
128
|
+
if (!S(s))
|
|
129
|
+
continue;
|
|
130
|
+
const r = s.blocking;
|
|
131
|
+
(!O(r) || !i.has(r)) && t.push(
|
|
132
|
+
g("open_questions", `unknown blocking milestone "${r}"`)
|
|
133
|
+
), typeof s.surfaced != "boolean" && t.push(
|
|
134
|
+
g(
|
|
135
|
+
`open_questions[${s.id}]`,
|
|
136
|
+
"surfaced must be boolean",
|
|
137
|
+
s.surfaced
|
|
138
|
+
)
|
|
139
|
+
), typeof s.answered != "boolean" && t.push(
|
|
140
|
+
g(
|
|
141
|
+
`open_questions[${s.id}]`,
|
|
142
|
+
"answered must be boolean",
|
|
143
|
+
s.answered
|
|
144
|
+
)
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const a = e.dispatch_units;
|
|
148
|
+
if (a !== void 0)
|
|
149
|
+
if (!Array.isArray(a))
|
|
150
|
+
t.push(
|
|
151
|
+
g("dispatch_units", "must be an array if present", a)
|
|
152
|
+
);
|
|
153
|
+
else
|
|
154
|
+
for (const s of a) {
|
|
155
|
+
if (!S(s))
|
|
156
|
+
continue;
|
|
157
|
+
const r = s.fits_context_window;
|
|
158
|
+
typeof r != "boolean" && t.push(
|
|
159
|
+
g(
|
|
160
|
+
`dispatch_units[${s.id}]`,
|
|
161
|
+
"fits_context_window must be boolean",
|
|
162
|
+
r
|
|
163
|
+
)
|
|
164
|
+
);
|
|
165
|
+
const c = s.milestones;
|
|
166
|
+
if (Array.isArray(c))
|
|
167
|
+
for (const u of c)
|
|
168
|
+
O(u) && !i.has(u) && t.push(
|
|
169
|
+
g(
|
|
170
|
+
`dispatch_units[${s.id}].milestones`,
|
|
171
|
+
`unknown milestone "${u}"`
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
S(e.pairwise_overlap) || t.push(
|
|
176
|
+
g(
|
|
177
|
+
"pairwise_overlap",
|
|
178
|
+
"must be an object",
|
|
179
|
+
e.pairwise_overlap
|
|
180
|
+
)
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
return { valid: t.length === 0, errors: t };
|
|
184
|
+
}
|
|
185
|
+
function he(e) {
|
|
186
|
+
const t = me(e);
|
|
187
|
+
if (!t.valid)
|
|
188
|
+
throw new Error(
|
|
189
|
+
`Snapshot validation failed:
|
|
190
|
+
${t.errors.map((n) => ` ${n.path}: ${n.message}`).join(`
|
|
191
|
+
`)}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
const U = {
|
|
195
|
+
prose: 5.5,
|
|
196
|
+
md: 5.5,
|
|
197
|
+
ts: 6.3,
|
|
198
|
+
tsx: 6.3,
|
|
199
|
+
py: 6.3,
|
|
200
|
+
default: 4
|
|
201
|
+
};
|
|
202
|
+
function C(e, t) {
|
|
203
|
+
if (e <= 0)
|
|
204
|
+
return 0;
|
|
205
|
+
const o = U[""] ?? U.default ?? 4;
|
|
206
|
+
return Math.ceil(e / o);
|
|
207
|
+
}
|
|
208
|
+
function Z(e, t) {
|
|
209
|
+
if (e.length === 0 || t.fileSizes === void 0)
|
|
210
|
+
return /* @__PURE__ */ new Map();
|
|
211
|
+
try {
|
|
212
|
+
return t.fileSizes(e);
|
|
213
|
+
} catch {
|
|
214
|
+
return /* @__PURE__ */ new Map();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const ge = {
|
|
218
|
+
low: 600,
|
|
219
|
+
medium: 1e3,
|
|
220
|
+
high: 2e3
|
|
221
|
+
}, be = pe;
|
|
222
|
+
function ye(e) {
|
|
223
|
+
const t = e.properties ?? {};
|
|
224
|
+
return Object.keys(t).length || Object.keys(e).length;
|
|
225
|
+
}
|
|
226
|
+
function ve(e, t) {
|
|
227
|
+
if (e.type === "tool-call")
|
|
228
|
+
return 0;
|
|
229
|
+
const n = e.shape;
|
|
230
|
+
if (!n || n.kind === null)
|
|
231
|
+
return 0;
|
|
232
|
+
const o = n.kind;
|
|
233
|
+
if (o === "function" || o === "interface" || o === "type" || o === "class" || o === "enum" || o === "const" || o === "script")
|
|
234
|
+
return ("ops" in n && Array.isArray(n.ops) ? n.ops : []).length * 200;
|
|
235
|
+
if (o === "config" || o === "env" || o === "schema" || o === "manifest")
|
|
236
|
+
return ("ops" in n && Array.isArray(n.ops) ? n.ops : []).length * 100;
|
|
237
|
+
if (o === "doc")
|
|
238
|
+
return ge[t ?? "medium"] ?? 1e3;
|
|
239
|
+
if (o === "structured-output") {
|
|
240
|
+
const i = "schema" in n && n.schema ? n.schema : {};
|
|
241
|
+
return ye(i) * 50;
|
|
242
|
+
}
|
|
243
|
+
return 0;
|
|
244
|
+
}
|
|
245
|
+
function we(e, t) {
|
|
246
|
+
const n = /* @__PURE__ */ new Set([...Object.keys(e), ...Object.keys(t)]), o = {};
|
|
247
|
+
for (const i of n) {
|
|
248
|
+
const l = e[i];
|
|
249
|
+
o[i] = l ?? t[i] ?? null;
|
|
250
|
+
}
|
|
251
|
+
return o;
|
|
252
|
+
}
|
|
253
|
+
function ke(e, t) {
|
|
254
|
+
const n = /* @__PURE__ */ new Set([...Object.keys(e), ...Object.keys(t)]), o = {};
|
|
255
|
+
for (const i of n) {
|
|
256
|
+
const l = e[i] ?? t[i];
|
|
257
|
+
if (l === void 0)
|
|
258
|
+
throw new TypeError(
|
|
259
|
+
`Model tier "${i}" not found in dag or deps context_window_per_tier`
|
|
260
|
+
);
|
|
261
|
+
o[i] = l;
|
|
262
|
+
}
|
|
263
|
+
return o;
|
|
264
|
+
}
|
|
265
|
+
function $e(e) {
|
|
266
|
+
var a;
|
|
267
|
+
const t = Object.keys(e), n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
|
|
268
|
+
for (const s of t)
|
|
269
|
+
n.has(s) || n.set(s, 0), o.has(s) || o.set(s, []);
|
|
270
|
+
for (const s of t) {
|
|
271
|
+
const r = ((a = e[s]) == null ? void 0 : a.depends_on) ?? [];
|
|
272
|
+
for (const c of r) {
|
|
273
|
+
const u = o.get(c);
|
|
274
|
+
u !== void 0 && u.push(s), n.set(s, (n.get(s) ?? 0) + 1);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const i = /* @__PURE__ */ new Map(), l = [];
|
|
278
|
+
let f = t.filter((s) => (n.get(s) ?? 0) === 0).sort();
|
|
279
|
+
for (const s of f)
|
|
280
|
+
i.set(s, 0);
|
|
281
|
+
for (; f.length > 0; ) {
|
|
282
|
+
const s = [];
|
|
283
|
+
for (const r of f) {
|
|
284
|
+
l.push(r);
|
|
285
|
+
const c = (o.get(r) ?? []).slice().sort();
|
|
286
|
+
for (const u of c) {
|
|
287
|
+
const p = (n.get(u) ?? 0) - 1;
|
|
288
|
+
n.set(u, p);
|
|
289
|
+
const m = i.get(r) ?? 0, b = i.get(u) ?? 0;
|
|
290
|
+
i.set(u, Math.max(b, m + 1)), p === 0 && s.push(u);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
f = s.sort();
|
|
294
|
+
}
|
|
295
|
+
if (l.length !== t.length) {
|
|
296
|
+
const s = new Set(l), r = t.filter((c) => !s.has(c));
|
|
297
|
+
throw new Error(
|
|
298
|
+
`snapshot(): cycle detected in milestone depends_on graph. Nodes involved: [${r.join(", ")}]`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
return { order: l, waves: i };
|
|
302
|
+
}
|
|
303
|
+
function ee(e, t) {
|
|
304
|
+
if (t.length === 0)
|
|
305
|
+
return [];
|
|
306
|
+
const n = new Set(t);
|
|
307
|
+
return e.filter(
|
|
308
|
+
(o) => o.operations.some((i) => n.has(i))
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
function te(e, t) {
|
|
312
|
+
return e.filter((n) => n.operations.includes(t));
|
|
313
|
+
}
|
|
314
|
+
function Ae(e, t, n, o, i) {
|
|
315
|
+
const l = `${e}.guard`, f = [...n, l], a = ee(o, f);
|
|
316
|
+
for (const r of a)
|
|
317
|
+
for (const c of r.results)
|
|
318
|
+
if (c.op_id === l && c.guard_result === "pass")
|
|
319
|
+
return "complete";
|
|
320
|
+
for (const r of a)
|
|
321
|
+
for (const c of r.results)
|
|
322
|
+
if (f.includes(c.op_id) && c.status === "failed")
|
|
323
|
+
return "failed";
|
|
324
|
+
for (const r of a)
|
|
325
|
+
for (const c of r.results)
|
|
326
|
+
if (f.includes(c.op_id) && // "in_progress" is not a dispatch_log result status (only complete/failed/skipped)
|
|
327
|
+
// but orchestrators may write it; guard defensively
|
|
328
|
+
c.status === "in_progress")
|
|
329
|
+
return "in_progress";
|
|
330
|
+
const s = i.length === 0 || i.every((r) => r === "complete");
|
|
331
|
+
return t.pending !== null && s ? "pending-surfaced" : "pending";
|
|
332
|
+
}
|
|
333
|
+
function Oe(e, t) {
|
|
334
|
+
const n = `${e}.guard`;
|
|
335
|
+
let o = null, i = null, l = null;
|
|
336
|
+
for (const f of t)
|
|
337
|
+
if (f.operations.includes(n))
|
|
338
|
+
for (const a of f.results)
|
|
339
|
+
a.op_id === n && a.guard_result !== null && (o = a.guard_result, i = a.guard_output, a.guard_result === "pass" && (l = a.guard_ran_at));
|
|
340
|
+
return o !== null ? {
|
|
341
|
+
guard_result: o,
|
|
342
|
+
guard_output: i,
|
|
343
|
+
completed_at: l
|
|
344
|
+
} : { guard_result: "pending", guard_output: null, completed_at: null };
|
|
345
|
+
}
|
|
346
|
+
function Se(e) {
|
|
347
|
+
const t = /* @__PURE__ */ new Set();
|
|
348
|
+
for (const n of e)
|
|
349
|
+
n.action === "move" && n.to_file ? t.add(n.to_file) : be.has(n.action) && n.file && t.add(n.file);
|
|
350
|
+
return Array.from(t);
|
|
351
|
+
}
|
|
352
|
+
function je(e, t, n) {
|
|
353
|
+
const o = te(n, e.id), i = o.map((c) => c.id);
|
|
354
|
+
let l = null, f = null, a = null;
|
|
355
|
+
for (const c of o)
|
|
356
|
+
for (const u of c.results)
|
|
357
|
+
u.op_id === e.id && u.guard_result !== null && (l = u.guard_result, f = u.guard_output, a = u.guard_ran_at);
|
|
358
|
+
const s = e.ki_estimate !== null && e.ki_estimate !== void 0 ? e.ki_estimate : ve(e, t), r = Me(e.shape);
|
|
359
|
+
return {
|
|
360
|
+
...e,
|
|
361
|
+
ki_estimate: s,
|
|
362
|
+
shape: r,
|
|
363
|
+
dispatch_ids: i,
|
|
364
|
+
// TODO: stubbed as 0 — op-level attempt_count requires per-op dispatch log scan
|
|
365
|
+
attempt_count: 0,
|
|
366
|
+
guard_result: l,
|
|
367
|
+
guard_output: f,
|
|
368
|
+
guard_ran_at: a,
|
|
369
|
+
// TODO: stubbed — requires gitnexus_impact MCP call (future work)
|
|
370
|
+
blast_radius: [],
|
|
371
|
+
// TODO: stubbed — requires same-wave op-key collision scan (future work)
|
|
372
|
+
conflict: {
|
|
373
|
+
detected: !1,
|
|
374
|
+
competing_op: null,
|
|
375
|
+
op_key: null,
|
|
376
|
+
resolution: null
|
|
377
|
+
},
|
|
378
|
+
// TODO: stubbed — requires ki_estimate share prorating across dispatch totals
|
|
379
|
+
tokens_actual: null
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
function Me(e) {
|
|
383
|
+
if (!e)
|
|
384
|
+
return null;
|
|
385
|
+
if (e.kind === null)
|
|
386
|
+
return e;
|
|
387
|
+
const t = e.kind;
|
|
388
|
+
if (t === "function" || t === "interface" || t === "type" || t === "class" || t === "enum" || t === "const" || t === "script" || t === "config" || t === "env" || t === "schema" || t === "manifest") {
|
|
389
|
+
const n = ("ops" in e && Array.isArray(e.ops) ? e.ops : []).map((o) => ({
|
|
390
|
+
...o,
|
|
391
|
+
// TODO: from/breaking/severity require AST read + gitnexus (future work)
|
|
392
|
+
from: null,
|
|
393
|
+
breaking: null,
|
|
394
|
+
severity: null
|
|
395
|
+
}));
|
|
396
|
+
return { ...e, ops: n };
|
|
397
|
+
}
|
|
398
|
+
return e;
|
|
399
|
+
}
|
|
400
|
+
function Te(e, t, n, o) {
|
|
401
|
+
const i = `${e}.guard`, l = te(o, i), f = l.map((c) => c.id);
|
|
402
|
+
let a = null, s = null, r = null;
|
|
403
|
+
for (const c of l)
|
|
404
|
+
for (const u of c.results)
|
|
405
|
+
u.op_id === i && u.guard_result !== null && (a = u.guard_result, s = u.guard_output, r = u.guard_ran_at);
|
|
406
|
+
return {
|
|
407
|
+
id: i,
|
|
408
|
+
milestone: e,
|
|
409
|
+
depends_on: n,
|
|
410
|
+
type: "tool-call",
|
|
411
|
+
action: "guard",
|
|
412
|
+
file: null,
|
|
413
|
+
symbol: null,
|
|
414
|
+
provenance: null,
|
|
415
|
+
confidence: null,
|
|
416
|
+
audit_check: null,
|
|
417
|
+
criteria: [],
|
|
418
|
+
tool: null,
|
|
419
|
+
args: null,
|
|
420
|
+
guard: t.guard ?? null,
|
|
421
|
+
to_file: null,
|
|
422
|
+
to_symbol: null,
|
|
423
|
+
ki_estimate: 0,
|
|
424
|
+
ki_source: null,
|
|
425
|
+
authored_by: "synthesized",
|
|
426
|
+
status: "pending",
|
|
427
|
+
shape: null,
|
|
428
|
+
dispatch_ids: f,
|
|
429
|
+
attempt_count: 0,
|
|
430
|
+
guard_result: a,
|
|
431
|
+
guard_output: s,
|
|
432
|
+
guard_ran_at: r,
|
|
433
|
+
blast_radius: [],
|
|
434
|
+
conflict: {
|
|
435
|
+
detected: !1,
|
|
436
|
+
competing_op: null,
|
|
437
|
+
op_key: null,
|
|
438
|
+
resolution: null
|
|
439
|
+
},
|
|
440
|
+
tokens_actual: null
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function xe(e, t) {
|
|
444
|
+
const n = {}, {
|
|
445
|
+
write_multiplier: o,
|
|
446
|
+
read_multiplier: i,
|
|
447
|
+
hit_probability: l
|
|
448
|
+
} = t;
|
|
449
|
+
for (const [f, a] of Object.entries(e))
|
|
450
|
+
a === null ? n[f] = null : n[f] = Math.round(a * ((1 - l) * o + l * i));
|
|
451
|
+
return n;
|
|
452
|
+
}
|
|
453
|
+
function Ie(e, t, n) {
|
|
454
|
+
const o = Array.from(e.keys()), i = {};
|
|
455
|
+
for (let l = 0; l < o.length; l++)
|
|
456
|
+
for (let f = l + 1; f < o.length; f++) {
|
|
457
|
+
const a = o[l], s = o[f];
|
|
458
|
+
if (a === void 0 || s === void 0)
|
|
459
|
+
continue;
|
|
460
|
+
const [r, c] = a < s ? [a, s] : [s, a], u = `${r}:${c}`, p = e.get(a) ?? [], m = e.get(s) ?? [], b = new Set(
|
|
461
|
+
p.map((w) => w.file).filter((w) => w !== null)
|
|
462
|
+
), v = new Set(
|
|
463
|
+
m.map((w) => w.file).filter((w) => w !== null)
|
|
464
|
+
), y = Array.from(b).filter((w) => v.has(w));
|
|
465
|
+
if (y.length === 0)
|
|
466
|
+
continue;
|
|
467
|
+
const k = t.get(a) ?? "pending", $ = t.get(s) ?? "pending", j = k === "complete" && $ === "complete";
|
|
468
|
+
let P = 0;
|
|
469
|
+
for (const w of y)
|
|
470
|
+
P += j ? n(w) : 0;
|
|
471
|
+
i[u] = P;
|
|
472
|
+
}
|
|
473
|
+
return i;
|
|
474
|
+
}
|
|
475
|
+
function ze(e) {
|
|
476
|
+
return (Array.isArray(e) ? e : Object.values(e)).map(
|
|
477
|
+
(n) => n.type === void 0 ? { ...n, type: "generative" } : n
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
function Ne(e, t) {
|
|
481
|
+
const n = (/* @__PURE__ */ new Date()).toISOString(), o = t.dispatchLog ?? e.dispatch_log, i = e.optimization.sentinel_fanout, l = we(e.optimization.b_per_tier, t.bPerTier), f = ke(
|
|
482
|
+
e.optimization.context_window_per_tier,
|
|
483
|
+
t.contextWindowPerTier
|
|
484
|
+
), a = xe(l, i), { waves: s } = $e(e.milestones), r = ze(e.operations), c = /* @__PURE__ */ new Map();
|
|
485
|
+
for (const _ of r) {
|
|
486
|
+
const d = c.get(_.milestone) ?? [];
|
|
487
|
+
d.push(_), c.set(_.milestone, d);
|
|
488
|
+
}
|
|
489
|
+
const u = /* @__PURE__ */ new Set();
|
|
490
|
+
for (const _ of r)
|
|
491
|
+
_.file && u.add(_.file), _.action === "move" && _.to_file && u.add(_.to_file);
|
|
492
|
+
const p = Z(Array.from(u), t), m = (_) => p.get(_) ?? 0, b = /* @__PURE__ */ new Map(), v = Array.from(s.entries()).sort((_, d) => _[1] - d[1] || _[0].localeCompare(d[0])).map(([_]) => _);
|
|
493
|
+
for (const _ of v) {
|
|
494
|
+
const d = e.milestones[_];
|
|
495
|
+
if (d === void 0)
|
|
496
|
+
continue;
|
|
497
|
+
const M = (c.get(_) ?? []).map((x) => x.id), T = d.depends_on.map(
|
|
498
|
+
(x) => b.get(x) ?? "pending"
|
|
499
|
+
), I = Ae(
|
|
500
|
+
_,
|
|
501
|
+
d,
|
|
502
|
+
M,
|
|
503
|
+
o,
|
|
504
|
+
T
|
|
505
|
+
);
|
|
506
|
+
b.set(_, I);
|
|
507
|
+
}
|
|
508
|
+
const y = {}, k = [];
|
|
509
|
+
for (const _ of v) {
|
|
510
|
+
const d = e.milestones[_];
|
|
511
|
+
if (d === void 0)
|
|
512
|
+
continue;
|
|
513
|
+
const M = s.get(_) ?? 0, T = c.get(_) ?? [], I = T.map((h) => h.id), x = b.get(_) ?? "pending", N = d.depends_on.map(
|
|
514
|
+
(h) => b.get(h) ?? "pending"
|
|
515
|
+
), re = d.depends_on.length === 0 || N.every((h) => h === "complete"), le = N.every((h) => h !== "failed"), ue = d.pending === null && re && le, E = ee(o, [
|
|
516
|
+
...I,
|
|
517
|
+
`${_}.guard`
|
|
518
|
+
]), ae = E.length > 0 ? E.map((h) => h.started_at).sort()[0] ?? null : null;
|
|
519
|
+
let F, q, B;
|
|
520
|
+
if (d.guard) {
|
|
521
|
+
const h = Oe(_, o);
|
|
522
|
+
F = h.guard_result, q = h.guard_output, B = h.completed_at;
|
|
523
|
+
} else
|
|
524
|
+
F = null, q = null, B = null;
|
|
525
|
+
const R = Se(T), K = R.reduce((h, A) => h + m(A), 0), W = T.map(
|
|
526
|
+
(h) => je(h, d.effort, o)
|
|
527
|
+
);
|
|
528
|
+
let z = null, G = 0, L = !1;
|
|
529
|
+
for (const h of W) {
|
|
530
|
+
if (h.ki_estimate === null) {
|
|
531
|
+
L = !0;
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
G += h.ki_estimate;
|
|
535
|
+
}
|
|
536
|
+
L || (z = G);
|
|
537
|
+
let V = null;
|
|
538
|
+
const Y = d.model;
|
|
539
|
+
if (Y !== null && z !== null) {
|
|
540
|
+
const h = a[Y] ?? null;
|
|
541
|
+
if (h !== null) {
|
|
542
|
+
const A = C(K);
|
|
543
|
+
V = h + A + z;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
let H = null;
|
|
547
|
+
const J = E.filter(
|
|
548
|
+
(h) => h.completed_at !== null && h.results.length > 0 && h.results.every(
|
|
549
|
+
(A) => A.status === "complete" || A.status === "skipped"
|
|
550
|
+
)
|
|
551
|
+
);
|
|
552
|
+
J.length > 0 && (H = J.reduce((h, A) => h + A.turns.reduce((fe, Q) => fe + Q.input_tokens + Q.output_tokens, 0), 0));
|
|
553
|
+
const ce = Te(
|
|
554
|
+
_,
|
|
555
|
+
d,
|
|
556
|
+
I,
|
|
557
|
+
o
|
|
558
|
+
);
|
|
559
|
+
k.push(...W, ce), y[_] = {
|
|
560
|
+
description: d.description,
|
|
561
|
+
...d.rationale !== void 0 ? { rationale: d.rationale } : {},
|
|
562
|
+
authored_by: d.authored_by,
|
|
563
|
+
pending: d.pending,
|
|
564
|
+
triggered_by: d.triggered_by,
|
|
565
|
+
phase: d.phase,
|
|
566
|
+
depends_on: d.depends_on,
|
|
567
|
+
agent: d.agent,
|
|
568
|
+
model: d.model,
|
|
569
|
+
effort: d.effort,
|
|
570
|
+
two_stage: d.two_stage,
|
|
571
|
+
read_only: d.read_only,
|
|
572
|
+
guard: d.guard,
|
|
573
|
+
context: `contexts/${_}.md`,
|
|
574
|
+
wave: M,
|
|
575
|
+
eligible: ue,
|
|
576
|
+
status: x,
|
|
577
|
+
started_at: ae,
|
|
578
|
+
completed_at: B,
|
|
579
|
+
guard_result: F,
|
|
580
|
+
guard_output: q,
|
|
581
|
+
artifacts: R,
|
|
582
|
+
si_bytes: K,
|
|
583
|
+
ki_estimate: z,
|
|
584
|
+
tokens_estimated: V,
|
|
585
|
+
tokens_actual: H
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
const $ = Ie(
|
|
589
|
+
c,
|
|
590
|
+
b,
|
|
591
|
+
m
|
|
592
|
+
), j = Pe(e, y), w = {
|
|
593
|
+
tokens_naive: (() => {
|
|
594
|
+
let _ = 0;
|
|
595
|
+
for (const d of Object.values(y))
|
|
596
|
+
if (d.eligible && d.status === "pending" && d.model !== null) {
|
|
597
|
+
const M = l[d.model] ?? t.bPerTier[d.model] ?? 0;
|
|
598
|
+
_ += M + (d.ki_estimate ?? 0);
|
|
599
|
+
}
|
|
600
|
+
return _;
|
|
601
|
+
})(),
|
|
602
|
+
sentinel_fanout: i,
|
|
603
|
+
context_window_override: e.optimization.context_window_override,
|
|
604
|
+
b_override: e.optimization.b_override,
|
|
605
|
+
b_per_tier: l,
|
|
606
|
+
b_eff_per_tier: a,
|
|
607
|
+
context_window_per_tier: f
|
|
608
|
+
}, D = {
|
|
609
|
+
snapshot_at: n,
|
|
610
|
+
snapshot_version: 1,
|
|
611
|
+
// callers may increment if persisting
|
|
612
|
+
plan: "",
|
|
613
|
+
// caller sets this from directory name
|
|
614
|
+
schema_version: e.schema_version,
|
|
615
|
+
plan_kind: e.plan_kind,
|
|
616
|
+
description: e.description,
|
|
617
|
+
problem: e.problem,
|
|
618
|
+
approach: e.approach,
|
|
619
|
+
executor: e.executor,
|
|
620
|
+
...e.executor_model !== void 0 ? { executor_model: e.executor_model } : {},
|
|
621
|
+
...e.executor_effort !== void 0 ? { executor_effort: e.executor_effort } : {},
|
|
622
|
+
phases: [...e.phases],
|
|
623
|
+
terminal: e.terminal,
|
|
624
|
+
...e.assumed_baseline !== void 0 ? { assumed_baseline: e.assumed_baseline } : {},
|
|
625
|
+
optimization: w,
|
|
626
|
+
milestones: y,
|
|
627
|
+
operations: k,
|
|
628
|
+
pairwise_overlap: $,
|
|
629
|
+
open_questions: j
|
|
630
|
+
};
|
|
631
|
+
return he(D), D;
|
|
632
|
+
}
|
|
633
|
+
function Pe(e, t) {
|
|
634
|
+
const n = [];
|
|
635
|
+
for (const [o, i] of Object.entries(t)) {
|
|
636
|
+
const l = e.milestones[o];
|
|
637
|
+
if (l === void 0 || l.pending === null)
|
|
638
|
+
continue;
|
|
639
|
+
const f = i.status === "pending-surfaced";
|
|
640
|
+
n.push({
|
|
641
|
+
id: `q:${o}`,
|
|
642
|
+
text: l.pending,
|
|
643
|
+
blocking: o,
|
|
644
|
+
surfaced: f,
|
|
645
|
+
// TODO: scan dispatch_log notes for the turn/dispatch where question appeared
|
|
646
|
+
raised_at_dispatch: null,
|
|
647
|
+
raised_at_turn: null,
|
|
648
|
+
answered: !1,
|
|
649
|
+
answer: null
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
return n;
|
|
653
|
+
}
|
|
654
|
+
function ne(e) {
|
|
655
|
+
return Object.keys(e.milestones).filter((t) => {
|
|
656
|
+
const n = e.milestones[t];
|
|
657
|
+
return n !== void 0 && n.eligible === !0 && n.status === "pending";
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
function Ee(e) {
|
|
661
|
+
if (e.length === 0 || e.every((t) => t.type === "tool-call"))
|
|
662
|
+
return "tool-call";
|
|
663
|
+
for (const t of e) {
|
|
664
|
+
if (t.type !== "generative" || !t.shape || t.shape.kind === null)
|
|
665
|
+
continue;
|
|
666
|
+
const n = t.shape.kind;
|
|
667
|
+
if (n === "function" || n === "interface" || n === "type" || n === "class" || n === "enum" || n === "const" || n === "script" || n === "config" || n === "env" || n === "schema" || n === "manifest")
|
|
668
|
+
return "code-config";
|
|
669
|
+
if (n === "doc")
|
|
670
|
+
return "doc";
|
|
671
|
+
if (n === "structured-output")
|
|
672
|
+
return "structured";
|
|
673
|
+
}
|
|
674
|
+
return "code-config";
|
|
675
|
+
}
|
|
676
|
+
function Fe(e) {
|
|
677
|
+
if (!e)
|
|
678
|
+
return "";
|
|
679
|
+
const t = e.indexOf(":");
|
|
680
|
+
return t >= 0 ? e.slice(t + 1) : e;
|
|
681
|
+
}
|
|
682
|
+
function qe(e, t, n) {
|
|
683
|
+
let o = !0;
|
|
684
|
+
const i = [];
|
|
685
|
+
for (const l of e) {
|
|
686
|
+
const f = t[l];
|
|
687
|
+
if (f === void 0)
|
|
688
|
+
continue;
|
|
689
|
+
const a = n.filter(
|
|
690
|
+
(r) => r.milestone === l && r.action !== "guard"
|
|
691
|
+
);
|
|
692
|
+
a.some((r) => r.type === "generative") && (o = !1), i.push(`## Milestone: ${l}`), i.push(f.description), f.rationale && i.push(`
|
|
693
|
+
*Rationale:* ${f.rationale}`), i.push(`
|
|
694
|
+
### Operations:`);
|
|
695
|
+
for (const r of a) {
|
|
696
|
+
const c = r.file ? ` ${r.file}` : "", u = r.symbol ? ` (${r.symbol})` : "";
|
|
697
|
+
if (i.push(`- [${r.id}] ${r.action}${c}${u}`), r.shape && r.shape.kind !== null) {
|
|
698
|
+
const p = r.shape;
|
|
699
|
+
if (p.kind === "doc")
|
|
700
|
+
i.push(` Description: ${p.description}`), i.push(` Objective: ${p.objective}`), p.required_sections && p.required_sections.length > 0 && i.push(
|
|
701
|
+
` Required sections: ${p.required_sections.join(", ")}`
|
|
702
|
+
);
|
|
703
|
+
else if (p.kind === "structured-output")
|
|
704
|
+
i.push(
|
|
705
|
+
` Schema:
|
|
706
|
+
` + JSON.stringify(p.schema, null, 2).split(`
|
|
707
|
+
`).map((m) => ` ${m}`).join(`
|
|
708
|
+
`)
|
|
709
|
+
);
|
|
710
|
+
else if ("ops" in p && Array.isArray(p.ops))
|
|
711
|
+
for (const m of p.ops) {
|
|
712
|
+
const b = m.to !== null ? ` → ${m.to}` : "", v = m.target !== null ? ` "${m.target}"` : "";
|
|
713
|
+
i.push(` - ${m.op}${v}${b}`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
const s = f.guard;
|
|
718
|
+
i.push(`
|
|
719
|
+
### Guard: ${s ?? "none"}`), i.push("");
|
|
720
|
+
}
|
|
721
|
+
return o ? null : i.join(`
|
|
722
|
+
`);
|
|
723
|
+
}
|
|
724
|
+
function oe(e, t, n) {
|
|
725
|
+
if (e === null)
|
|
726
|
+
return null;
|
|
727
|
+
const o = t.optimization.b_eff_per_tier[e];
|
|
728
|
+
if (o != null)
|
|
729
|
+
return o;
|
|
730
|
+
const i = t.optimization.b_per_tier[e];
|
|
731
|
+
if (i != null)
|
|
732
|
+
return i;
|
|
733
|
+
const l = n.bPerTier[e];
|
|
734
|
+
return l !== void 0 ? l : null;
|
|
735
|
+
}
|
|
736
|
+
function se(e, t, n) {
|
|
737
|
+
if (e === null)
|
|
738
|
+
return Number.POSITIVE_INFINITY;
|
|
739
|
+
const o = t.optimization.context_window_per_tier[e];
|
|
740
|
+
if (o !== void 0)
|
|
741
|
+
return o;
|
|
742
|
+
const i = n.contextWindowPerTier[e];
|
|
743
|
+
return i !== void 0 ? i : Number.POSITIVE_INFINITY;
|
|
744
|
+
}
|
|
745
|
+
function ie(e, t) {
|
|
746
|
+
const n = /* @__PURE__ */ new Set();
|
|
747
|
+
for (const o of e) {
|
|
748
|
+
const i = t.snapshot.milestones[o];
|
|
749
|
+
if (i !== void 0) {
|
|
750
|
+
n.add(i.context);
|
|
751
|
+
for (const l of i.read_only)
|
|
752
|
+
n.add(l);
|
|
753
|
+
for (const l of t.opsByMilestone.get(o) ?? [])
|
|
754
|
+
l.file && n.add(l.file);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return Array.from(n);
|
|
758
|
+
}
|
|
759
|
+
function X(e, t, n) {
|
|
760
|
+
const o = oe(t, n.snapshot, n.deps);
|
|
761
|
+
if (o === null)
|
|
762
|
+
return null;
|
|
763
|
+
const l = ie(e, n).reduce(
|
|
764
|
+
(s, r) => s + (n.sizeMap.get(r) ?? 0),
|
|
765
|
+
0
|
|
766
|
+
), f = C(l), a = e.reduce(
|
|
767
|
+
(s, r) => {
|
|
768
|
+
var c;
|
|
769
|
+
return s + (((c = n.snapshot.milestones[r]) == null ? void 0 : c.ki_estimate) ?? 0);
|
|
770
|
+
},
|
|
771
|
+
0
|
|
772
|
+
);
|
|
773
|
+
return o + f + a;
|
|
774
|
+
}
|
|
775
|
+
function Be(e, t, n) {
|
|
776
|
+
const o = se(t, n.snapshot, n.deps), i = [...e].sort((a, s) => {
|
|
777
|
+
var u, p;
|
|
778
|
+
const r = ((u = n.snapshot.milestones[a]) == null ? void 0 : u.ki_estimate) ?? 0, c = ((p = n.snapshot.milestones[s]) == null ? void 0 : p.ki_estimate) ?? 0;
|
|
779
|
+
return r - c || a.localeCompare(s);
|
|
780
|
+
}), l = [];
|
|
781
|
+
let f = [];
|
|
782
|
+
for (const a of i) {
|
|
783
|
+
const s = [...f, a], r = X(s, t, n);
|
|
784
|
+
r !== null && r > o && f.length > 0 ? (l.push(f), f = [a]) : f = s;
|
|
785
|
+
}
|
|
786
|
+
return f.length > 0 && l.push(f), l.filter((a) => {
|
|
787
|
+
const s = X(a, t, n);
|
|
788
|
+
return s === null || s <= o;
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
function Ce(e, t, n, o) {
|
|
792
|
+
const i = e[0] ?? "", l = o.snapshot.milestones[i], f = (l == null ? void 0 : l.effort) ?? null, a = [];
|
|
793
|
+
for (const k of e)
|
|
794
|
+
for (const $ of o.opsByMilestone.get(k) ?? [])
|
|
795
|
+
a.push($.id);
|
|
796
|
+
const s = ie(e, o), r = s.reduce(
|
|
797
|
+
(k, $) => k + (o.sizeMap.get($) ?? 0),
|
|
798
|
+
0
|
|
799
|
+
), c = oe(n, o.snapshot, o.deps), u = e.reduce(
|
|
800
|
+
(k, $) => {
|
|
801
|
+
var j;
|
|
802
|
+
return k + (((j = o.snapshot.milestones[$]) == null ? void 0 : j.ki_estimate) ?? 0);
|
|
803
|
+
},
|
|
804
|
+
0
|
|
805
|
+
), p = c !== null ? c + C(r) + u : null, m = se(n, o.snapshot, o.deps), b = p !== null ? p <= m : !0, v = Fe((l == null ? void 0 : l.agent) ?? null), y = qe(e, o.snapshot.milestones, o.snapshot.operations);
|
|
806
|
+
return {
|
|
807
|
+
id: `${i}.dispatch.${t}`,
|
|
808
|
+
milestones: e,
|
|
809
|
+
operations: a,
|
|
810
|
+
model: n,
|
|
811
|
+
effort: f,
|
|
812
|
+
two_stage: (l == null ? void 0 : l.two_stage) ?? !1,
|
|
813
|
+
provider: null,
|
|
814
|
+
agent_name: v,
|
|
815
|
+
mcp_servers: null,
|
|
816
|
+
resolved_max_tokens: null,
|
|
817
|
+
background: !0,
|
|
818
|
+
prompt: y,
|
|
819
|
+
context_files: s,
|
|
820
|
+
si_bytes: r,
|
|
821
|
+
tokens_estimated: p,
|
|
822
|
+
fits_context_window: b,
|
|
823
|
+
sentinel_role: null,
|
|
824
|
+
dispatch_log_id: null,
|
|
825
|
+
remote_task_id: null,
|
|
826
|
+
result: null,
|
|
827
|
+
status: "pending",
|
|
828
|
+
started_at: null,
|
|
829
|
+
completed_at: null,
|
|
830
|
+
tokens_actual: null
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
function Re(e, t) {
|
|
834
|
+
const n = ne(e);
|
|
835
|
+
if (n.length === 0)
|
|
836
|
+
return [];
|
|
837
|
+
const o = /* @__PURE__ */ new Map();
|
|
838
|
+
for (const u of e.operations) {
|
|
839
|
+
if (u.action === "guard")
|
|
840
|
+
continue;
|
|
841
|
+
const p = o.get(u.milestone) ?? [];
|
|
842
|
+
p.push(u), o.set(u.milestone, p);
|
|
843
|
+
}
|
|
844
|
+
const i = /* @__PURE__ */ new Map();
|
|
845
|
+
for (const u of n) {
|
|
846
|
+
const p = e.milestones[u];
|
|
847
|
+
if (p === void 0)
|
|
848
|
+
continue;
|
|
849
|
+
const m = Ee(o.get(u) ?? []), b = p.model ?? "_null", v = `${m}:${b}`, y = i.get(v) ?? [];
|
|
850
|
+
y.push(u), i.set(v, y);
|
|
851
|
+
}
|
|
852
|
+
const l = /* @__PURE__ */ new Set();
|
|
853
|
+
for (const u of n) {
|
|
854
|
+
const p = e.milestones[u];
|
|
855
|
+
if (p !== void 0) {
|
|
856
|
+
l.add(p.context);
|
|
857
|
+
for (const m of p.read_only)
|
|
858
|
+
l.add(m);
|
|
859
|
+
for (const m of o.get(u) ?? [])
|
|
860
|
+
m.file && l.add(m.file);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
const f = Z(Array.from(l), t), a = { snapshot: e, deps: t, sizeMap: f, opsByMilestone: o }, s = [];
|
|
864
|
+
let r = 0;
|
|
865
|
+
const c = Array.from(i.keys()).sort();
|
|
866
|
+
for (const u of c) {
|
|
867
|
+
const p = i.get(u);
|
|
868
|
+
if (p === void 0)
|
|
869
|
+
continue;
|
|
870
|
+
const m = u.slice(u.indexOf(":") + 1), b = m !== "_null" ? m : null, v = Be(p, b, a);
|
|
871
|
+
for (const y of v)
|
|
872
|
+
s.push(Ce(y, r++, b, a));
|
|
873
|
+
}
|
|
874
|
+
return s;
|
|
875
|
+
}
|
|
876
|
+
function Ke(e, t) {
|
|
877
|
+
let n = 0;
|
|
878
|
+
for (const o of ne(e)) {
|
|
879
|
+
const i = e.milestones[o];
|
|
880
|
+
if (i === void 0)
|
|
881
|
+
continue;
|
|
882
|
+
const l = De(i.model, e, t) ?? 0;
|
|
883
|
+
n += l + (i.ki_estimate ?? 0);
|
|
884
|
+
}
|
|
885
|
+
return n;
|
|
886
|
+
}
|
|
887
|
+
function De(e, t, n) {
|
|
888
|
+
if (e === null)
|
|
889
|
+
return null;
|
|
890
|
+
const o = t.optimization.b_per_tier[e];
|
|
891
|
+
if (o != null)
|
|
892
|
+
return o;
|
|
893
|
+
const i = n.bPerTier[e];
|
|
894
|
+
return i !== void 0 ? i : null;
|
|
895
|
+
}
|
|
896
|
+
export {
|
|
897
|
+
Ke as computeTokensNaive,
|
|
898
|
+
Re as optimize,
|
|
899
|
+
Ne as snapshot,
|
|
900
|
+
$e as topoSortMilestones
|
|
901
|
+
};
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { optimize, computeTokensNaive } from '../optimize.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DagSnapshot, DispatchUnit, IOptimizerDeps } from '@adhd/dispatch-base-spec';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compute the greedy dispatch plan for the current scheduling cycle.
|
|
5
|
+
*
|
|
6
|
+
* Input: DagSnapshot — fully computed from snapshot().
|
|
7
|
+
* Output: DispatchUnit[] — one unit per batch assignment. Never mixes
|
|
8
|
+
* shape.kind families or model tiers within one unit. Never contains a
|
|
9
|
+
* unit whose tokens_estimated exceeds the tier's context window.
|
|
10
|
+
*
|
|
11
|
+
* Does not mutate the input snapshot.
|
|
12
|
+
*/
|
|
13
|
+
export declare function optimize(snapshot: DagSnapshot, deps: IOptimizerDeps): DispatchUnit[];
|
|
14
|
+
/**
|
|
15
|
+
* Naive baseline (SCOPE.md §F4): one milestone = one agent call, no packing,
|
|
16
|
+
* no Sentinel-Fanout caching.
|
|
17
|
+
*
|
|
18
|
+
* tokens_naive = Σ (b_per_tier[model] + ki_estimate) for each packable milestone
|
|
19
|
+
*
|
|
20
|
+
* Deliberately uses the RAW b_per_tier (not b_eff_per_tier) — the point of
|
|
21
|
+
* this baseline is "what would it cost with zero optimization applied",
|
|
22
|
+
* which specifically means no caching benefit either.
|
|
23
|
+
*
|
|
24
|
+
* The optimizer-core.2 shape.ops entry says to "emit tokens_naive... into
|
|
25
|
+
* the snapshot's optimization block" — but SnapshotOptimization (types.ts)
|
|
26
|
+
* has no tokens_naive field, and optimize()'s return type is fixed at
|
|
27
|
+
* DispatchUnit[], so there's no type-safe way to attach it to the snapshot
|
|
28
|
+
* from inside this module without either mutating the input (breaking the
|
|
29
|
+
* "does not mutate its input" contract) or editing @adhd/dispatch-base-spec
|
|
30
|
+
* (outside this milestone's file scope). This named export is the type-safe
|
|
31
|
+
* alternative: the value is computed, testable, and available to any caller
|
|
32
|
+
* that wants "packed vs naive". Adding a `tokens_naive` field to
|
|
33
|
+
* SnapshotOptimization belongs to a future @adhd/dispatch-base-spec change, not
|
|
34
|
+
* this file.
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeTokensNaive(snapshot: DagSnapshot, deps: IOptimizerDeps): number;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IOptimizerDeps } from '@adhd/dispatch-base-spec';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert file bytes to an approximate token count.
|
|
5
|
+
* Source: SCOPE.md §C3 — byte-count is the right proxy (r>0.98, arxiv 2511.08066).
|
|
6
|
+
*/
|
|
7
|
+
export declare function siBytesAsTokens(bytes: number, filePath?: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* Batch-resolve file sizes via the injected deps.fileSizes callback.
|
|
10
|
+
*
|
|
11
|
+
* Graceful degradation: returns an empty map (every lookup then resolves to 0
|
|
12
|
+
* via `map.get(path) ?? 0` at the call site) when deps.fileSizes is undefined,
|
|
13
|
+
* the path list is empty, or the callback itself throws.
|
|
14
|
+
*/
|
|
15
|
+
export declare function lookupFileSizes(paths: string[], deps: IOptimizerDeps): Map<string, number>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { snapshot, topoSortMilestones } from '../snapshot.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DagJson, DagSnapshot, IOptimizerDeps, MilestoneDag } from '@adhd/dispatch-base-spec';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Topologically sort milestone slugs and assign wave numbers.
|
|
5
|
+
* Uses Kahn's algorithm (BFS) for O(V+E).
|
|
6
|
+
*
|
|
7
|
+
* Wave 0: nodes with empty depends_on.
|
|
8
|
+
* Wave N: 1 + max(wave of deps).
|
|
9
|
+
* Ties within a wave are broken by slug (lexicographic) for determinism.
|
|
10
|
+
*
|
|
11
|
+
* @throws {Error} if a cycle is detected, including the cycle path.
|
|
12
|
+
*/
|
|
13
|
+
export declare function topoSortMilestones(milestones: Record<string, MilestoneDag>): {
|
|
14
|
+
order: string[];
|
|
15
|
+
waves: Map<string, number>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Compute the fully-derived DagSnapshot from a dag.json document.
|
|
19
|
+
*
|
|
20
|
+
* Computation order (per SCOPE.md §N1):
|
|
21
|
+
* 1. Copy dag-level fields verbatim; resolve b_per_tier / context_window_per_tier
|
|
22
|
+
* cold-start defaults from deps.
|
|
23
|
+
* 2. Compute b_eff_per_tier.
|
|
24
|
+
* 3. Topological sort → assign wave numbers.
|
|
25
|
+
* 4. Per-milestone derived fields.
|
|
26
|
+
* 5. Per-operation derived fields.
|
|
27
|
+
* 6. pairwise_overlap.
|
|
28
|
+
* 7. open_questions.
|
|
29
|
+
*
|
|
30
|
+
* Does not mutate the input dag.
|
|
31
|
+
*
|
|
32
|
+
* @throws {Error} if a dependency cycle is detected, or if the computed snapshot
|
|
33
|
+
* fails structural validation (assertValidSnapshot).
|
|
34
|
+
*/
|
|
35
|
+
export declare function snapshot(dag: DagJson, deps: IOptimizerDeps): DagSnapshot;
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DagJson, DispatchLogEntry, IOptimizerDeps, MilestoneDag, OperationDag } from '@adhd/dispatch-base-spec';
|
|
2
|
+
|
|
3
|
+
/** Recommended cold-start defaults per SCOPE.md Open Decision #2. */
|
|
4
|
+
export declare function defaultDeps(overrides?: Partial<IOptimizerDeps>): IOptimizerDeps;
|
|
5
|
+
export declare function miniMilestone(overrides?: Partial<MilestoneDag>): MilestoneDag;
|
|
6
|
+
export declare function miniOp(overrides?: Partial<OperationDag>): OperationDag;
|
|
7
|
+
export declare function miniDag(overrides?: Partial<DagJson>): DagJson;
|
|
8
|
+
/**
|
|
9
|
+
* Recursively Object.freeze a value and everything reachable from it (own
|
|
10
|
+
* enumerable keys only, arrays included). Functions are left unfrozen-and-
|
|
11
|
+
* unrecursed — freezing them adds nothing and isn't needed to prove data
|
|
12
|
+
* non-mutation.
|
|
13
|
+
*
|
|
14
|
+
* Used to prove snapshot()/optimize()/computeTokensNaive() honor their "does
|
|
15
|
+
* not mutate its input" contract: ES module code runs in strict mode, so any
|
|
16
|
+
* in-place write to a frozen object throws a TypeError instead of silently
|
|
17
|
+
* no-oping — a mutation bug turns into a failing test, not a passing one.
|
|
18
|
+
*/
|
|
19
|
+
export declare function deepFreeze<T>(value: T, seen?: WeakSet<object>): T;
|
|
20
|
+
/** A dispatch_log entry recording a passed guard for `${slug}.guard`. */
|
|
21
|
+
export declare function passingGuardEntry(slug: string, overrides?: Partial<DispatchLogEntry>): DispatchLogEntry;
|