@adhd/dispatch-base-spec 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/index.mjs +6 -1
- package/lib/types.d.ts +12 -0
- package/package.json +20 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 0.1.3 (2026-09-24)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for dispatch-base-spec to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
5
|
+
## 0.1.2 (2026-08-08)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### 🩹 Fixes
|
|
9
|
+
|
|
10
|
+
- **dispatch:** D-07 own-status eligibility guard (DEBT-DISPATCH-013) + formalize ICalibrationStore (DEBT-DISPATCH-018, BL-103)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### ❤️ Thank You
|
|
14
|
+
|
|
15
|
+
- pseudosky
|
|
16
|
+
|
|
1
17
|
## 0.1.1 (2026-08-07)
|
|
2
18
|
|
|
3
19
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { BlastRadiusEntry, CodeKind, Confidence, ConfigKind, CrossPlanDep, DagJson, DagSnapshot, DispatchExecutionMode, 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,4 +1,4 @@
|
|
|
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 b of o.depends_on)l(b)?c.has(b)||e.push(n(`milestones.${u}.depends_on`,`unknown milestone "${b}"`)):e.push(n(`milestones.${u}.depends_on[]`,"must be a string",b));const _=o.phase;(!l(_)||_.trim()==="")&&e.push(n(`milestones.${u}.phase`,"required string",_)),(!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 _=o.id;if(!l(_)){e.push(n("operations[?]","missing/invalid id",_));continue}const f=_;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 b=o.type;l(b)&&!E.has(b)&&e.push(n(`operations[${f}].type`,"invalid type",b));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 _=o.id;if(!l(_))continue;const f=o.depends_on;if(Array.isArray(f))for(const y of f)l(y)&&!i.has(y)&&e.push(n(`operations[${_}].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 _=i.status;(!l(_)||!T.has(_))&&e.push(n(`milestones.${s}.status`,"invalid status",_));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 b of["tokens_estimated","tokens_actual"]){const v=i[b];v!=null&&typeof v!="number"&&e.push(n(`milestones.${s}.${b}`,"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:
|
|
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
2
|
${e.errors.map(r=>` ${r.path}: ${r.message}`).join(`
|
|
3
3
|
`)}`)}function K(t){const e=I(t);if(!e.valid)throw new Error(`Snapshot validation failed:
|
|
4
4
|
${e.errors.map(r=>` ${r.path}: ${r.message}`).join(`
|
package/index.mjs
CHANGED
|
@@ -424,7 +424,12 @@ function N(t) {
|
|
|
424
424
|
n(`milestones.${o}.eligible`, "must be boolean", u)
|
|
425
425
|
);
|
|
426
426
|
const b = i.status;
|
|
427
|
-
(!l(b) || !O.has(b)) && e.push(n(`milestones.${o}.status`, "invalid status", b))
|
|
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
|
+
)
|
|
432
|
+
);
|
|
428
433
|
const f = i.wave;
|
|
429
434
|
(typeof f != "number" || !Number.isInteger(f) || f < 0) && e.push(
|
|
430
435
|
n(`milestones.${o}.wave`, "must be non-negative integer", f)
|
package/lib/types.d.ts
CHANGED
|
@@ -360,3 +360,15 @@ export interface IOptimizerDeps {
|
|
|
360
360
|
readFiles?: (paths: string[]) => Map<string, string>;
|
|
361
361
|
dispatchLog?: DispatchLogEntry[];
|
|
362
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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhd/dispatch-base-spec",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"dependencies": {},
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.mjs",
|
|
@@ -11,5 +11,23 @@
|
|
|
11
11
|
"assets": [
|
|
12
12
|
"src/dag-v4.schema.json",
|
|
13
13
|
"src/valid-ops-by-kind.json"
|
|
14
|
-
]
|
|
14
|
+
],
|
|
15
|
+
"description": "Specification and types for @adhd/dispatch task DAGs",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"dag",
|
|
18
|
+
"spec",
|
|
19
|
+
"task",
|
|
20
|
+
"orchestration",
|
|
21
|
+
"typescript"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/PseudoSky/adhd.git",
|
|
27
|
+
"directory": "packages/dispatch/dispatch-base-spec"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/PseudoSky/adhd/tree/main/packages/dispatch/dispatch-base-spec#readme",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/PseudoSky/adhd/issues"
|
|
32
|
+
}
|
|
15
33
|
}
|