@adhd/dispatch-base-spec 0.1.0 → 0.1.2
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/CHANGELOG.md +32 -0
- package/index.d.ts +1 -1
- package/index.js +5 -5
- package/index.mjs +239 -224
- package/lib/types.d.ts +16 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
## 0.1.2 (2026-08-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### 🩹 Fixes
|
|
5
|
+
|
|
6
|
+
- **dispatch:** D-07 own-status eligibility guard (DEBT-DISPATCH-013) + formalize ICalibrationStore (DEBT-DISPATCH-018, BL-103)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### ❤️ Thank You
|
|
10
|
+
|
|
11
|
+
- pseudosky
|
|
12
|
+
|
|
13
|
+
## 0.1.1 (2026-08-07)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### 🚀 Features
|
|
17
|
+
|
|
18
|
+
- **dispatch-base-spec:** split DispatchUnit.prompt into systemPrompt/prompt, add execution_mode
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### 🩹 Fixes
|
|
22
|
+
|
|
23
|
+
- **dispatch-base-spec:** enforce DispatchLogEntry.provider enum in validateDagJson
|
|
24
|
+
|
|
25
|
+
- **apigen-cli:** restore 2768 files mass-deleted by 0117eb22 (BUG-APIGEN-052)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### ❤️ Thank You
|
|
29
|
+
|
|
30
|
+
- parity-harness-self-test
|
|
31
|
+
- pseudosky
|
|
32
|
+
|
|
1
33
|
## 0.0.6 (2026-07-25)
|
|
2
34
|
|
|
3
35
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { BlastRadiusEntry, CodeKind, Confidence, ConfigKind, CrossPlanDep, DagJson, DagSnapshot, DispatchKind, DispatchLogEntry, DispatchNote, DispatchResult, DispatchUnit, DispatchUnitStatus, EffortTier, GuardResult, IOptimizerDeps, KindFamily, KiSource, MilestoneDag, MilestoneGuardResult, MilestoneSnapshot, MilestoneStatus, ModelTier, OpenQuestion, OperationAction, OperationConflict, OperationDag, OperationSnapshot, OperationStatus, OperationType, OptimizationConfig, PairwiseOverlapMap, PlanKind, Provenance, ProviderConfig, ProviderType, RetryConfig, SentinelFanoutConfig, SentinelRole, Shape, ShapeCode, ShapeCodeSnapshot, ShapeConfig, ShapeConfigSnapshot, ShapeDoc, ShapeKind, ShapeNull, ShapeOpDag, ShapeOpSnapshot, ShapeOpType, ShapeSnapshot, ShapeStructuredOutput, SnapshotOptimization, Turn, ValidationError, ValidationResult, } from './lib/types.js';
|
|
1
|
+
export type { BlastRadiusEntry, CodeKind, Confidence, ConfigKind, CrossPlanDep, DagJson, DagSnapshot, DispatchExecutionMode, DispatchKind, DispatchLogEntry, DispatchNote, DispatchResult, DispatchUnit, DispatchUnitStatus, EffortTier, GuardResult, ICalibrationStore, IOptimizerDeps, KindFamily, KiSource, MilestoneDag, MilestoneGuardResult, MilestoneSnapshot, MilestoneStatus, ModelTier, OpenQuestion, OperationAction, OperationConflict, OperationDag, OperationSnapshot, OperationStatus, OperationType, OptimizationConfig, PairwiseOverlapMap, PlanKind, Provenance, ProviderConfig, ProviderType, RetryConfig, SentinelFanoutConfig, SentinelRole, Shape, ShapeCode, ShapeCodeSnapshot, ShapeConfig, ShapeConfigSnapshot, ShapeDoc, ShapeKind, ShapeNull, ShapeOpDag, ShapeOpSnapshot, ShapeOpType, ShapeSnapshot, ShapeStructuredOutput, SnapshotOptimization, Turn, ValidationError, ValidationResult, } from './lib/types.js';
|
|
2
2
|
export { isValidOpForKind, VALID_OPS_BY_KIND, WRITE_CLASS_ACTIONS, } from './lib/types.js';
|
|
3
3
|
export { assertValidDagJson, assertValidSnapshot, validateDagJson, validateSnapshot, } from './lib/validate.js';
|
|
4
4
|
export { migrateDag } from './lib/migrate.js';
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=new Set(["create","modify-signature","modify-body","add-export","remove-export","rename"]),x={function:new Set(["add-param","remove-param","rename-param","retype-param","change-param-optional","reorder-params","change-return"]),interface:new Set(["add-field","remove-field","rename-field","retype-field","change-field-optional","add-generic","remove-generic","constrain-generic","add-extends","remove-extends"]),type:new Set(["add-field","remove-field","retype-field"]),class:new Set(["add-field","remove-field","rename-field","retype-field","change-field-optional","add-param","add-generic","remove-generic","constrain-generic","add-extends","remove-extends"]),enum:new Set(["add-field","remove-field","rename-field"]),const:new Set(["add-var","remove-var","rename-var","change-default"]),config:new Set(["set-key","remove-key","rename-key","add-entry","remove-entry","update-entry","bump-version","update-checksum"]),env:new Set(["set-key","remove-key","rename-key"]),schema:new Set(["add-table","remove-table","add-column","remove-column","rename-column","retype-column","change-nullable","add-index","remove-index"]),manifest:new Set(["add-entry","remove-entry","bump-version"]),doc:new Set(["add-section","remove-section","rename-section","update-section"]),"structured-output":new Set([]),script:new Set(["add-param","remove-param","rename-param","retype-param","change-param-optional","reorder-params","change-return","add-field","remove-field","rename-field","retype-field","change-field-optional","add-generic","remove-generic","constrain-generic","add-extends","remove-extends","set-key","remove-key","rename-key","add-array-item","remove-array-item","add-var","remove-var","rename-var","change-default","add-section","remove-section","rename-section","update-section","add-table","remove-table","add-column","remove-column","rename-column","retype-column","change-nullable","add-index","remove-index","add-entry","remove-entry","update-entry","bump-version","update-checksum","add-export"])};function j(t,e){const i=x[t];return i?i.has(e):!1}const T=new Set(["pending","pending-surfaced","in_progress","complete","failed","skipped"]),q=new Set(["pending","in_progress","complete","failed","skipped"]),E=new Set(["automated","tool-call","generative"]),N=new Set(["function","interface","type","class","enum","const","script","config","env","schema","manifest","doc","structured-output"]);function f(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function d(t){return typeof t=="string"}function n(t,e,i){return{path:t,message:e,value:i}}function L(t){var l,y;const e=Object.keys(t),i=new Map,r=new Map;for(const s of e)i.set(s,0),r.set(s,[]);for(const s of e)for(const a of((l=t[s])==null?void 0:l.depends_on)??[])t[a]&&((y=r.get(a))==null||y.push(s),i.set(s,(i.get(s)??0)+1));const p=e.filter(s=>(i.get(s)??0)===0),c=new Set;for(;p.length>0;){const s=p.shift();if(s!==void 0){c.add(s);for(const a of r.get(s)??[]){const u=(i.get(a)??1)-1;i.set(a,u),u===0&&p.push(a)}}}return c.size!==e.length?e.filter(s=>!c.has(s)).map(s=>({slug:s})):null}function R(t,e){for(const i of t){if(!f(i))continue;const r=d(i.id)?i.id:"?",p=i.turns;if(!Array.isArray(p)){e.push(n(`dispatch_log[${r}].turns`,"must be an array",p));continue}for(let c=0;c<p.length;c++){const l=p[c],y=`dispatch_log[${r}].turns[${c}]`;if(!f(l)){e.push(n(y,"must be an object",l));continue}(typeof l.turn!="number"||!Number.isInteger(l.turn)||l.turn<1)&&e.push(n(`${y}.turn`,"must be a positive integer",l.turn)),typeof l.input_tokens!="number"&&e.push(n(`${y}.input_tokens`,"must be a number",l.input_tokens)),typeof l.output_tokens!="number"&&e.push(n(`${y}.output_tokens`,"must be a number",l.output_tokens)),d(l.t)||e.push(n(`${y}.t`,"must be a string",l.t));const s=l.model_calls;s!=null&&typeof s!="number"&&e.push(n(`${y}.model_calls`,"must be a number or null if present",s))}}}function O(t){const e=[];if(!f(t))return{valid:!1,errors:[n("","root must be an object")]};for(const c of["description","problem","approach","executor"]){const l=t[c];(!d(l)||l.trim()==="")&&e.push(n(c,"required string field missing/empty",l))}typeof t.schema_version!="number"&&e.push(n("schema_version","must be a number",t.schema_version));const i=t.plan_kind;i!=="brownfield"&&i!=="greenfield"&&e.push(n("plan_kind",'must be "brownfield" or "greenfield"',i)),Array.isArray(t.phases)?t.phases.length===0&&e.push(n("phases","must have at least one entry")):e.push(n("phases","must be an array",t.phases));const r=t.terminal;!d(r)&&!Array.isArray(r)&&e.push(n("terminal","must be a string or array",r)),Array.isArray(t.dispatch_log)?R(t.dispatch_log,e):e.push(n("dispatch_log","must be an array",t.dispatch_log)),f(t.optimization)||e.push(n("optimization","must be an object",t.optimization)),f(t.providers)||e.push(n("providers","must be an object",t.providers)),f(t.effort_max_tokens)||e.push(n("effort_max_tokens","must be an object",t.effort_max_tokens));const p=t.milestones;if(!f(p))e.push(n("milestones","must be an object",p));else{const c=Object.keys(p);c.length===0&&e.push(n("milestones","must have at least one entry"));const l=new Set(c);for(const u of c){const o=p[u];if(!f(o)){e.push(n(`milestones.${u}`,"must be an object",o));continue}if((!d(o.description)||o.description.trim()==="")&&e.push(n(`milestones.${u}.description`,"required string",o.description)),!Array.isArray(o.depends_on))e.push(n(`milestones.${u}.depends_on`,"must be an array",o.depends_on));else for(const _ of o.depends_on)d(_)?l.has(_)||e.push(n(`milestones.${u}.depends_on`,`unknown milestone "${_}"`)):e.push(n(`milestones.${u}.depends_on[]`,"must be a string",_));const b=o.phase;(!d(b)||b.trim()==="")&&e.push(n(`milestones.${u}.phase`,"required string",b)),(!d(o.authored_by)||o.authored_by.trim()==="")&&e.push(n(`milestones.${u}.authored_by`,"required string",o.authored_by));const m=o.model;m!=null&&!["Haiku","Sonnet","Opus"].includes(m)&&e.push(n(`milestones.${u}.model`,"invalid model tier",m));const h=o.effort;h!=null&&!["low","medium","high","xhigh","max"].includes(h)&&e.push(n(`milestones.${u}.effort`,"invalid effort tier",h)),o.two_stage!==void 0&&typeof o.two_stage!="boolean"&&e.push(n(`milestones.${u}.two_stage`,"must be a boolean",o.two_stage)),Array.isArray(o.read_only)||e.push(n(`milestones.${u}.read_only`,"must be an array",o.read_only))}const y=L(p);if(y)for(const{slug:u}of y)e.push(n(`milestones.${u}`,"dependency cycle detected"));if(d(r)&&!l.has(r))e.push(n("terminal",`unknown milestone "${r}"`));else if(Array.isArray(r))for(const u of r)l.has(u)||e.push(n("terminal[]",`unknown milestone "${u}"`));const s=t.operations,a=new Set;if(!Array.isArray(s)&&!f(s))e.push(n("operations","must be an array or object",s));else{const u=Array.isArray(s)?s:Object.values(s);for(const o of u){if(!f(o)){e.push(n("operations[]","must be an object",o));continue}const b=o.id;if(!d(b)){e.push(n("operations[?]","missing/invalid id",b));continue}const m=b;a.add(m);const h=o.milestone;d(h)?l.has(h)||e.push(n(`operations[${m}].milestone`,`unknown milestone "${h}"`)):e.push(n(`operations[${m}].milestone`,"required string",h));const _=o.type;d(_)&&!E.has(_)&&e.push(n(`operations[${m}].type`,"invalid type",_));const v=o.shape;if(f(v)){const g=v.kind;g!=null&&d(g)&&!N.has(g)&&e.push(n(`operations[${m}].shape.kind`,"invalid shape kind",g));const $=v.ops;if(Array.isArray($)&&d(g))for(let w=0;w<$.length;w++){const k=$[w];if(!f(k))continue;const A=k.op;d(A)&&!j(g,A)&&e.push(n(`operations[${m}].shape.ops[${w}]`,`op "${A}" not valid for kind "${g}"`))}}Array.isArray(o.depends_on)||e.push(n(`operations[${m}].depends_on`,"must be an array",o.depends_on))}for(const o of u){if(!f(o))continue;const b=o.id;if(!d(b))continue;const m=o.depends_on;if(Array.isArray(m))for(const h of m)d(h)&&!a.has(h)&&e.push(n(`operations[${b}].depends_on`,`unknown operation "${h}"`))}}}return{valid:e.length===0,errors:e}}function I(t){const e=[];if(!f(t))return{valid:!1,errors:[n("","root must be an object")]};for(const r of["snapshot_at","description"])d(t[r])||e.push(n(r,"required string field missing",t[r]));d(t.plan)||e.push(n("plan","required string",t.plan));const i=t.milestones;if(!f(i))e.push(n("milestones","must be an object",i));else{const r=Object.keys(i),p=new Set(r);for(const s of r){const a=i[s];if(!f(a)){e.push(n(`milestones.${s}`,"must be an object",a));continue}const u=a.eligible,o=a.pending;u===!0&&o!==null&&o!==void 0&&e.push(n(`milestones.${s}`,"D-07 violation: eligible=true but pending not null")),typeof u!="boolean"&&e.push(n(`milestones.${s}.eligible`,"must be boolean",u));const b=a.status;(!d(b)||!T.has(b))&&e.push(n(`milestones.${s}.status`,"invalid status",b));const m=a.wave;(typeof m!="number"||!Number.isInteger(m)||m<0)&&e.push(n(`milestones.${s}.wave`,"must be non-negative integer",m));const h=a.ki_estimate;h!=null&&typeof h!="number"&&e.push(n(`milestones.${s}.ki_estimate`,"must be number|null",h));for(const _ of["tokens_estimated","tokens_actual"]){const v=a[_];v!=null&&typeof v!="number"&&e.push(n(`milestones.${s}.${_}`,"must be number|null",v))}Array.isArray(a.artifacts)||e.push(n(`milestones.${s}.artifacts`,"must be an array",a.artifacts)),typeof a.si_bytes!="number"&&e.push(n(`milestones.${s}.si_bytes`,"must be a number",a.si_bytes))}const c=t.operations;if(!Array.isArray(c))e.push(n("operations","must be an array",c));else for(const s of c){if(!f(s))continue;const a=d(s.id)?s.id:"?",u=s.milestone;d(u)&&!p.has(u)&&e.push(n(`operations[${a}].milestone`,`unknown milestone "${u}"`));const o=s.status;(!d(o)||!q.has(o))&&e.push(n(`operations[${a}].status`,"invalid operation status",o)),Array.isArray(s.dispatch_ids)||e.push(n(`operations[${a}].dispatch_ids`,"must be an array",s.dispatch_ids)),typeof s.attempt_count!="number"&&e.push(n(`operations[${a}].attempt_count`,"must be a number",s.attempt_count)),Array.isArray(s.blast_radius)||e.push(n(`operations[${a}].blast_radius`,"must be an array",s.blast_radius))}const l=t.open_questions;if(!Array.isArray(l))e.push(n("open_questions","must be an array",l));else for(const s of l){if(!f(s))continue;const a=s.blocking;(!d(a)||!p.has(a))&&e.push(n("open_questions",`unknown blocking milestone "${a}"`)),typeof s.surfaced!="boolean"&&e.push(n(`open_questions[${s.id}]`,"surfaced must be boolean",s.surfaced)),typeof s.answered!="boolean"&&e.push(n(`open_questions[${s.id}]`,"answered must be boolean",s.answered))}const y=t.dispatch_units;if(y!==void 0)if(!Array.isArray(y))e.push(n("dispatch_units","must be an array if present",y));else for(const s of y){if(!f(s))continue;const a=s.fits_context_window;typeof a!="boolean"&&e.push(n(`dispatch_units[${s.id}]`,"fits_context_window must be boolean",a));const u=s.milestones;if(Array.isArray(u))for(const o of u)d(o)&&!p.has(o)&&e.push(n(`dispatch_units[${s.id}].milestones`,`unknown milestone "${o}"`))}f(t.pairwise_overlap)||e.push(n("pairwise_overlap","must be an object",t.pairwise_overlap))}return{valid:e.length===0,errors:e}}function K(t){const e=O(t);if(!e.valid)throw new Error(`DagJson validation failed:
|
|
2
|
-
${e.errors.map(
|
|
3
|
-
`)}`)}function
|
|
4
|
-
${e.errors.map(
|
|
5
|
-
`)}`)}const S=[{from:2,to:3,apply:t=>{!t.milestones&&t.nodes&&(t.milestones=t.nodes,delete t.nodes);const e=t.operations;e&&typeof e=="object"&&!Array.isArray(e)&&(t.operations=Object.values(e))}},{from:3,to:4,apply:t=>{(!t.providers||Object.keys(t.providers).length===0)&&(t.providers={Haiku:{type:"claudecli",model_id:"claude-haiku-4-5",env_secret:null,base_url:null,timeout_ms:6e4,retry_config:{retries:3,min_timeout:1e3,max_timeout:3e4,factor:2}},Sonnet:{type:"claudecli",model_id:"claude-sonnet-4-5",env_secret:null,base_url:null,timeout_ms:12e4,retry_config:{retries:3,min_timeout:1e3,max_timeout:3e4,factor:2}},Opus:{type:"claudecli",model_id:"claude-opus-4-5",env_secret:null,base_url:null,timeout_ms:3e5,retry_config:{retries:3,min_timeout:1e3,max_timeout:3e4,factor:2}}}),(!t.effort_max_tokens||Object.keys(t.effort_max_tokens).length===0)&&(t.effort_max_tokens={low:1024,medium:4096,high:8192,xhigh:16384,max:32768}),t.optimization||(t.optimization={sentinel_fanout:{enabled:!0,write_multiplier:1.25,read_multiplier:.1,hit_probability:.9},b_per_tier:{Haiku:8e3,Sonnet:15e3,Opus:27e3},context_window_per_tier:{Haiku:16e3,Sonnet:16e3,Opus:32e3},context_window_override:null,b_override:null});let e=[];Array.isArray(t.operations)?e=t.operations:t.operations&&typeof t.operations=="object"&&(e=Object.values(t.operations));for(const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=new Set(["create","modify-signature","modify-body","add-export","remove-export","rename"]),x={function:new Set(["add-param","remove-param","rename-param","retype-param","change-param-optional","reorder-params","change-return"]),interface:new Set(["add-field","remove-field","rename-field","retype-field","change-field-optional","add-generic","remove-generic","constrain-generic","add-extends","remove-extends"]),type:new Set(["add-field","remove-field","retype-field"]),class:new Set(["add-field","remove-field","rename-field","retype-field","change-field-optional","add-param","add-generic","remove-generic","constrain-generic","add-extends","remove-extends"]),enum:new Set(["add-field","remove-field","rename-field"]),const:new Set(["add-var","remove-var","rename-var","change-default"]),config:new Set(["set-key","remove-key","rename-key","add-entry","remove-entry","update-entry","bump-version","update-checksum"]),env:new Set(["set-key","remove-key","rename-key"]),schema:new Set(["add-table","remove-table","add-column","remove-column","rename-column","retype-column","change-nullable","add-index","remove-index"]),manifest:new Set(["add-entry","remove-entry","bump-version"]),doc:new Set(["add-section","remove-section","rename-section","update-section"]),"structured-output":new Set([]),script:new Set(["add-param","remove-param","rename-param","retype-param","change-param-optional","reorder-params","change-return","add-field","remove-field","rename-field","retype-field","change-field-optional","add-generic","remove-generic","constrain-generic","add-extends","remove-extends","set-key","remove-key","rename-key","add-array-item","remove-array-item","add-var","remove-var","rename-var","change-default","add-section","remove-section","rename-section","update-section","add-table","remove-table","add-column","remove-column","rename-column","retype-column","change-nullable","add-index","remove-index","add-entry","remove-entry","update-entry","bump-version","update-checksum","add-export"])};function j(t,e){const r=x[t];return r?r.has(e):!1}const T=new Set(["pending","pending-surfaced","in_progress","complete","failed","skipped"]),q=new Set(["pending","in_progress","complete","failed","skipped"]),E=new Set(["automated","tool-call","generative"]),L=new Set(["anthropic","openai","deepseek","google","local","claudecli","teammate"]),N=new Set(["function","interface","type","class","enum","const","script","config","env","schema","manifest","doc","structured-output"]);function h(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function l(t){return typeof t=="string"}function n(t,e,r){return{path:t,message:e,value:r}}function R(t){var c,d;const e=Object.keys(t),r=new Map,a=new Map;for(const s of e)r.set(s,0),a.set(s,[]);for(const s of e)for(const i of((c=t[s])==null?void 0:c.depends_on)??[])t[i]&&((d=a.get(i))==null||d.push(s),r.set(s,(r.get(s)??0)+1));const p=e.filter(s=>(r.get(s)??0)===0),m=new Set;for(;p.length>0;){const s=p.shift();if(s!==void 0){m.add(s);for(const i of a.get(s)??[]){const u=(r.get(i)??1)-1;r.set(i,u),u===0&&p.push(i)}}}return m.size!==e.length?e.filter(s=>!m.has(s)).map(s=>({slug:s})):null}function V(t,e){for(const r of t){if(!h(r))continue;const a=l(r.id)?r.id:"?",p=r.provider;(!l(p)||!L.has(p))&&e.push(n(`dispatch_log[${a}].provider`,"invalid provider",p));const m=r.turns;if(!Array.isArray(m)){e.push(n(`dispatch_log[${a}].turns`,"must be an array",m));continue}for(let c=0;c<m.length;c++){const d=m[c],s=`dispatch_log[${a}].turns[${c}]`;if(!h(d)){e.push(n(s,"must be an object",d));continue}(typeof d.turn!="number"||!Number.isInteger(d.turn)||d.turn<1)&&e.push(n(`${s}.turn`,"must be a positive integer",d.turn)),typeof d.input_tokens!="number"&&e.push(n(`${s}.input_tokens`,"must be a number",d.input_tokens)),typeof d.output_tokens!="number"&&e.push(n(`${s}.output_tokens`,"must be a number",d.output_tokens)),l(d.t)||e.push(n(`${s}.t`,"must be a string",d.t));const i=d.model_calls;i!=null&&typeof i!="number"&&e.push(n(`${s}.model_calls`,"must be a number or null if present",i))}}}function O(t){const e=[];if(!h(t))return{valid:!1,errors:[n("","root must be an object")]};for(const m of["description","problem","approach","executor"]){const c=t[m];(!l(c)||c.trim()==="")&&e.push(n(m,"required string field missing/empty",c))}typeof t.schema_version!="number"&&e.push(n("schema_version","must be a number",t.schema_version));const r=t.plan_kind;r!=="brownfield"&&r!=="greenfield"&&e.push(n("plan_kind",'must be "brownfield" or "greenfield"',r)),Array.isArray(t.phases)?t.phases.length===0&&e.push(n("phases","must have at least one entry")):e.push(n("phases","must be an array",t.phases));const a=t.terminal;!l(a)&&!Array.isArray(a)&&e.push(n("terminal","must be a string or array",a)),Array.isArray(t.dispatch_log)?V(t.dispatch_log,e):e.push(n("dispatch_log","must be an array",t.dispatch_log)),h(t.optimization)||e.push(n("optimization","must be an object",t.optimization)),h(t.providers)||e.push(n("providers","must be an object",t.providers)),h(t.effort_max_tokens)||e.push(n("effort_max_tokens","must be an object",t.effort_max_tokens));const p=t.milestones;if(!h(p))e.push(n("milestones","must be an object",p));else{const m=Object.keys(p);m.length===0&&e.push(n("milestones","must have at least one entry"));const c=new Set(m);for(const u of m){const o=p[u];if(!h(o)){e.push(n(`milestones.${u}`,"must be an object",o));continue}if((!l(o.description)||o.description.trim()==="")&&e.push(n(`milestones.${u}.description`,"required string",o.description)),!Array.isArray(o.depends_on))e.push(n(`milestones.${u}.depends_on`,"must be an array",o.depends_on));else for(const _ of o.depends_on)l(_)?c.has(_)||e.push(n(`milestones.${u}.depends_on`,`unknown milestone "${_}"`)):e.push(n(`milestones.${u}.depends_on[]`,"must be a string",_));const b=o.phase;(!l(b)||b.trim()==="")&&e.push(n(`milestones.${u}.phase`,"required string",b)),(!l(o.authored_by)||o.authored_by.trim()==="")&&e.push(n(`milestones.${u}.authored_by`,"required string",o.authored_by));const f=o.model;f!=null&&!["Haiku","Sonnet","Opus"].includes(f)&&e.push(n(`milestones.${u}.model`,"invalid model tier",f));const y=o.effort;y!=null&&!["low","medium","high","xhigh","max"].includes(y)&&e.push(n(`milestones.${u}.effort`,"invalid effort tier",y)),o.two_stage!==void 0&&typeof o.two_stage!="boolean"&&e.push(n(`milestones.${u}.two_stage`,"must be a boolean",o.two_stage)),Array.isArray(o.read_only)||e.push(n(`milestones.${u}.read_only`,"must be an array",o.read_only))}const d=R(p);if(d)for(const{slug:u}of d)e.push(n(`milestones.${u}`,"dependency cycle detected"));if(l(a)&&!c.has(a))e.push(n("terminal",`unknown milestone "${a}"`));else if(Array.isArray(a))for(const u of a)c.has(u)||e.push(n("terminal[]",`unknown milestone "${u}"`));const s=t.operations,i=new Set;if(!Array.isArray(s)&&!h(s))e.push(n("operations","must be an array or object",s));else{const u=Array.isArray(s)?s:Object.values(s);for(const o of u){if(!h(o)){e.push(n("operations[]","must be an object",o));continue}const b=o.id;if(!l(b)){e.push(n("operations[?]","missing/invalid id",b));continue}const f=b;i.add(f);const y=o.milestone;l(y)?c.has(y)||e.push(n(`operations[${f}].milestone`,`unknown milestone "${y}"`)):e.push(n(`operations[${f}].milestone`,"required string",y));const _=o.type;l(_)&&!E.has(_)&&e.push(n(`operations[${f}].type`,"invalid type",_));const v=o.shape;if(h(v)){const g=v.kind;g!=null&&l(g)&&!N.has(g)&&e.push(n(`operations[${f}].shape.kind`,"invalid shape kind",g));const $=v.ops;if(Array.isArray($)&&l(g))for(let w=0;w<$.length;w++){const k=$[w];if(!h(k))continue;const A=k.op;l(A)&&!j(g,A)&&e.push(n(`operations[${f}].shape.ops[${w}]`,`op "${A}" not valid for kind "${g}"`))}}Array.isArray(o.depends_on)||e.push(n(`operations[${f}].depends_on`,"must be an array",o.depends_on))}for(const o of u){if(!h(o))continue;const b=o.id;if(!l(b))continue;const f=o.depends_on;if(Array.isArray(f))for(const y of f)l(y)&&!i.has(y)&&e.push(n(`operations[${b}].depends_on`,`unknown operation "${y}"`))}}}return{valid:e.length===0,errors:e}}function I(t){const e=[];if(!h(t))return{valid:!1,errors:[n("","root must be an object")]};for(const a of["snapshot_at","description"])l(t[a])||e.push(n(a,"required string field missing",t[a]));l(t.plan)||e.push(n("plan","required string",t.plan));const r=t.milestones;if(!h(r))e.push(n("milestones","must be an object",r));else{const a=Object.keys(r),p=new Set(a);for(const s of a){const i=r[s];if(!h(i)){e.push(n(`milestones.${s}`,"must be an object",i));continue}const u=i.eligible,o=i.pending;u===!0&&o!==null&&o!==void 0&&e.push(n(`milestones.${s}`,"D-07 violation: eligible=true but pending not null")),typeof u!="boolean"&&e.push(n(`milestones.${s}.eligible`,"must be boolean",u));const b=i.status;(!l(b)||!T.has(b))&&e.push(n(`milestones.${s}.status`,"invalid status",b)),u===!0&&b==="complete"&&e.push(n(`milestones.${s}`,"D-07 violation: eligible=true but status is complete"));const f=i.wave;(typeof f!="number"||!Number.isInteger(f)||f<0)&&e.push(n(`milestones.${s}.wave`,"must be non-negative integer",f));const y=i.ki_estimate;y!=null&&typeof y!="number"&&e.push(n(`milestones.${s}.ki_estimate`,"must be number|null",y));for(const _ of["tokens_estimated","tokens_actual"]){const v=i[_];v!=null&&typeof v!="number"&&e.push(n(`milestones.${s}.${_}`,"must be number|null",v))}Array.isArray(i.artifacts)||e.push(n(`milestones.${s}.artifacts`,"must be an array",i.artifacts)),typeof i.si_bytes!="number"&&e.push(n(`milestones.${s}.si_bytes`,"must be a number",i.si_bytes))}const m=t.operations;if(!Array.isArray(m))e.push(n("operations","must be an array",m));else for(const s of m){if(!h(s))continue;const i=l(s.id)?s.id:"?",u=s.milestone;l(u)&&!p.has(u)&&e.push(n(`operations[${i}].milestone`,`unknown milestone "${u}"`));const o=s.status;(!l(o)||!q.has(o))&&e.push(n(`operations[${i}].status`,"invalid operation status",o)),Array.isArray(s.dispatch_ids)||e.push(n(`operations[${i}].dispatch_ids`,"must be an array",s.dispatch_ids)),typeof s.attempt_count!="number"&&e.push(n(`operations[${i}].attempt_count`,"must be a number",s.attempt_count)),Array.isArray(s.blast_radius)||e.push(n(`operations[${i}].blast_radius`,"must be an array",s.blast_radius))}const c=t.open_questions;if(!Array.isArray(c))e.push(n("open_questions","must be an array",c));else for(const s of c){if(!h(s))continue;const i=s.blocking;(!l(i)||!p.has(i))&&e.push(n("open_questions",`unknown blocking milestone "${i}"`)),typeof s.surfaced!="boolean"&&e.push(n(`open_questions[${s.id}]`,"surfaced must be boolean",s.surfaced)),typeof s.answered!="boolean"&&e.push(n(`open_questions[${s.id}]`,"answered must be boolean",s.answered))}const d=t.dispatch_units;if(d!==void 0)if(!Array.isArray(d))e.push(n("dispatch_units","must be an array if present",d));else for(const s of d){if(!h(s))continue;const i=s.fits_context_window;typeof i!="boolean"&&e.push(n(`dispatch_units[${s.id}]`,"fits_context_window must be boolean",i));const u=s.milestones;if(Array.isArray(u))for(const o of u)l(o)&&!p.has(o)&&e.push(n(`dispatch_units[${s.id}].milestones`,`unknown milestone "${o}"`))}h(t.pairwise_overlap)||e.push(n("pairwise_overlap","must be an object",t.pairwise_overlap))}return{valid:e.length===0,errors:e}}function P(t){const e=O(t);if(!e.valid)throw new Error(`DagJson validation failed:
|
|
2
|
+
${e.errors.map(r=>` ${r.path}: ${r.message}`).join(`
|
|
3
|
+
`)}`)}function K(t){const e=I(t);if(!e.valid)throw new Error(`Snapshot validation failed:
|
|
4
|
+
${e.errors.map(r=>` ${r.path}: ${r.message}`).join(`
|
|
5
|
+
`)}`)}const S=[{from:2,to:3,apply:t=>{!t.milestones&&t.nodes&&(t.milestones=t.nodes,delete t.nodes);const e=t.operations;e&&typeof e=="object"&&!Array.isArray(e)&&(t.operations=Object.values(e))}},{from:3,to:4,apply:t=>{(!t.providers||Object.keys(t.providers).length===0)&&(t.providers={Haiku:{type:"claudecli",model_id:"claude-haiku-4-5",env_secret:null,base_url:null,timeout_ms:6e4,retry_config:{retries:3,min_timeout:1e3,max_timeout:3e4,factor:2}},Sonnet:{type:"claudecli",model_id:"claude-sonnet-4-5",env_secret:null,base_url:null,timeout_ms:12e4,retry_config:{retries:3,min_timeout:1e3,max_timeout:3e4,factor:2}},Opus:{type:"claudecli",model_id:"claude-opus-4-5",env_secret:null,base_url:null,timeout_ms:3e5,retry_config:{retries:3,min_timeout:1e3,max_timeout:3e4,factor:2}}}),(!t.effort_max_tokens||Object.keys(t.effort_max_tokens).length===0)&&(t.effort_max_tokens={low:1024,medium:4096,high:8192,xhigh:16384,max:32768}),t.optimization||(t.optimization={sentinel_fanout:{enabled:!0,write_multiplier:1.25,read_multiplier:.1,hit_probability:.9},b_per_tier:{Haiku:8e3,Sonnet:15e3,Opus:27e3},context_window_per_tier:{Haiku:16e3,Sonnet:16e3,Opus:32e3},context_window_override:null,b_override:null});let e=[];Array.isArray(t.operations)?e=t.operations:t.operations&&typeof t.operations=="object"&&(e=Object.values(t.operations));for(const r of e)if(typeof r=="object"&&r!==null){const a=r;a.type===void 0&&(a.type="generative"),a.criteria===void 0&&(a.criteria=[]),a.tool===void 0&&(a.tool=null),a.args===void 0&&(a.args=null)}}}];function z(t,e,r){if(t===e)return;let a=t;for(const p of[...S].sort((m,c)=>m.from-c.from))if(p.from===a&&(p.apply(r),a=p.to,a===e)){r.schema_version=e;return}throw new Error(`migrateDag: no path from v${t} to v${e}. Available: [${S.map(p=>`v${p.from}→v${p.to}`).join(", ")}]`)}exports.VALID_OPS_BY_KIND=x;exports.WRITE_CLASS_ACTIONS=D;exports.assertValidDagJson=P;exports.assertValidSnapshot=K;exports.isValidOpForKind=j;exports.migrateDag=z;exports.validateDagJson=O;exports.validateSnapshot=I;
|
package/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const z = /* @__PURE__ */ new Set([
|
|
2
2
|
"create",
|
|
3
3
|
"modify-signature",
|
|
4
4
|
"modify-body",
|
|
@@ -127,8 +127,8 @@ const R = /* @__PURE__ */ new Set([
|
|
|
127
127
|
])
|
|
128
128
|
};
|
|
129
129
|
function j(t, e) {
|
|
130
|
-
const
|
|
131
|
-
return
|
|
130
|
+
const r = x[t];
|
|
131
|
+
return r ? r.has(e) : !1;
|
|
132
132
|
}
|
|
133
133
|
const O = /* @__PURE__ */ new Set([
|
|
134
134
|
"pending",
|
|
@@ -143,7 +143,15 @@ const O = /* @__PURE__ */ new Set([
|
|
|
143
143
|
"complete",
|
|
144
144
|
"failed",
|
|
145
145
|
"skipped"
|
|
146
|
-
]),
|
|
146
|
+
]), D = /* @__PURE__ */ new Set(["automated", "tool-call", "generative"]), q = /* @__PURE__ */ new Set([
|
|
147
|
+
"anthropic",
|
|
148
|
+
"openai",
|
|
149
|
+
"deepseek",
|
|
150
|
+
"google",
|
|
151
|
+
"local",
|
|
152
|
+
"claudecli",
|
|
153
|
+
"teammate"
|
|
154
|
+
]), E = /* @__PURE__ */ new Set([
|
|
147
155
|
"function",
|
|
148
156
|
"interface",
|
|
149
157
|
"type",
|
|
@@ -158,227 +166,229 @@ const O = /* @__PURE__ */ new Set([
|
|
|
158
166
|
"doc",
|
|
159
167
|
"structured-output"
|
|
160
168
|
]);
|
|
161
|
-
function
|
|
169
|
+
function h(t) {
|
|
162
170
|
return typeof t == "object" && t !== null && !Array.isArray(t);
|
|
163
171
|
}
|
|
164
|
-
function
|
|
172
|
+
function l(t) {
|
|
165
173
|
return typeof t == "string";
|
|
166
174
|
}
|
|
167
|
-
function n(t, e,
|
|
168
|
-
return { path: t, message: e, value:
|
|
175
|
+
function n(t, e, r) {
|
|
176
|
+
return { path: t, message: e, value: r };
|
|
169
177
|
}
|
|
170
178
|
function T(t) {
|
|
171
|
-
var
|
|
172
|
-
const e = Object.keys(t),
|
|
173
|
-
for (const
|
|
174
|
-
|
|
175
|
-
for (const
|
|
176
|
-
for (const
|
|
177
|
-
t[
|
|
178
|
-
const p = e.filter((
|
|
179
|
+
var d, c;
|
|
180
|
+
const e = Object.keys(t), r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const o of e)
|
|
182
|
+
r.set(o, 0), a.set(o, []);
|
|
183
|
+
for (const o of e)
|
|
184
|
+
for (const i of ((d = t[o]) == null ? void 0 : d.depends_on) ?? [])
|
|
185
|
+
t[i] && ((c = a.get(i)) == null || c.push(o), r.set(o, (r.get(o) ?? 0) + 1));
|
|
186
|
+
const p = e.filter((o) => (r.get(o) ?? 0) === 0), m = /* @__PURE__ */ new Set();
|
|
179
187
|
for (; p.length > 0; ) {
|
|
180
|
-
const
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
for (const
|
|
184
|
-
const u = (
|
|
185
|
-
|
|
188
|
+
const o = p.shift();
|
|
189
|
+
if (o !== void 0) {
|
|
190
|
+
m.add(o);
|
|
191
|
+
for (const i of a.get(o) ?? []) {
|
|
192
|
+
const u = (r.get(i) ?? 1) - 1;
|
|
193
|
+
r.set(i, u), u === 0 && p.push(i);
|
|
186
194
|
}
|
|
187
195
|
}
|
|
188
196
|
}
|
|
189
|
-
return
|
|
197
|
+
return m.size !== e.length ? e.filter((o) => !m.has(o)).map((o) => ({ slug: o })) : null;
|
|
190
198
|
}
|
|
191
|
-
function
|
|
192
|
-
for (const
|
|
193
|
-
if (!
|
|
199
|
+
function R(t, e) {
|
|
200
|
+
for (const r of t) {
|
|
201
|
+
if (!h(r))
|
|
194
202
|
continue;
|
|
195
|
-
const
|
|
196
|
-
|
|
203
|
+
const a = l(r.id) ? r.id : "?", p = r.provider;
|
|
204
|
+
(!l(p) || !q.has(p)) && e.push(n(`dispatch_log[${a}].provider`, "invalid provider", p));
|
|
205
|
+
const m = r.turns;
|
|
206
|
+
if (!Array.isArray(m)) {
|
|
197
207
|
e.push(
|
|
198
|
-
n(`dispatch_log[${
|
|
208
|
+
n(`dispatch_log[${a}].turns`, "must be an array", m)
|
|
199
209
|
);
|
|
200
210
|
continue;
|
|
201
211
|
}
|
|
202
|
-
for (let d = 0; d <
|
|
203
|
-
const
|
|
204
|
-
if (!
|
|
205
|
-
e.push(n(
|
|
212
|
+
for (let d = 0; d < m.length; d++) {
|
|
213
|
+
const c = m[d], o = `dispatch_log[${a}].turns[${d}]`;
|
|
214
|
+
if (!h(c)) {
|
|
215
|
+
e.push(n(o, "must be an object", c));
|
|
206
216
|
continue;
|
|
207
217
|
}
|
|
208
|
-
(typeof
|
|
209
|
-
n(`${
|
|
210
|
-
), typeof
|
|
211
|
-
n(`${
|
|
212
|
-
), c
|
|
213
|
-
const
|
|
214
|
-
|
|
218
|
+
(typeof c.turn != "number" || !Number.isInteger(c.turn) || c.turn < 1) && e.push(n(`${o}.turn`, "must be a positive integer", c.turn)), typeof c.input_tokens != "number" && e.push(
|
|
219
|
+
n(`${o}.input_tokens`, "must be a number", c.input_tokens)
|
|
220
|
+
), typeof c.output_tokens != "number" && e.push(
|
|
221
|
+
n(`${o}.output_tokens`, "must be a number", c.output_tokens)
|
|
222
|
+
), l(c.t) || e.push(n(`${o}.t`, "must be a string", c.t));
|
|
223
|
+
const i = c.model_calls;
|
|
224
|
+
i != null && typeof i != "number" && e.push(
|
|
215
225
|
n(
|
|
216
|
-
`${
|
|
226
|
+
`${o}.model_calls`,
|
|
217
227
|
"must be a number or null if present",
|
|
218
|
-
|
|
228
|
+
i
|
|
219
229
|
)
|
|
220
230
|
);
|
|
221
231
|
}
|
|
222
232
|
}
|
|
223
233
|
}
|
|
224
|
-
function
|
|
234
|
+
function L(t) {
|
|
225
235
|
const e = [];
|
|
226
|
-
if (!
|
|
236
|
+
if (!h(t))
|
|
227
237
|
return { valid: !1, errors: [n("", "root must be an object")] };
|
|
228
|
-
for (const
|
|
229
|
-
const
|
|
230
|
-
(!
|
|
238
|
+
for (const m of ["description", "problem", "approach", "executor"]) {
|
|
239
|
+
const d = t[m];
|
|
240
|
+
(!l(d) || d.trim() === "") && e.push(n(m, "required string field missing/empty", d));
|
|
231
241
|
}
|
|
232
242
|
typeof t.schema_version != "number" && e.push(
|
|
233
243
|
n("schema_version", "must be a number", t.schema_version)
|
|
234
244
|
);
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
!
|
|
245
|
+
const r = t.plan_kind;
|
|
246
|
+
r !== "brownfield" && r !== "greenfield" && e.push(n("plan_kind", 'must be "brownfield" or "greenfield"', r)), Array.isArray(t.phases) ? t.phases.length === 0 && e.push(n("phases", "must have at least one entry")) : e.push(n("phases", "must be an array", t.phases));
|
|
247
|
+
const a = t.terminal;
|
|
248
|
+
!l(a) && !Array.isArray(a) && e.push(n("terminal", "must be a string or array", a)), Array.isArray(t.dispatch_log) ? R(t.dispatch_log, e) : e.push(n("dispatch_log", "must be an array", t.dispatch_log)), h(t.optimization) || e.push(n("optimization", "must be an object", t.optimization)), h(t.providers) || e.push(n("providers", "must be an object", t.providers)), h(t.effort_max_tokens) || e.push(
|
|
239
249
|
n("effort_max_tokens", "must be an object", t.effort_max_tokens)
|
|
240
250
|
);
|
|
241
251
|
const p = t.milestones;
|
|
242
|
-
if (!
|
|
252
|
+
if (!h(p))
|
|
243
253
|
e.push(n("milestones", "must be an object", p));
|
|
244
254
|
else {
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
for (const u of
|
|
249
|
-
const
|
|
250
|
-
if (!
|
|
251
|
-
e.push(n(`milestones.${u}`, "must be an object",
|
|
255
|
+
const m = Object.keys(p);
|
|
256
|
+
m.length === 0 && e.push(n("milestones", "must have at least one entry"));
|
|
257
|
+
const d = new Set(m);
|
|
258
|
+
for (const u of m) {
|
|
259
|
+
const s = p[u];
|
|
260
|
+
if (!h(s)) {
|
|
261
|
+
e.push(n(`milestones.${u}`, "must be an object", s));
|
|
252
262
|
continue;
|
|
253
263
|
}
|
|
254
|
-
if ((!
|
|
264
|
+
if ((!l(s.description) || s.description.trim() === "") && e.push(
|
|
255
265
|
n(
|
|
256
266
|
`milestones.${u}.description`,
|
|
257
267
|
"required string",
|
|
258
|
-
|
|
268
|
+
s.description
|
|
259
269
|
)
|
|
260
|
-
), !Array.isArray(
|
|
270
|
+
), !Array.isArray(s.depends_on))
|
|
261
271
|
e.push(
|
|
262
272
|
n(
|
|
263
273
|
`milestones.${u}.depends_on`,
|
|
264
274
|
"must be an array",
|
|
265
|
-
|
|
275
|
+
s.depends_on
|
|
266
276
|
)
|
|
267
277
|
);
|
|
268
278
|
else
|
|
269
|
-
for (const _ of
|
|
270
|
-
|
|
279
|
+
for (const _ of s.depends_on)
|
|
280
|
+
l(_) ? d.has(_) || e.push(
|
|
271
281
|
n(`milestones.${u}.depends_on`, `unknown milestone "${_}"`)
|
|
272
282
|
) : e.push(
|
|
273
283
|
n(`milestones.${u}.depends_on[]`, "must be a string", _)
|
|
274
284
|
);
|
|
275
|
-
const b =
|
|
276
|
-
(!
|
|
285
|
+
const b = s.phase;
|
|
286
|
+
(!l(b) || b.trim() === "") && e.push(n(`milestones.${u}.phase`, "required string", b)), (!l(s.authored_by) || s.authored_by.trim() === "") && e.push(
|
|
277
287
|
n(
|
|
278
288
|
`milestones.${u}.authored_by`,
|
|
279
289
|
"required string",
|
|
280
|
-
|
|
290
|
+
s.authored_by
|
|
281
291
|
)
|
|
282
292
|
);
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
n(`milestones.${u}.model`, "invalid model tier",
|
|
293
|
+
const f = s.model;
|
|
294
|
+
f != null && !["Haiku", "Sonnet", "Opus"].includes(f) && e.push(
|
|
295
|
+
n(`milestones.${u}.model`, "invalid model tier", f)
|
|
286
296
|
);
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
n(`milestones.${u}.effort`, "invalid effort tier",
|
|
290
|
-
),
|
|
297
|
+
const y = s.effort;
|
|
298
|
+
y != null && !["low", "medium", "high", "xhigh", "max"].includes(y) && e.push(
|
|
299
|
+
n(`milestones.${u}.effort`, "invalid effort tier", y)
|
|
300
|
+
), s.two_stage !== void 0 && typeof s.two_stage != "boolean" && e.push(
|
|
291
301
|
n(
|
|
292
302
|
`milestones.${u}.two_stage`,
|
|
293
303
|
"must be a boolean",
|
|
294
|
-
|
|
304
|
+
s.two_stage
|
|
295
305
|
)
|
|
296
|
-
), Array.isArray(
|
|
306
|
+
), Array.isArray(s.read_only) || e.push(
|
|
297
307
|
n(
|
|
298
308
|
`milestones.${u}.read_only`,
|
|
299
309
|
"must be an array",
|
|
300
|
-
|
|
310
|
+
s.read_only
|
|
301
311
|
)
|
|
302
312
|
);
|
|
303
313
|
}
|
|
304
|
-
const
|
|
314
|
+
const c = T(
|
|
305
315
|
p
|
|
306
316
|
);
|
|
307
|
-
if (
|
|
308
|
-
for (const { slug: u } of
|
|
317
|
+
if (c)
|
|
318
|
+
for (const { slug: u } of c)
|
|
309
319
|
e.push(n(`milestones.${u}`, "dependency cycle detected"));
|
|
310
|
-
if (
|
|
311
|
-
e.push(n("terminal", `unknown milestone "${
|
|
312
|
-
else if (Array.isArray(
|
|
313
|
-
for (const u of
|
|
314
|
-
|
|
315
|
-
const
|
|
316
|
-
if (!Array.isArray(
|
|
317
|
-
e.push(n("operations", "must be an array or object",
|
|
320
|
+
if (l(a) && !d.has(a))
|
|
321
|
+
e.push(n("terminal", `unknown milestone "${a}"`));
|
|
322
|
+
else if (Array.isArray(a))
|
|
323
|
+
for (const u of a)
|
|
324
|
+
d.has(u) || e.push(n("terminal[]", `unknown milestone "${u}"`));
|
|
325
|
+
const o = t.operations, i = /* @__PURE__ */ new Set();
|
|
326
|
+
if (!Array.isArray(o) && !h(o))
|
|
327
|
+
e.push(n("operations", "must be an array or object", o));
|
|
318
328
|
else {
|
|
319
|
-
const u = Array.isArray(
|
|
320
|
-
for (const
|
|
321
|
-
if (!
|
|
322
|
-
e.push(n("operations[]", "must be an object",
|
|
329
|
+
const u = Array.isArray(o) ? o : Object.values(o);
|
|
330
|
+
for (const s of u) {
|
|
331
|
+
if (!h(s)) {
|
|
332
|
+
e.push(n("operations[]", "must be an object", s));
|
|
323
333
|
continue;
|
|
324
334
|
}
|
|
325
|
-
const b =
|
|
326
|
-
if (!
|
|
335
|
+
const b = s.id;
|
|
336
|
+
if (!l(b)) {
|
|
327
337
|
e.push(n("operations[?]", "missing/invalid id", b));
|
|
328
338
|
continue;
|
|
329
339
|
}
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
n(`operations[${
|
|
340
|
+
const f = b;
|
|
341
|
+
i.add(f);
|
|
342
|
+
const y = s.milestone;
|
|
343
|
+
l(y) ? d.has(y) || e.push(
|
|
344
|
+
n(`operations[${f}].milestone`, `unknown milestone "${y}"`)
|
|
335
345
|
) : e.push(
|
|
336
|
-
n(`operations[${
|
|
346
|
+
n(`operations[${f}].milestone`, "required string", y)
|
|
337
347
|
);
|
|
338
|
-
const _ =
|
|
339
|
-
|
|
340
|
-
const v =
|
|
341
|
-
if (
|
|
348
|
+
const _ = s.type;
|
|
349
|
+
l(_) && !D.has(_) && e.push(n(`operations[${f}].type`, "invalid type", _));
|
|
350
|
+
const v = s.shape;
|
|
351
|
+
if (h(v)) {
|
|
342
352
|
const g = v.kind;
|
|
343
|
-
g != null &&
|
|
344
|
-
n(`operations[${
|
|
353
|
+
g != null && l(g) && !E.has(g) && e.push(
|
|
354
|
+
n(`operations[${f}].shape.kind`, "invalid shape kind", g)
|
|
345
355
|
);
|
|
346
356
|
const $ = v.ops;
|
|
347
|
-
if (Array.isArray($) &&
|
|
357
|
+
if (Array.isArray($) && l(g))
|
|
348
358
|
for (let w = 0; w < $.length; w++) {
|
|
349
359
|
const A = $[w];
|
|
350
|
-
if (!
|
|
360
|
+
if (!h(A))
|
|
351
361
|
continue;
|
|
352
362
|
const k = A.op;
|
|
353
|
-
|
|
363
|
+
l(k) && !j(g, k) && e.push(
|
|
354
364
|
n(
|
|
355
|
-
`operations[${
|
|
365
|
+
`operations[${f}].shape.ops[${w}]`,
|
|
356
366
|
`op "${k}" not valid for kind "${g}"`
|
|
357
367
|
)
|
|
358
368
|
);
|
|
359
369
|
}
|
|
360
370
|
}
|
|
361
|
-
Array.isArray(
|
|
371
|
+
Array.isArray(s.depends_on) || e.push(
|
|
362
372
|
n(
|
|
363
|
-
`operations[${
|
|
373
|
+
`operations[${f}].depends_on`,
|
|
364
374
|
"must be an array",
|
|
365
|
-
|
|
375
|
+
s.depends_on
|
|
366
376
|
)
|
|
367
377
|
);
|
|
368
378
|
}
|
|
369
|
-
for (const
|
|
370
|
-
if (!
|
|
379
|
+
for (const s of u) {
|
|
380
|
+
if (!h(s))
|
|
371
381
|
continue;
|
|
372
|
-
const b =
|
|
373
|
-
if (!
|
|
382
|
+
const b = s.id;
|
|
383
|
+
if (!l(b))
|
|
374
384
|
continue;
|
|
375
|
-
const
|
|
376
|
-
if (Array.isArray(
|
|
377
|
-
for (const
|
|
378
|
-
|
|
385
|
+
const f = s.depends_on;
|
|
386
|
+
if (Array.isArray(f))
|
|
387
|
+
for (const y of f)
|
|
388
|
+
l(y) && !i.has(y) && e.push(
|
|
379
389
|
n(
|
|
380
390
|
`operations[${b}].depends_on`,
|
|
381
|
-
`unknown operation "${
|
|
391
|
+
`unknown operation "${y}"`
|
|
382
392
|
)
|
|
383
393
|
);
|
|
384
394
|
}
|
|
@@ -386,151 +396,156 @@ function N(t) {
|
|
|
386
396
|
}
|
|
387
397
|
return { valid: e.length === 0, errors: e };
|
|
388
398
|
}
|
|
389
|
-
function
|
|
399
|
+
function N(t) {
|
|
390
400
|
const e = [];
|
|
391
|
-
if (!
|
|
401
|
+
if (!h(t))
|
|
392
402
|
return { valid: !1, errors: [n("", "root must be an object")] };
|
|
393
|
-
for (const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
if (!
|
|
398
|
-
e.push(n("milestones", "must be an object",
|
|
403
|
+
for (const a of ["snapshot_at", "description"])
|
|
404
|
+
l(t[a]) || e.push(n(a, "required string field missing", t[a]));
|
|
405
|
+
l(t.plan) || e.push(n("plan", "required string", t.plan));
|
|
406
|
+
const r = t.milestones;
|
|
407
|
+
if (!h(r))
|
|
408
|
+
e.push(n("milestones", "must be an object", r));
|
|
399
409
|
else {
|
|
400
|
-
const
|
|
401
|
-
for (const
|
|
402
|
-
const
|
|
403
|
-
if (!
|
|
404
|
-
e.push(n(`milestones.${
|
|
410
|
+
const a = Object.keys(r), p = new Set(a);
|
|
411
|
+
for (const o of a) {
|
|
412
|
+
const i = r[o];
|
|
413
|
+
if (!h(i)) {
|
|
414
|
+
e.push(n(`milestones.${o}`, "must be an object", i));
|
|
405
415
|
continue;
|
|
406
416
|
}
|
|
407
|
-
const u =
|
|
408
|
-
u === !0 &&
|
|
417
|
+
const u = i.eligible, s = i.pending;
|
|
418
|
+
u === !0 && s !== null && s !== void 0 && e.push(
|
|
409
419
|
n(
|
|
410
|
-
`milestones.${
|
|
420
|
+
`milestones.${o}`,
|
|
411
421
|
"D-07 violation: eligible=true but pending not null"
|
|
412
422
|
)
|
|
413
423
|
), typeof u != "boolean" && e.push(
|
|
414
|
-
n(`milestones.${
|
|
424
|
+
n(`milestones.${o}.eligible`, "must be boolean", u)
|
|
425
|
+
);
|
|
426
|
+
const b = i.status;
|
|
427
|
+
(!l(b) || !O.has(b)) && e.push(n(`milestones.${o}.status`, "invalid status", b)), u === !0 && b === "complete" && e.push(
|
|
428
|
+
n(
|
|
429
|
+
`milestones.${o}`,
|
|
430
|
+
"D-07 violation: eligible=true but status is complete"
|
|
431
|
+
)
|
|
415
432
|
);
|
|
416
|
-
const
|
|
417
|
-
(
|
|
418
|
-
|
|
419
|
-
(typeof m != "number" || !Number.isInteger(m) || m < 0) && e.push(
|
|
420
|
-
n(`milestones.${s}.wave`, "must be non-negative integer", m)
|
|
433
|
+
const f = i.wave;
|
|
434
|
+
(typeof f != "number" || !Number.isInteger(f) || f < 0) && e.push(
|
|
435
|
+
n(`milestones.${o}.wave`, "must be non-negative integer", f)
|
|
421
436
|
);
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
n(`milestones.${
|
|
437
|
+
const y = i.ki_estimate;
|
|
438
|
+
y != null && typeof y != "number" && e.push(
|
|
439
|
+
n(`milestones.${o}.ki_estimate`, "must be number|null", y)
|
|
425
440
|
);
|
|
426
441
|
for (const _ of ["tokens_estimated", "tokens_actual"]) {
|
|
427
|
-
const v =
|
|
428
|
-
v != null && typeof v != "number" && e.push(n(`milestones.${
|
|
442
|
+
const v = i[_];
|
|
443
|
+
v != null && typeof v != "number" && e.push(n(`milestones.${o}.${_}`, "must be number|null", v));
|
|
429
444
|
}
|
|
430
|
-
Array.isArray(
|
|
445
|
+
Array.isArray(i.artifacts) || e.push(
|
|
431
446
|
n(
|
|
432
|
-
`milestones.${
|
|
447
|
+
`milestones.${o}.artifacts`,
|
|
433
448
|
"must be an array",
|
|
434
|
-
|
|
449
|
+
i.artifacts
|
|
435
450
|
)
|
|
436
|
-
), typeof
|
|
437
|
-
n(`milestones.${
|
|
451
|
+
), typeof i.si_bytes != "number" && e.push(
|
|
452
|
+
n(`milestones.${o}.si_bytes`, "must be a number", i.si_bytes)
|
|
438
453
|
);
|
|
439
454
|
}
|
|
440
|
-
const
|
|
441
|
-
if (!Array.isArray(
|
|
442
|
-
e.push(n("operations", "must be an array",
|
|
455
|
+
const m = t.operations;
|
|
456
|
+
if (!Array.isArray(m))
|
|
457
|
+
e.push(n("operations", "must be an array", m));
|
|
443
458
|
else
|
|
444
|
-
for (const
|
|
445
|
-
if (!
|
|
459
|
+
for (const o of m) {
|
|
460
|
+
if (!h(o))
|
|
446
461
|
continue;
|
|
447
|
-
const
|
|
448
|
-
|
|
462
|
+
const i = l(o.id) ? o.id : "?", u = o.milestone;
|
|
463
|
+
l(u) && !p.has(u) && e.push(
|
|
449
464
|
n(
|
|
450
|
-
`operations[${
|
|
465
|
+
`operations[${i}].milestone`,
|
|
451
466
|
`unknown milestone "${u}"`
|
|
452
467
|
)
|
|
453
468
|
);
|
|
454
|
-
const
|
|
455
|
-
(!
|
|
469
|
+
const s = o.status;
|
|
470
|
+
(!l(s) || !I.has(s)) && e.push(
|
|
456
471
|
n(
|
|
457
|
-
`operations[${
|
|
472
|
+
`operations[${i}].status`,
|
|
458
473
|
"invalid operation status",
|
|
459
|
-
|
|
474
|
+
s
|
|
460
475
|
)
|
|
461
|
-
), Array.isArray(
|
|
476
|
+
), Array.isArray(o.dispatch_ids) || e.push(
|
|
462
477
|
n(
|
|
463
|
-
`operations[${
|
|
478
|
+
`operations[${i}].dispatch_ids`,
|
|
464
479
|
"must be an array",
|
|
465
|
-
|
|
480
|
+
o.dispatch_ids
|
|
466
481
|
)
|
|
467
|
-
), typeof
|
|
482
|
+
), typeof o.attempt_count != "number" && e.push(
|
|
468
483
|
n(
|
|
469
|
-
`operations[${
|
|
484
|
+
`operations[${i}].attempt_count`,
|
|
470
485
|
"must be a number",
|
|
471
|
-
|
|
486
|
+
o.attempt_count
|
|
472
487
|
)
|
|
473
|
-
), Array.isArray(
|
|
488
|
+
), Array.isArray(o.blast_radius) || e.push(
|
|
474
489
|
n(
|
|
475
|
-
`operations[${
|
|
490
|
+
`operations[${i}].blast_radius`,
|
|
476
491
|
"must be an array",
|
|
477
|
-
|
|
492
|
+
o.blast_radius
|
|
478
493
|
)
|
|
479
494
|
);
|
|
480
495
|
}
|
|
481
|
-
const
|
|
482
|
-
if (!Array.isArray(
|
|
483
|
-
e.push(n("open_questions", "must be an array",
|
|
496
|
+
const d = t.open_questions;
|
|
497
|
+
if (!Array.isArray(d))
|
|
498
|
+
e.push(n("open_questions", "must be an array", d));
|
|
484
499
|
else
|
|
485
|
-
for (const
|
|
486
|
-
if (!
|
|
500
|
+
for (const o of d) {
|
|
501
|
+
if (!h(o))
|
|
487
502
|
continue;
|
|
488
|
-
const
|
|
489
|
-
(!
|
|
490
|
-
n("open_questions", `unknown blocking milestone "${
|
|
491
|
-
), typeof
|
|
503
|
+
const i = o.blocking;
|
|
504
|
+
(!l(i) || !p.has(i)) && e.push(
|
|
505
|
+
n("open_questions", `unknown blocking milestone "${i}"`)
|
|
506
|
+
), typeof o.surfaced != "boolean" && e.push(
|
|
492
507
|
n(
|
|
493
|
-
`open_questions[${
|
|
508
|
+
`open_questions[${o.id}]`,
|
|
494
509
|
"surfaced must be boolean",
|
|
495
|
-
|
|
510
|
+
o.surfaced
|
|
496
511
|
)
|
|
497
|
-
), typeof
|
|
512
|
+
), typeof o.answered != "boolean" && e.push(
|
|
498
513
|
n(
|
|
499
|
-
`open_questions[${
|
|
514
|
+
`open_questions[${o.id}]`,
|
|
500
515
|
"answered must be boolean",
|
|
501
|
-
|
|
516
|
+
o.answered
|
|
502
517
|
)
|
|
503
518
|
);
|
|
504
519
|
}
|
|
505
|
-
const
|
|
506
|
-
if (
|
|
507
|
-
if (!Array.isArray(
|
|
520
|
+
const c = t.dispatch_units;
|
|
521
|
+
if (c !== void 0)
|
|
522
|
+
if (!Array.isArray(c))
|
|
508
523
|
e.push(
|
|
509
|
-
n("dispatch_units", "must be an array if present",
|
|
524
|
+
n("dispatch_units", "must be an array if present", c)
|
|
510
525
|
);
|
|
511
526
|
else
|
|
512
|
-
for (const
|
|
513
|
-
if (!
|
|
527
|
+
for (const o of c) {
|
|
528
|
+
if (!h(o))
|
|
514
529
|
continue;
|
|
515
|
-
const
|
|
516
|
-
typeof
|
|
530
|
+
const i = o.fits_context_window;
|
|
531
|
+
typeof i != "boolean" && e.push(
|
|
517
532
|
n(
|
|
518
|
-
`dispatch_units[${
|
|
533
|
+
`dispatch_units[${o.id}]`,
|
|
519
534
|
"fits_context_window must be boolean",
|
|
520
|
-
|
|
535
|
+
i
|
|
521
536
|
)
|
|
522
537
|
);
|
|
523
|
-
const u =
|
|
538
|
+
const u = o.milestones;
|
|
524
539
|
if (Array.isArray(u))
|
|
525
|
-
for (const
|
|
526
|
-
|
|
540
|
+
for (const s of u)
|
|
541
|
+
l(s) && !p.has(s) && e.push(
|
|
527
542
|
n(
|
|
528
|
-
`dispatch_units[${
|
|
529
|
-
`unknown milestone "${
|
|
543
|
+
`dispatch_units[${o.id}].milestones`,
|
|
544
|
+
`unknown milestone "${s}"`
|
|
530
545
|
)
|
|
531
546
|
);
|
|
532
547
|
}
|
|
533
|
-
|
|
548
|
+
h(t.pairwise_overlap) || e.push(
|
|
534
549
|
n(
|
|
535
550
|
"pairwise_overlap",
|
|
536
551
|
"must be an object",
|
|
@@ -540,21 +555,21 @@ function L(t) {
|
|
|
540
555
|
}
|
|
541
556
|
return { valid: e.length === 0, errors: e };
|
|
542
557
|
}
|
|
543
|
-
function
|
|
544
|
-
const e =
|
|
558
|
+
function P(t) {
|
|
559
|
+
const e = L(t);
|
|
545
560
|
if (!e.valid)
|
|
546
561
|
throw new Error(
|
|
547
562
|
`DagJson validation failed:
|
|
548
|
-
${e.errors.map((
|
|
563
|
+
${e.errors.map((r) => ` ${r.path}: ${r.message}`).join(`
|
|
549
564
|
`)}`
|
|
550
565
|
);
|
|
551
566
|
}
|
|
552
567
|
function H(t) {
|
|
553
|
-
const e =
|
|
568
|
+
const e = N(t);
|
|
554
569
|
if (!e.valid)
|
|
555
570
|
throw new Error(
|
|
556
571
|
`Snapshot validation failed:
|
|
557
|
-
${e.errors.map((
|
|
572
|
+
${e.errors.map((r) => ` ${r.path}: ${r.message}`).join(`
|
|
558
573
|
`)}`
|
|
559
574
|
);
|
|
560
575
|
}
|
|
@@ -632,21 +647,21 @@ const S = [
|
|
|
632
647
|
});
|
|
633
648
|
let e = [];
|
|
634
649
|
Array.isArray(t.operations) ? e = t.operations : t.operations && typeof t.operations == "object" && (e = Object.values(t.operations));
|
|
635
|
-
for (const
|
|
636
|
-
if (typeof
|
|
637
|
-
const
|
|
638
|
-
|
|
650
|
+
for (const r of e)
|
|
651
|
+
if (typeof r == "object" && r !== null) {
|
|
652
|
+
const a = r;
|
|
653
|
+
a.type === void 0 && (a.type = "generative"), a.criteria === void 0 && (a.criteria = []), a.tool === void 0 && (a.tool = null), a.args === void 0 && (a.args = null);
|
|
639
654
|
}
|
|
640
655
|
}
|
|
641
656
|
}
|
|
642
657
|
];
|
|
643
|
-
function K(t, e,
|
|
658
|
+
function K(t, e, r) {
|
|
644
659
|
if (t === e)
|
|
645
660
|
return;
|
|
646
|
-
let
|
|
647
|
-
for (const p of [...S].sort((
|
|
648
|
-
if (p.from ===
|
|
649
|
-
|
|
661
|
+
let a = t;
|
|
662
|
+
for (const p of [...S].sort((m, d) => m.from - d.from))
|
|
663
|
+
if (p.from === a && (p.apply(r), a = p.to, a === e)) {
|
|
664
|
+
r.schema_version = e;
|
|
650
665
|
return;
|
|
651
666
|
}
|
|
652
667
|
throw new Error(
|
|
@@ -657,11 +672,11 @@ function K(t, e, i) {
|
|
|
657
672
|
}
|
|
658
673
|
export {
|
|
659
674
|
x as VALID_OPS_BY_KIND,
|
|
660
|
-
|
|
661
|
-
|
|
675
|
+
z as WRITE_CLASS_ACTIONS,
|
|
676
|
+
P as assertValidDagJson,
|
|
662
677
|
H as assertValidSnapshot,
|
|
663
678
|
j as isValidOpForKind,
|
|
664
679
|
K as migrateDag,
|
|
665
|
-
|
|
666
|
-
|
|
680
|
+
L as validateDagJson,
|
|
681
|
+
N as validateSnapshot
|
|
667
682
|
};
|
package/lib/types.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export type ShapeKind = CodeKind | ConfigKind | 'doc' | 'structured-output';
|
|
|
17
17
|
export type KindFamily = 'code-config' | 'doc' | 'structured' | 'tool-call';
|
|
18
18
|
export type MilestoneStatus = 'pending' | 'pending-surfaced' | 'in_progress' | 'complete' | 'failed' | 'skipped';
|
|
19
19
|
export type DispatchUnitStatus = 'pending' | 'in_progress' | 'complete' | 'failed';
|
|
20
|
+
export type DispatchExecutionMode = 'model-dispatch' | 'guard-only';
|
|
20
21
|
export type OperationStatus = 'pending' | 'in_progress' | 'complete' | 'failed' | 'skipped';
|
|
21
22
|
export type GuardResult = 'pass' | 'fail';
|
|
22
23
|
export type MilestoneGuardResult = 'pass' | 'fail' | 'pending';
|
|
@@ -38,6 +39,7 @@ export interface ShapeOpDag {
|
|
|
38
39
|
to: string | null;
|
|
39
40
|
position: number | null;
|
|
40
41
|
required: boolean | null;
|
|
42
|
+
type_spec?: Record<string, string> | null;
|
|
41
43
|
}
|
|
42
44
|
export interface ShapeOpSnapshot extends ShapeOpDag {
|
|
43
45
|
from: string | null;
|
|
@@ -323,9 +325,11 @@ export interface DispatchUnit {
|
|
|
323
325
|
two_stage: boolean;
|
|
324
326
|
provider: ProviderConfig | null;
|
|
325
327
|
agent_name: string;
|
|
328
|
+
execution_mode: DispatchExecutionMode;
|
|
326
329
|
mcp_servers: Record<string, unknown> | null;
|
|
327
330
|
resolved_max_tokens: number | null;
|
|
328
331
|
background: true;
|
|
332
|
+
systemPrompt: string | null;
|
|
329
333
|
prompt: string | null;
|
|
330
334
|
context_files: string[];
|
|
331
335
|
si_bytes: number;
|
|
@@ -356,3 +360,15 @@ export interface IOptimizerDeps {
|
|
|
356
360
|
readFiles?: (paths: string[]) => Map<string, string>;
|
|
357
361
|
dispatchLog?: DispatchLogEntry[];
|
|
358
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* B-calibration store contract (SCOPE.md §C4 / §Open Decisions #2 —
|
|
365
|
+
* `~/.adhd/dispatch-calibration.json`). Formalizes what was previously a
|
|
366
|
+
* dispatch-orchestrator-local `ICalibrationPlaceholder` (DEBT-DISPATCH-018):
|
|
367
|
+
* read-only access to whatever calibrated per-tier B values a calibration
|
|
368
|
+
* utility has persisted. Deliberately minimal — a single `read()` accessor —
|
|
369
|
+
* so any storage backend (JSON file, DB, in-memory fixture) can implement it
|
|
370
|
+
* without dispatch-orchestrator depending on the storage mechanism.
|
|
371
|
+
*/
|
|
372
|
+
export interface ICalibrationStore {
|
|
373
|
+
read(): Promise<Record<string, number>> | Record<string, number>;
|
|
374
|
+
}
|