@adhd/dispatch-base-spec 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 +4 -0
- package/index.js +5 -0
- package/index.mjs +667 -0
- package/lib/migrate.d.ts +1 -0
- package/lib/types.d.ts +358 -0
- package/lib/validate.d.ts +6 -0
- package/package.json +11 -0
package/index.d.ts
ADDED
|
@@ -0,0 +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';
|
|
2
|
+
export { isValidOpForKind, VALID_OPS_BY_KIND, WRITE_CLASS_ACTIONS, } from './lib/types.js';
|
|
3
|
+
export { assertValidDagJson, assertValidSnapshot, validateDagJson, validateSnapshot, } from './lib/validate.js';
|
|
4
|
+
export { migrateDag } from './lib/migrate.js';
|
package/index.js
ADDED
|
@@ -0,0 +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(i=>` ${i.path}: ${i.message}`).join(`
|
|
3
|
+
`)}`)}function P(t){const e=I(t);if(!e.valid)throw new Error(`Snapshot validation failed:
|
|
4
|
+
${e.errors.map(i=>` ${i.path}: ${i.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 i of e)if(typeof i=="object"&&i!==null){const r=i;r.type===void 0&&(r.type="generative"),r.criteria===void 0&&(r.criteria=[]),r.tool===void 0&&(r.tool=null),r.args===void 0&&(r.args=null)}}}];function V(t,e,i){if(t===e)return;let r=t;for(const p of[...S].sort((c,l)=>c.from-l.from))if(p.from===r&&(p.apply(i),r=p.to,r===e)){i.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=K;exports.assertValidSnapshot=P;exports.isValidOpForKind=j;exports.migrateDag=V;exports.validateDagJson=O;exports.validateSnapshot=I;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
const R = /* @__PURE__ */ new Set([
|
|
2
|
+
"create",
|
|
3
|
+
"modify-signature",
|
|
4
|
+
"modify-body",
|
|
5
|
+
"add-export",
|
|
6
|
+
"remove-export",
|
|
7
|
+
"rename"
|
|
8
|
+
]), x = {
|
|
9
|
+
function: /* @__PURE__ */ new Set([
|
|
10
|
+
"add-param",
|
|
11
|
+
"remove-param",
|
|
12
|
+
"rename-param",
|
|
13
|
+
"retype-param",
|
|
14
|
+
"change-param-optional",
|
|
15
|
+
"reorder-params",
|
|
16
|
+
"change-return"
|
|
17
|
+
]),
|
|
18
|
+
interface: /* @__PURE__ */ new Set([
|
|
19
|
+
"add-field",
|
|
20
|
+
"remove-field",
|
|
21
|
+
"rename-field",
|
|
22
|
+
"retype-field",
|
|
23
|
+
"change-field-optional",
|
|
24
|
+
"add-generic",
|
|
25
|
+
"remove-generic",
|
|
26
|
+
"constrain-generic",
|
|
27
|
+
"add-extends",
|
|
28
|
+
"remove-extends"
|
|
29
|
+
]),
|
|
30
|
+
type: /* @__PURE__ */ new Set(["add-field", "remove-field", "retype-field"]),
|
|
31
|
+
class: /* @__PURE__ */ new Set([
|
|
32
|
+
"add-field",
|
|
33
|
+
"remove-field",
|
|
34
|
+
"rename-field",
|
|
35
|
+
"retype-field",
|
|
36
|
+
"change-field-optional",
|
|
37
|
+
"add-param",
|
|
38
|
+
"add-generic",
|
|
39
|
+
"remove-generic",
|
|
40
|
+
"constrain-generic",
|
|
41
|
+
"add-extends",
|
|
42
|
+
"remove-extends"
|
|
43
|
+
]),
|
|
44
|
+
enum: /* @__PURE__ */ new Set(["add-field", "remove-field", "rename-field"]),
|
|
45
|
+
const: /* @__PURE__ */ new Set([
|
|
46
|
+
"add-var",
|
|
47
|
+
"remove-var",
|
|
48
|
+
"rename-var",
|
|
49
|
+
"change-default"
|
|
50
|
+
]),
|
|
51
|
+
config: /* @__PURE__ */ new Set([
|
|
52
|
+
"set-key",
|
|
53
|
+
"remove-key",
|
|
54
|
+
"rename-key",
|
|
55
|
+
"add-entry",
|
|
56
|
+
"remove-entry",
|
|
57
|
+
"update-entry",
|
|
58
|
+
"bump-version",
|
|
59
|
+
"update-checksum"
|
|
60
|
+
]),
|
|
61
|
+
env: /* @__PURE__ */ new Set(["set-key", "remove-key", "rename-key"]),
|
|
62
|
+
schema: /* @__PURE__ */ new Set([
|
|
63
|
+
"add-table",
|
|
64
|
+
"remove-table",
|
|
65
|
+
"add-column",
|
|
66
|
+
"remove-column",
|
|
67
|
+
"rename-column",
|
|
68
|
+
"retype-column",
|
|
69
|
+
"change-nullable",
|
|
70
|
+
"add-index",
|
|
71
|
+
"remove-index"
|
|
72
|
+
]),
|
|
73
|
+
manifest: /* @__PURE__ */ new Set(["add-entry", "remove-entry", "bump-version"]),
|
|
74
|
+
doc: /* @__PURE__ */ new Set([
|
|
75
|
+
"add-section",
|
|
76
|
+
"remove-section",
|
|
77
|
+
"rename-section",
|
|
78
|
+
"update-section"
|
|
79
|
+
]),
|
|
80
|
+
"structured-output": /* @__PURE__ */ new Set([]),
|
|
81
|
+
script: /* @__PURE__ */ new Set([
|
|
82
|
+
"add-param",
|
|
83
|
+
"remove-param",
|
|
84
|
+
"rename-param",
|
|
85
|
+
"retype-param",
|
|
86
|
+
"change-param-optional",
|
|
87
|
+
"reorder-params",
|
|
88
|
+
"change-return",
|
|
89
|
+
"add-field",
|
|
90
|
+
"remove-field",
|
|
91
|
+
"rename-field",
|
|
92
|
+
"retype-field",
|
|
93
|
+
"change-field-optional",
|
|
94
|
+
"add-generic",
|
|
95
|
+
"remove-generic",
|
|
96
|
+
"constrain-generic",
|
|
97
|
+
"add-extends",
|
|
98
|
+
"remove-extends",
|
|
99
|
+
"set-key",
|
|
100
|
+
"remove-key",
|
|
101
|
+
"rename-key",
|
|
102
|
+
"add-array-item",
|
|
103
|
+
"remove-array-item",
|
|
104
|
+
"add-var",
|
|
105
|
+
"remove-var",
|
|
106
|
+
"rename-var",
|
|
107
|
+
"change-default",
|
|
108
|
+
"add-section",
|
|
109
|
+
"remove-section",
|
|
110
|
+
"rename-section",
|
|
111
|
+
"update-section",
|
|
112
|
+
"add-table",
|
|
113
|
+
"remove-table",
|
|
114
|
+
"add-column",
|
|
115
|
+
"remove-column",
|
|
116
|
+
"rename-column",
|
|
117
|
+
"retype-column",
|
|
118
|
+
"change-nullable",
|
|
119
|
+
"add-index",
|
|
120
|
+
"remove-index",
|
|
121
|
+
"add-entry",
|
|
122
|
+
"remove-entry",
|
|
123
|
+
"update-entry",
|
|
124
|
+
"bump-version",
|
|
125
|
+
"update-checksum",
|
|
126
|
+
"add-export"
|
|
127
|
+
])
|
|
128
|
+
};
|
|
129
|
+
function j(t, e) {
|
|
130
|
+
const i = x[t];
|
|
131
|
+
return i ? i.has(e) : !1;
|
|
132
|
+
}
|
|
133
|
+
const O = /* @__PURE__ */ new Set([
|
|
134
|
+
"pending",
|
|
135
|
+
"pending-surfaced",
|
|
136
|
+
"in_progress",
|
|
137
|
+
"complete",
|
|
138
|
+
"failed",
|
|
139
|
+
"skipped"
|
|
140
|
+
]), I = /* @__PURE__ */ new Set([
|
|
141
|
+
"pending",
|
|
142
|
+
"in_progress",
|
|
143
|
+
"complete",
|
|
144
|
+
"failed",
|
|
145
|
+
"skipped"
|
|
146
|
+
]), q = /* @__PURE__ */ new Set(["automated", "tool-call", "generative"]), D = /* @__PURE__ */ new Set([
|
|
147
|
+
"function",
|
|
148
|
+
"interface",
|
|
149
|
+
"type",
|
|
150
|
+
"class",
|
|
151
|
+
"enum",
|
|
152
|
+
"const",
|
|
153
|
+
"script",
|
|
154
|
+
"config",
|
|
155
|
+
"env",
|
|
156
|
+
"schema",
|
|
157
|
+
"manifest",
|
|
158
|
+
"doc",
|
|
159
|
+
"structured-output"
|
|
160
|
+
]);
|
|
161
|
+
function f(t) {
|
|
162
|
+
return typeof t == "object" && t !== null && !Array.isArray(t);
|
|
163
|
+
}
|
|
164
|
+
function c(t) {
|
|
165
|
+
return typeof t == "string";
|
|
166
|
+
}
|
|
167
|
+
function n(t, e, i) {
|
|
168
|
+
return { path: t, message: e, value: i };
|
|
169
|
+
}
|
|
170
|
+
function T(t) {
|
|
171
|
+
var l, y;
|
|
172
|
+
const e = Object.keys(t), i = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
173
|
+
for (const s of e)
|
|
174
|
+
i.set(s, 0), r.set(s, []);
|
|
175
|
+
for (const s of e)
|
|
176
|
+
for (const a of ((l = t[s]) == null ? void 0 : l.depends_on) ?? [])
|
|
177
|
+
t[a] && ((y = r.get(a)) == null || y.push(s), i.set(s, (i.get(s) ?? 0) + 1));
|
|
178
|
+
const p = e.filter((s) => (i.get(s) ?? 0) === 0), d = /* @__PURE__ */ new Set();
|
|
179
|
+
for (; p.length > 0; ) {
|
|
180
|
+
const s = p.shift();
|
|
181
|
+
if (s !== void 0) {
|
|
182
|
+
d.add(s);
|
|
183
|
+
for (const a of r.get(s) ?? []) {
|
|
184
|
+
const u = (i.get(a) ?? 1) - 1;
|
|
185
|
+
i.set(a, u), u === 0 && p.push(a);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return d.size !== e.length ? e.filter((s) => !d.has(s)).map((s) => ({ slug: s })) : null;
|
|
190
|
+
}
|
|
191
|
+
function E(t, e) {
|
|
192
|
+
for (const i of t) {
|
|
193
|
+
if (!f(i))
|
|
194
|
+
continue;
|
|
195
|
+
const r = c(i.id) ? i.id : "?", p = i.turns;
|
|
196
|
+
if (!Array.isArray(p)) {
|
|
197
|
+
e.push(
|
|
198
|
+
n(`dispatch_log[${r}].turns`, "must be an array", p)
|
|
199
|
+
);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
for (let d = 0; d < p.length; d++) {
|
|
203
|
+
const l = p[d], y = `dispatch_log[${r}].turns[${d}]`;
|
|
204
|
+
if (!f(l)) {
|
|
205
|
+
e.push(n(y, "must be an object", l));
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
(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(
|
|
209
|
+
n(`${y}.input_tokens`, "must be a number", l.input_tokens)
|
|
210
|
+
), typeof l.output_tokens != "number" && e.push(
|
|
211
|
+
n(`${y}.output_tokens`, "must be a number", l.output_tokens)
|
|
212
|
+
), c(l.t) || e.push(n(`${y}.t`, "must be a string", l.t));
|
|
213
|
+
const s = l.model_calls;
|
|
214
|
+
s != null && typeof s != "number" && e.push(
|
|
215
|
+
n(
|
|
216
|
+
`${y}.model_calls`,
|
|
217
|
+
"must be a number or null if present",
|
|
218
|
+
s
|
|
219
|
+
)
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function N(t) {
|
|
225
|
+
const e = [];
|
|
226
|
+
if (!f(t))
|
|
227
|
+
return { valid: !1, errors: [n("", "root must be an object")] };
|
|
228
|
+
for (const d of ["description", "problem", "approach", "executor"]) {
|
|
229
|
+
const l = t[d];
|
|
230
|
+
(!c(l) || l.trim() === "") && e.push(n(d, "required string field missing/empty", l));
|
|
231
|
+
}
|
|
232
|
+
typeof t.schema_version != "number" && e.push(
|
|
233
|
+
n("schema_version", "must be a number", t.schema_version)
|
|
234
|
+
);
|
|
235
|
+
const i = t.plan_kind;
|
|
236
|
+
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));
|
|
237
|
+
const r = t.terminal;
|
|
238
|
+
!c(r) && !Array.isArray(r) && e.push(n("terminal", "must be a string or array", r)), Array.isArray(t.dispatch_log) ? E(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(
|
|
239
|
+
n("effort_max_tokens", "must be an object", t.effort_max_tokens)
|
|
240
|
+
);
|
|
241
|
+
const p = t.milestones;
|
|
242
|
+
if (!f(p))
|
|
243
|
+
e.push(n("milestones", "must be an object", p));
|
|
244
|
+
else {
|
|
245
|
+
const d = Object.keys(p);
|
|
246
|
+
d.length === 0 && e.push(n("milestones", "must have at least one entry"));
|
|
247
|
+
const l = new Set(d);
|
|
248
|
+
for (const u of d) {
|
|
249
|
+
const o = p[u];
|
|
250
|
+
if (!f(o)) {
|
|
251
|
+
e.push(n(`milestones.${u}`, "must be an object", o));
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if ((!c(o.description) || o.description.trim() === "") && e.push(
|
|
255
|
+
n(
|
|
256
|
+
`milestones.${u}.description`,
|
|
257
|
+
"required string",
|
|
258
|
+
o.description
|
|
259
|
+
)
|
|
260
|
+
), !Array.isArray(o.depends_on))
|
|
261
|
+
e.push(
|
|
262
|
+
n(
|
|
263
|
+
`milestones.${u}.depends_on`,
|
|
264
|
+
"must be an array",
|
|
265
|
+
o.depends_on
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
else
|
|
269
|
+
for (const _ of o.depends_on)
|
|
270
|
+
c(_) ? l.has(_) || e.push(
|
|
271
|
+
n(`milestones.${u}.depends_on`, `unknown milestone "${_}"`)
|
|
272
|
+
) : e.push(
|
|
273
|
+
n(`milestones.${u}.depends_on[]`, "must be a string", _)
|
|
274
|
+
);
|
|
275
|
+
const b = o.phase;
|
|
276
|
+
(!c(b) || b.trim() === "") && e.push(n(`milestones.${u}.phase`, "required string", b)), (!c(o.authored_by) || o.authored_by.trim() === "") && e.push(
|
|
277
|
+
n(
|
|
278
|
+
`milestones.${u}.authored_by`,
|
|
279
|
+
"required string",
|
|
280
|
+
o.authored_by
|
|
281
|
+
)
|
|
282
|
+
);
|
|
283
|
+
const m = o.model;
|
|
284
|
+
m != null && !["Haiku", "Sonnet", "Opus"].includes(m) && e.push(
|
|
285
|
+
n(`milestones.${u}.model`, "invalid model tier", m)
|
|
286
|
+
);
|
|
287
|
+
const h = o.effort;
|
|
288
|
+
h != null && !["low", "medium", "high", "xhigh", "max"].includes(h) && e.push(
|
|
289
|
+
n(`milestones.${u}.effort`, "invalid effort tier", h)
|
|
290
|
+
), o.two_stage !== void 0 && typeof o.two_stage != "boolean" && e.push(
|
|
291
|
+
n(
|
|
292
|
+
`milestones.${u}.two_stage`,
|
|
293
|
+
"must be a boolean",
|
|
294
|
+
o.two_stage
|
|
295
|
+
)
|
|
296
|
+
), Array.isArray(o.read_only) || e.push(
|
|
297
|
+
n(
|
|
298
|
+
`milestones.${u}.read_only`,
|
|
299
|
+
"must be an array",
|
|
300
|
+
o.read_only
|
|
301
|
+
)
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
const y = T(
|
|
305
|
+
p
|
|
306
|
+
);
|
|
307
|
+
if (y)
|
|
308
|
+
for (const { slug: u } of y)
|
|
309
|
+
e.push(n(`milestones.${u}`, "dependency cycle detected"));
|
|
310
|
+
if (c(r) && !l.has(r))
|
|
311
|
+
e.push(n("terminal", `unknown milestone "${r}"`));
|
|
312
|
+
else if (Array.isArray(r))
|
|
313
|
+
for (const u of r)
|
|
314
|
+
l.has(u) || e.push(n("terminal[]", `unknown milestone "${u}"`));
|
|
315
|
+
const s = t.operations, a = /* @__PURE__ */ new Set();
|
|
316
|
+
if (!Array.isArray(s) && !f(s))
|
|
317
|
+
e.push(n("operations", "must be an array or object", s));
|
|
318
|
+
else {
|
|
319
|
+
const u = Array.isArray(s) ? s : Object.values(s);
|
|
320
|
+
for (const o of u) {
|
|
321
|
+
if (!f(o)) {
|
|
322
|
+
e.push(n("operations[]", "must be an object", o));
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const b = o.id;
|
|
326
|
+
if (!c(b)) {
|
|
327
|
+
e.push(n("operations[?]", "missing/invalid id", b));
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
const m = b;
|
|
331
|
+
a.add(m);
|
|
332
|
+
const h = o.milestone;
|
|
333
|
+
c(h) ? l.has(h) || e.push(
|
|
334
|
+
n(`operations[${m}].milestone`, `unknown milestone "${h}"`)
|
|
335
|
+
) : e.push(
|
|
336
|
+
n(`operations[${m}].milestone`, "required string", h)
|
|
337
|
+
);
|
|
338
|
+
const _ = o.type;
|
|
339
|
+
c(_) && !q.has(_) && e.push(n(`operations[${m}].type`, "invalid type", _));
|
|
340
|
+
const v = o.shape;
|
|
341
|
+
if (f(v)) {
|
|
342
|
+
const g = v.kind;
|
|
343
|
+
g != null && c(g) && !D.has(g) && e.push(
|
|
344
|
+
n(`operations[${m}].shape.kind`, "invalid shape kind", g)
|
|
345
|
+
);
|
|
346
|
+
const $ = v.ops;
|
|
347
|
+
if (Array.isArray($) && c(g))
|
|
348
|
+
for (let w = 0; w < $.length; w++) {
|
|
349
|
+
const A = $[w];
|
|
350
|
+
if (!f(A))
|
|
351
|
+
continue;
|
|
352
|
+
const k = A.op;
|
|
353
|
+
c(k) && !j(g, k) && e.push(
|
|
354
|
+
n(
|
|
355
|
+
`operations[${m}].shape.ops[${w}]`,
|
|
356
|
+
`op "${k}" not valid for kind "${g}"`
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
Array.isArray(o.depends_on) || e.push(
|
|
362
|
+
n(
|
|
363
|
+
`operations[${m}].depends_on`,
|
|
364
|
+
"must be an array",
|
|
365
|
+
o.depends_on
|
|
366
|
+
)
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
for (const o of u) {
|
|
370
|
+
if (!f(o))
|
|
371
|
+
continue;
|
|
372
|
+
const b = o.id;
|
|
373
|
+
if (!c(b))
|
|
374
|
+
continue;
|
|
375
|
+
const m = o.depends_on;
|
|
376
|
+
if (Array.isArray(m))
|
|
377
|
+
for (const h of m)
|
|
378
|
+
c(h) && !a.has(h) && e.push(
|
|
379
|
+
n(
|
|
380
|
+
`operations[${b}].depends_on`,
|
|
381
|
+
`unknown operation "${h}"`
|
|
382
|
+
)
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return { valid: e.length === 0, errors: e };
|
|
388
|
+
}
|
|
389
|
+
function L(t) {
|
|
390
|
+
const e = [];
|
|
391
|
+
if (!f(t))
|
|
392
|
+
return { valid: !1, errors: [n("", "root must be an object")] };
|
|
393
|
+
for (const r of ["snapshot_at", "description"])
|
|
394
|
+
c(t[r]) || e.push(n(r, "required string field missing", t[r]));
|
|
395
|
+
c(t.plan) || e.push(n("plan", "required string", t.plan));
|
|
396
|
+
const i = t.milestones;
|
|
397
|
+
if (!f(i))
|
|
398
|
+
e.push(n("milestones", "must be an object", i));
|
|
399
|
+
else {
|
|
400
|
+
const r = Object.keys(i), p = new Set(r);
|
|
401
|
+
for (const s of r) {
|
|
402
|
+
const a = i[s];
|
|
403
|
+
if (!f(a)) {
|
|
404
|
+
e.push(n(`milestones.${s}`, "must be an object", a));
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
const u = a.eligible, o = a.pending;
|
|
408
|
+
u === !0 && o !== null && o !== void 0 && e.push(
|
|
409
|
+
n(
|
|
410
|
+
`milestones.${s}`,
|
|
411
|
+
"D-07 violation: eligible=true but pending not null"
|
|
412
|
+
)
|
|
413
|
+
), typeof u != "boolean" && e.push(
|
|
414
|
+
n(`milestones.${s}.eligible`, "must be boolean", u)
|
|
415
|
+
);
|
|
416
|
+
const b = a.status;
|
|
417
|
+
(!c(b) || !O.has(b)) && e.push(n(`milestones.${s}.status`, "invalid status", b));
|
|
418
|
+
const m = a.wave;
|
|
419
|
+
(typeof m != "number" || !Number.isInteger(m) || m < 0) && e.push(
|
|
420
|
+
n(`milestones.${s}.wave`, "must be non-negative integer", m)
|
|
421
|
+
);
|
|
422
|
+
const h = a.ki_estimate;
|
|
423
|
+
h != null && typeof h != "number" && e.push(
|
|
424
|
+
n(`milestones.${s}.ki_estimate`, "must be number|null", h)
|
|
425
|
+
);
|
|
426
|
+
for (const _ of ["tokens_estimated", "tokens_actual"]) {
|
|
427
|
+
const v = a[_];
|
|
428
|
+
v != null && typeof v != "number" && e.push(n(`milestones.${s}.${_}`, "must be number|null", v));
|
|
429
|
+
}
|
|
430
|
+
Array.isArray(a.artifacts) || e.push(
|
|
431
|
+
n(
|
|
432
|
+
`milestones.${s}.artifacts`,
|
|
433
|
+
"must be an array",
|
|
434
|
+
a.artifacts
|
|
435
|
+
)
|
|
436
|
+
), typeof a.si_bytes != "number" && e.push(
|
|
437
|
+
n(`milestones.${s}.si_bytes`, "must be a number", a.si_bytes)
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
const d = t.operations;
|
|
441
|
+
if (!Array.isArray(d))
|
|
442
|
+
e.push(n("operations", "must be an array", d));
|
|
443
|
+
else
|
|
444
|
+
for (const s of d) {
|
|
445
|
+
if (!f(s))
|
|
446
|
+
continue;
|
|
447
|
+
const a = c(s.id) ? s.id : "?", u = s.milestone;
|
|
448
|
+
c(u) && !p.has(u) && e.push(
|
|
449
|
+
n(
|
|
450
|
+
`operations[${a}].milestone`,
|
|
451
|
+
`unknown milestone "${u}"`
|
|
452
|
+
)
|
|
453
|
+
);
|
|
454
|
+
const o = s.status;
|
|
455
|
+
(!c(o) || !I.has(o)) && e.push(
|
|
456
|
+
n(
|
|
457
|
+
`operations[${a}].status`,
|
|
458
|
+
"invalid operation status",
|
|
459
|
+
o
|
|
460
|
+
)
|
|
461
|
+
), Array.isArray(s.dispatch_ids) || e.push(
|
|
462
|
+
n(
|
|
463
|
+
`operations[${a}].dispatch_ids`,
|
|
464
|
+
"must be an array",
|
|
465
|
+
s.dispatch_ids
|
|
466
|
+
)
|
|
467
|
+
), typeof s.attempt_count != "number" && e.push(
|
|
468
|
+
n(
|
|
469
|
+
`operations[${a}].attempt_count`,
|
|
470
|
+
"must be a number",
|
|
471
|
+
s.attempt_count
|
|
472
|
+
)
|
|
473
|
+
), Array.isArray(s.blast_radius) || e.push(
|
|
474
|
+
n(
|
|
475
|
+
`operations[${a}].blast_radius`,
|
|
476
|
+
"must be an array",
|
|
477
|
+
s.blast_radius
|
|
478
|
+
)
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
const l = t.open_questions;
|
|
482
|
+
if (!Array.isArray(l))
|
|
483
|
+
e.push(n("open_questions", "must be an array", l));
|
|
484
|
+
else
|
|
485
|
+
for (const s of l) {
|
|
486
|
+
if (!f(s))
|
|
487
|
+
continue;
|
|
488
|
+
const a = s.blocking;
|
|
489
|
+
(!c(a) || !p.has(a)) && e.push(
|
|
490
|
+
n("open_questions", `unknown blocking milestone "${a}"`)
|
|
491
|
+
), typeof s.surfaced != "boolean" && e.push(
|
|
492
|
+
n(
|
|
493
|
+
`open_questions[${s.id}]`,
|
|
494
|
+
"surfaced must be boolean",
|
|
495
|
+
s.surfaced
|
|
496
|
+
)
|
|
497
|
+
), typeof s.answered != "boolean" && e.push(
|
|
498
|
+
n(
|
|
499
|
+
`open_questions[${s.id}]`,
|
|
500
|
+
"answered must be boolean",
|
|
501
|
+
s.answered
|
|
502
|
+
)
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
const y = t.dispatch_units;
|
|
506
|
+
if (y !== void 0)
|
|
507
|
+
if (!Array.isArray(y))
|
|
508
|
+
e.push(
|
|
509
|
+
n("dispatch_units", "must be an array if present", y)
|
|
510
|
+
);
|
|
511
|
+
else
|
|
512
|
+
for (const s of y) {
|
|
513
|
+
if (!f(s))
|
|
514
|
+
continue;
|
|
515
|
+
const a = s.fits_context_window;
|
|
516
|
+
typeof a != "boolean" && e.push(
|
|
517
|
+
n(
|
|
518
|
+
`dispatch_units[${s.id}]`,
|
|
519
|
+
"fits_context_window must be boolean",
|
|
520
|
+
a
|
|
521
|
+
)
|
|
522
|
+
);
|
|
523
|
+
const u = s.milestones;
|
|
524
|
+
if (Array.isArray(u))
|
|
525
|
+
for (const o of u)
|
|
526
|
+
c(o) && !p.has(o) && e.push(
|
|
527
|
+
n(
|
|
528
|
+
`dispatch_units[${s.id}].milestones`,
|
|
529
|
+
`unknown milestone "${o}"`
|
|
530
|
+
)
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
f(t.pairwise_overlap) || e.push(
|
|
534
|
+
n(
|
|
535
|
+
"pairwise_overlap",
|
|
536
|
+
"must be an object",
|
|
537
|
+
t.pairwise_overlap
|
|
538
|
+
)
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
return { valid: e.length === 0, errors: e };
|
|
542
|
+
}
|
|
543
|
+
function z(t) {
|
|
544
|
+
const e = N(t);
|
|
545
|
+
if (!e.valid)
|
|
546
|
+
throw new Error(
|
|
547
|
+
`DagJson validation failed:
|
|
548
|
+
${e.errors.map((i) => ` ${i.path}: ${i.message}`).join(`
|
|
549
|
+
`)}`
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
function H(t) {
|
|
553
|
+
const e = L(t);
|
|
554
|
+
if (!e.valid)
|
|
555
|
+
throw new Error(
|
|
556
|
+
`Snapshot validation failed:
|
|
557
|
+
${e.errors.map((i) => ` ${i.path}: ${i.message}`).join(`
|
|
558
|
+
`)}`
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
const S = [
|
|
562
|
+
{
|
|
563
|
+
from: 2,
|
|
564
|
+
to: 3,
|
|
565
|
+
apply: (t) => {
|
|
566
|
+
!t.milestones && t.nodes && (t.milestones = t.nodes, delete t.nodes);
|
|
567
|
+
const e = t.operations;
|
|
568
|
+
e && typeof e == "object" && !Array.isArray(e) && (t.operations = Object.values(e));
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
from: 3,
|
|
573
|
+
to: 4,
|
|
574
|
+
apply: (t) => {
|
|
575
|
+
(!t.providers || Object.keys(t.providers).length === 0) && (t.providers = {
|
|
576
|
+
Haiku: {
|
|
577
|
+
type: "claudecli",
|
|
578
|
+
model_id: "claude-haiku-4-5",
|
|
579
|
+
env_secret: null,
|
|
580
|
+
base_url: null,
|
|
581
|
+
timeout_ms: 6e4,
|
|
582
|
+
retry_config: {
|
|
583
|
+
retries: 3,
|
|
584
|
+
min_timeout: 1e3,
|
|
585
|
+
max_timeout: 3e4,
|
|
586
|
+
factor: 2
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
Sonnet: {
|
|
590
|
+
type: "claudecli",
|
|
591
|
+
model_id: "claude-sonnet-4-5",
|
|
592
|
+
env_secret: null,
|
|
593
|
+
base_url: null,
|
|
594
|
+
timeout_ms: 12e4,
|
|
595
|
+
retry_config: {
|
|
596
|
+
retries: 3,
|
|
597
|
+
min_timeout: 1e3,
|
|
598
|
+
max_timeout: 3e4,
|
|
599
|
+
factor: 2
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
Opus: {
|
|
603
|
+
type: "claudecli",
|
|
604
|
+
model_id: "claude-opus-4-5",
|
|
605
|
+
env_secret: null,
|
|
606
|
+
base_url: null,
|
|
607
|
+
timeout_ms: 3e5,
|
|
608
|
+
retry_config: {
|
|
609
|
+
retries: 3,
|
|
610
|
+
min_timeout: 1e3,
|
|
611
|
+
max_timeout: 3e4,
|
|
612
|
+
factor: 2
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}), (!t.effort_max_tokens || Object.keys(t.effort_max_tokens).length === 0) && (t.effort_max_tokens = {
|
|
616
|
+
low: 1024,
|
|
617
|
+
medium: 4096,
|
|
618
|
+
high: 8192,
|
|
619
|
+
xhigh: 16384,
|
|
620
|
+
max: 32768
|
|
621
|
+
}), t.optimization || (t.optimization = {
|
|
622
|
+
sentinel_fanout: {
|
|
623
|
+
enabled: !0,
|
|
624
|
+
write_multiplier: 1.25,
|
|
625
|
+
read_multiplier: 0.1,
|
|
626
|
+
hit_probability: 0.9
|
|
627
|
+
},
|
|
628
|
+
b_per_tier: { Haiku: 8e3, Sonnet: 15e3, Opus: 27e3 },
|
|
629
|
+
context_window_per_tier: { Haiku: 16e3, Sonnet: 16e3, Opus: 32e3 },
|
|
630
|
+
context_window_override: null,
|
|
631
|
+
b_override: null
|
|
632
|
+
});
|
|
633
|
+
let e = [];
|
|
634
|
+
Array.isArray(t.operations) ? e = t.operations : t.operations && typeof t.operations == "object" && (e = Object.values(t.operations));
|
|
635
|
+
for (const i of e)
|
|
636
|
+
if (typeof i == "object" && i !== null) {
|
|
637
|
+
const r = i;
|
|
638
|
+
r.type === void 0 && (r.type = "generative"), r.criteria === void 0 && (r.criteria = []), r.tool === void 0 && (r.tool = null), r.args === void 0 && (r.args = null);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
];
|
|
643
|
+
function K(t, e, i) {
|
|
644
|
+
if (t === e)
|
|
645
|
+
return;
|
|
646
|
+
let r = t;
|
|
647
|
+
for (const p of [...S].sort((d, l) => d.from - l.from))
|
|
648
|
+
if (p.from === r && (p.apply(i), r = p.to, r === e)) {
|
|
649
|
+
i.schema_version = e;
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
throw new Error(
|
|
653
|
+
`migrateDag: no path from v${t} to v${e}. Available: [${S.map(
|
|
654
|
+
(p) => `v${p.from}→v${p.to}`
|
|
655
|
+
).join(", ")}]`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
export {
|
|
659
|
+
x as VALID_OPS_BY_KIND,
|
|
660
|
+
R as WRITE_CLASS_ACTIONS,
|
|
661
|
+
z as assertValidDagJson,
|
|
662
|
+
H as assertValidSnapshot,
|
|
663
|
+
j as isValidOpForKind,
|
|
664
|
+
K as migrateDag,
|
|
665
|
+
N as validateDagJson,
|
|
666
|
+
L as validateSnapshot
|
|
667
|
+
};
|
package/lib/migrate.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function migrateDag(fromVersion: number, toVersion: number, dag: Record<string, unknown>): void;
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* types.ts — Complete TypeScript type system for the dispatch plan ecosystem.
|
|
3
|
+
*
|
|
4
|
+
* Source: docs/plan/dispatch-completion/superseded/dispatch-optimizer/PROPOSED_DAG_STRUCTURE.md
|
|
5
|
+
* Design decisions: D-01 through D-18 in DECISIONS.md
|
|
6
|
+
*
|
|
7
|
+
* Field provenance: dag | derived | scheduler | optimizer | clock | gitnexus
|
|
8
|
+
* Zero dependencies. Pure TypeScript. platform:shared.
|
|
9
|
+
*/
|
|
10
|
+
/** D-03 + D-18 — which executor the orchestrator routes this operation to. */
|
|
11
|
+
export type OperationType = 'automated' | 'tool-call' | 'generative';
|
|
12
|
+
export type OperationAction = 'create' | 'delete' | 'move' | 'rename' | 'modify-signature' | 'modify-body' | 'add-export' | 'remove-export' | 'guard' | 'exec' | 'dag.inject' | 'dag.wait' | 'dag.add-milestone' | 'dag.set-field' | 'dag.clear-pending' | 'dag.append-dispatch-log' | 'fs.move' | 'fs.delete' | 'fs.scaffold';
|
|
13
|
+
export declare const WRITE_CLASS_ACTIONS: ReadonlySet<OperationAction>;
|
|
14
|
+
export type CodeKind = 'function' | 'interface' | 'type' | 'class' | 'enum' | 'const' | 'script';
|
|
15
|
+
export type ConfigKind = 'config' | 'env' | 'schema' | 'manifest';
|
|
16
|
+
export type ShapeKind = CodeKind | ConfigKind | 'doc' | 'structured-output';
|
|
17
|
+
export type KindFamily = 'code-config' | 'doc' | 'structured' | 'tool-call';
|
|
18
|
+
export type MilestoneStatus = 'pending' | 'pending-surfaced' | 'in_progress' | 'complete' | 'failed' | 'skipped';
|
|
19
|
+
export type DispatchUnitStatus = 'pending' | 'in_progress' | 'complete' | 'failed';
|
|
20
|
+
export type OperationStatus = 'pending' | 'in_progress' | 'complete' | 'failed' | 'skipped';
|
|
21
|
+
export type GuardResult = 'pass' | 'fail';
|
|
22
|
+
export type MilestoneGuardResult = 'pass' | 'fail' | 'pending';
|
|
23
|
+
export type Provenance = 'gitnexus' | 'manual' | 'assumed' | 'vendored';
|
|
24
|
+
export type Confidence = 'verified' | 'vendored' | 'documented' | 'assumed';
|
|
25
|
+
export type KiSource = 'estimate' | 'calibrated' | 'actual';
|
|
26
|
+
export type DispatchKind = 'planning' | 'execution';
|
|
27
|
+
export type ProviderType = 'anthropic' | 'openai' | 'claudecli';
|
|
28
|
+
export type SentinelRole = 'prewarm' | 'payload' | 'solo';
|
|
29
|
+
export type ModelTier = 'Haiku' | 'Sonnet' | 'Opus';
|
|
30
|
+
export type EffortTier = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
31
|
+
export type PlanKind = 'brownfield' | 'greenfield';
|
|
32
|
+
export type ShapeOpType = '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' | 'remove-export';
|
|
33
|
+
export declare const VALID_OPS_BY_KIND: Record<string, ReadonlySet<ShapeOpType>>;
|
|
34
|
+
export declare function isValidOpForKind(kind: string, op: ShapeOpType): boolean;
|
|
35
|
+
export interface ShapeOpDag {
|
|
36
|
+
op: ShapeOpType;
|
|
37
|
+
target: string | null;
|
|
38
|
+
to: string | null;
|
|
39
|
+
position: number | null;
|
|
40
|
+
required: boolean | null;
|
|
41
|
+
}
|
|
42
|
+
export interface ShapeOpSnapshot extends ShapeOpDag {
|
|
43
|
+
from: string | null;
|
|
44
|
+
breaking: boolean | null;
|
|
45
|
+
severity: 'error' | 'warning' | 'info' | null;
|
|
46
|
+
}
|
|
47
|
+
export interface ShapeCode {
|
|
48
|
+
kind: CodeKind;
|
|
49
|
+
ops: ShapeOpDag[];
|
|
50
|
+
description?: null;
|
|
51
|
+
objective?: null;
|
|
52
|
+
required_sections?: null;
|
|
53
|
+
schema?: null;
|
|
54
|
+
}
|
|
55
|
+
export interface ShapeConfig {
|
|
56
|
+
kind: ConfigKind;
|
|
57
|
+
ops: ShapeOpDag[];
|
|
58
|
+
description?: null;
|
|
59
|
+
objective?: null;
|
|
60
|
+
required_sections?: null;
|
|
61
|
+
schema?: null;
|
|
62
|
+
}
|
|
63
|
+
export interface ShapeDoc {
|
|
64
|
+
kind: 'doc';
|
|
65
|
+
ops?: null;
|
|
66
|
+
description: string;
|
|
67
|
+
objective: string;
|
|
68
|
+
required_sections: string[];
|
|
69
|
+
schema?: null;
|
|
70
|
+
}
|
|
71
|
+
export interface ShapeStructuredOutput {
|
|
72
|
+
kind: 'structured-output';
|
|
73
|
+
ops?: null;
|
|
74
|
+
description?: null;
|
|
75
|
+
objective?: null;
|
|
76
|
+
required_sections?: null;
|
|
77
|
+
schema: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
export interface ShapeNull {
|
|
80
|
+
kind: null;
|
|
81
|
+
ops?: null;
|
|
82
|
+
description?: null;
|
|
83
|
+
objective?: null;
|
|
84
|
+
required_sections?: null;
|
|
85
|
+
schema?: null;
|
|
86
|
+
}
|
|
87
|
+
export type Shape = ShapeCode | ShapeConfig | ShapeDoc | ShapeStructuredOutput | ShapeNull;
|
|
88
|
+
export interface ShapeCodeSnapshot extends Omit<ShapeCode, 'ops'> {
|
|
89
|
+
ops: ShapeOpSnapshot[];
|
|
90
|
+
}
|
|
91
|
+
export interface ShapeConfigSnapshot extends Omit<ShapeConfig, 'ops'> {
|
|
92
|
+
ops: ShapeOpSnapshot[];
|
|
93
|
+
}
|
|
94
|
+
export type ShapeSnapshot = ShapeCodeSnapshot | ShapeConfigSnapshot | ShapeDoc | ShapeStructuredOutput | ShapeNull;
|
|
95
|
+
export interface BlastRadiusEntry {
|
|
96
|
+
file: string;
|
|
97
|
+
symbol: string;
|
|
98
|
+
impact: 'implements' | 'calls' | 'imports' | 'extends' | 're-exports' | 'overrides';
|
|
99
|
+
consumer: 'current' | 'future';
|
|
100
|
+
}
|
|
101
|
+
export interface OperationConflict {
|
|
102
|
+
detected: boolean;
|
|
103
|
+
competing_op: string | null;
|
|
104
|
+
op_key: string | null;
|
|
105
|
+
resolution: 'safe-merge' | 'warning' | 'error' | null;
|
|
106
|
+
}
|
|
107
|
+
export interface RetryConfig {
|
|
108
|
+
retries: number;
|
|
109
|
+
min_timeout: number;
|
|
110
|
+
max_timeout: number;
|
|
111
|
+
factor: number;
|
|
112
|
+
}
|
|
113
|
+
export interface ProviderConfig {
|
|
114
|
+
type: ProviderType;
|
|
115
|
+
model_id: string;
|
|
116
|
+
env_secret: string | null;
|
|
117
|
+
base_url: string | null;
|
|
118
|
+
timeout_ms: number;
|
|
119
|
+
retry_config: RetryConfig;
|
|
120
|
+
}
|
|
121
|
+
export interface Turn {
|
|
122
|
+
turn: number;
|
|
123
|
+
input_tokens: number;
|
|
124
|
+
output_tokens: number;
|
|
125
|
+
t: string;
|
|
126
|
+
/**
|
|
127
|
+
* Number of real model calls this synthesized turn represents. Added for
|
|
128
|
+
* DEBT-DISPATCH-008: agent-mcp's MCP surface exposes only aggregate usage
|
|
129
|
+
* per task (no per-turn breakdown — see agent-runner.ts `SynthesizedTurn`/
|
|
130
|
+
* `DispatchUsageReport`), so a dispatcher collapses a task's entire usage
|
|
131
|
+
* into ONE `Turn` and needs somewhere to carry `modelCalls` through.
|
|
132
|
+
* Optional and nullable for backward compatibility: every dag.json written
|
|
133
|
+
* before this field existed — and any producer that doesn't track model
|
|
134
|
+
* call counts — remains valid without it.
|
|
135
|
+
*/
|
|
136
|
+
model_calls?: number | null;
|
|
137
|
+
}
|
|
138
|
+
export interface DispatchResult {
|
|
139
|
+
op_id: string;
|
|
140
|
+
status: 'complete' | 'failed' | 'skipped';
|
|
141
|
+
guard_result: GuardResult | null;
|
|
142
|
+
guard_output: string | null;
|
|
143
|
+
guard_ran_at: string | null;
|
|
144
|
+
/**
|
|
145
|
+
* Real outcome payload for `type: "tool-call"` operations (BUG-DISPATCH-EXEC-001
|
|
146
|
+
* / D-13, D-18). `null`/absent for every other op kind (generative,
|
|
147
|
+
* automated-guard). On success, the tool handler's own return value (e.g.
|
|
148
|
+
* `{ path, to }` for `fs.move`, `{ slug }` for `dag.add-milestone`). On
|
|
149
|
+
* failure, `{ error: string }` — never a silent 'skipped' with no payload.
|
|
150
|
+
* Optional for backward compatibility: every `dispatch_log` entry written
|
|
151
|
+
* before this field existed remains valid without it.
|
|
152
|
+
*/
|
|
153
|
+
tool_result?: unknown | null;
|
|
154
|
+
}
|
|
155
|
+
export interface DispatchNote {
|
|
156
|
+
level: 'info' | 'warn' | 'error';
|
|
157
|
+
text: string;
|
|
158
|
+
}
|
|
159
|
+
export interface DispatchLogEntry {
|
|
160
|
+
id: string;
|
|
161
|
+
kind: DispatchKind;
|
|
162
|
+
provider: 'anthropic' | 'openai' | 'deepseek' | 'google' | 'local' | 'claudecli' | 'teammate';
|
|
163
|
+
model: string | null;
|
|
164
|
+
agent: string;
|
|
165
|
+
effort: EffortTier | null;
|
|
166
|
+
started_at: string;
|
|
167
|
+
completed_at: string | null;
|
|
168
|
+
operations: string[];
|
|
169
|
+
turns: Turn[];
|
|
170
|
+
results: DispatchResult[];
|
|
171
|
+
notes: DispatchNote[];
|
|
172
|
+
}
|
|
173
|
+
export interface OperationDag {
|
|
174
|
+
id: string;
|
|
175
|
+
milestone: string;
|
|
176
|
+
depends_on: string[];
|
|
177
|
+
type: OperationType;
|
|
178
|
+
action: OperationAction;
|
|
179
|
+
file: string | null;
|
|
180
|
+
symbol: string | null;
|
|
181
|
+
provenance: Provenance | null;
|
|
182
|
+
confidence: Confidence | null;
|
|
183
|
+
audit_check: string | null;
|
|
184
|
+
criteria: string[];
|
|
185
|
+
tool: string | null;
|
|
186
|
+
args: Record<string, unknown> | null;
|
|
187
|
+
guard: string | null;
|
|
188
|
+
to_file: string | null;
|
|
189
|
+
to_symbol: string | null;
|
|
190
|
+
ki_estimate: number | null;
|
|
191
|
+
ki_source: KiSource | null;
|
|
192
|
+
authored_by: string;
|
|
193
|
+
status: OperationStatus;
|
|
194
|
+
shape: Shape | null;
|
|
195
|
+
}
|
|
196
|
+
export interface OperationSnapshot extends Omit<OperationDag, 'shape'> {
|
|
197
|
+
shape: ShapeSnapshot | null;
|
|
198
|
+
dispatch_ids: string[];
|
|
199
|
+
attempt_count: number;
|
|
200
|
+
guard_result: GuardResult | null;
|
|
201
|
+
guard_output: string | null;
|
|
202
|
+
guard_ran_at: string | null;
|
|
203
|
+
blast_radius: BlastRadiusEntry[];
|
|
204
|
+
conflict: OperationConflict;
|
|
205
|
+
tokens_actual: number | null;
|
|
206
|
+
}
|
|
207
|
+
export interface MilestoneDag {
|
|
208
|
+
description: string;
|
|
209
|
+
rationale?: string;
|
|
210
|
+
authored_by: string;
|
|
211
|
+
pending: string | null;
|
|
212
|
+
triggered_by: string | null;
|
|
213
|
+
phase: string;
|
|
214
|
+
depends_on: string[];
|
|
215
|
+
agent: string | null;
|
|
216
|
+
model: ModelTier | null;
|
|
217
|
+
effort: EffortTier | null;
|
|
218
|
+
two_stage: boolean;
|
|
219
|
+
read_only: string[];
|
|
220
|
+
guard: string | null;
|
|
221
|
+
}
|
|
222
|
+
export interface CrossPlanDep {
|
|
223
|
+
plan: string;
|
|
224
|
+
milestone: string;
|
|
225
|
+
}
|
|
226
|
+
export type PairwiseOverlapMap = Record<string, number>;
|
|
227
|
+
export interface OpenQuestion {
|
|
228
|
+
id: string;
|
|
229
|
+
text: string;
|
|
230
|
+
blocking: string;
|
|
231
|
+
surfaced: boolean;
|
|
232
|
+
raised_at_dispatch: string | null;
|
|
233
|
+
raised_at_turn: number | null;
|
|
234
|
+
answered: boolean;
|
|
235
|
+
answer: string | null;
|
|
236
|
+
}
|
|
237
|
+
export interface MilestoneSnapshot extends MilestoneDag {
|
|
238
|
+
context: string;
|
|
239
|
+
wave: number;
|
|
240
|
+
eligible: boolean;
|
|
241
|
+
status: MilestoneStatus;
|
|
242
|
+
started_at: string | null;
|
|
243
|
+
completed_at: string | null;
|
|
244
|
+
guard_result: MilestoneGuardResult | null;
|
|
245
|
+
guard_output: string | null;
|
|
246
|
+
artifacts: string[];
|
|
247
|
+
si_bytes: number;
|
|
248
|
+
ki_estimate: number | null;
|
|
249
|
+
tokens_estimated: number | null;
|
|
250
|
+
tokens_actual: number | null;
|
|
251
|
+
}
|
|
252
|
+
export interface SentinelFanoutConfig {
|
|
253
|
+
enabled: boolean;
|
|
254
|
+
write_multiplier: number;
|
|
255
|
+
read_multiplier: number;
|
|
256
|
+
hit_probability: number;
|
|
257
|
+
}
|
|
258
|
+
export interface OptimizationConfig {
|
|
259
|
+
sentinel_fanout: SentinelFanoutConfig;
|
|
260
|
+
b_per_tier: Record<string, number | null>;
|
|
261
|
+
context_window_per_tier: Record<string, number>;
|
|
262
|
+
context_window_override: Record<string, number> | null;
|
|
263
|
+
b_override: Record<string, number> | null;
|
|
264
|
+
}
|
|
265
|
+
export interface DagJson {
|
|
266
|
+
schema_version: number;
|
|
267
|
+
plan_kind: PlanKind;
|
|
268
|
+
description: string;
|
|
269
|
+
problem: string;
|
|
270
|
+
approach: string;
|
|
271
|
+
executor: string;
|
|
272
|
+
executor_model?: ModelTier;
|
|
273
|
+
executor_effort?: EffortTier;
|
|
274
|
+
phases: string[];
|
|
275
|
+
terminal: string | string[];
|
|
276
|
+
assumed_baseline?: string[] | Record<string, unknown>;
|
|
277
|
+
cross_plan_deps?: CrossPlanDep[];
|
|
278
|
+
optimization: OptimizationConfig;
|
|
279
|
+
providers: Record<string, ProviderConfig>;
|
|
280
|
+
effort_max_tokens: Record<string, number>;
|
|
281
|
+
milestones: Record<string, MilestoneDag>;
|
|
282
|
+
operations: OperationDag[] | Record<string, OperationDag>;
|
|
283
|
+
dispatch_log: DispatchLogEntry[];
|
|
284
|
+
}
|
|
285
|
+
export interface SnapshotOptimization {
|
|
286
|
+
tokens_naive: number | null;
|
|
287
|
+
sentinel_fanout: SentinelFanoutConfig;
|
|
288
|
+
context_window_override: Record<string, number> | null;
|
|
289
|
+
b_override: Record<string, number> | null;
|
|
290
|
+
b_per_tier: Record<string, number | null>;
|
|
291
|
+
b_eff_per_tier: Record<string, number | null>;
|
|
292
|
+
context_window_per_tier: Record<string, number>;
|
|
293
|
+
}
|
|
294
|
+
export interface DagSnapshot {
|
|
295
|
+
snapshot_at: string;
|
|
296
|
+
snapshot_version: number;
|
|
297
|
+
plan: string;
|
|
298
|
+
schema_version: number;
|
|
299
|
+
plan_kind: PlanKind;
|
|
300
|
+
description: string;
|
|
301
|
+
problem: string;
|
|
302
|
+
approach: string;
|
|
303
|
+
executor: string;
|
|
304
|
+
executor_model?: ModelTier;
|
|
305
|
+
executor_effort?: EffortTier;
|
|
306
|
+
phases: string[];
|
|
307
|
+
terminal: string | string[];
|
|
308
|
+
assumed_baseline?: string[] | Record<string, unknown>;
|
|
309
|
+
cross_plan_deps?: CrossPlanDep[];
|
|
310
|
+
optimization: SnapshotOptimization;
|
|
311
|
+
milestones: Record<string, MilestoneSnapshot>;
|
|
312
|
+
operations: OperationSnapshot[];
|
|
313
|
+
pairwise_overlap: PairwiseOverlapMap;
|
|
314
|
+
dispatch_units?: DispatchUnit[];
|
|
315
|
+
open_questions: OpenQuestion[];
|
|
316
|
+
}
|
|
317
|
+
export interface DispatchUnit {
|
|
318
|
+
id: string;
|
|
319
|
+
milestones: string[];
|
|
320
|
+
operations: string[];
|
|
321
|
+
model: ModelTier | null;
|
|
322
|
+
effort: EffortTier | null;
|
|
323
|
+
two_stage: boolean;
|
|
324
|
+
provider: ProviderConfig | null;
|
|
325
|
+
agent_name: string;
|
|
326
|
+
mcp_servers: Record<string, unknown> | null;
|
|
327
|
+
resolved_max_tokens: number | null;
|
|
328
|
+
background: true;
|
|
329
|
+
prompt: string | null;
|
|
330
|
+
context_files: string[];
|
|
331
|
+
si_bytes: number;
|
|
332
|
+
tokens_estimated: number | null;
|
|
333
|
+
fits_context_window: boolean;
|
|
334
|
+
sentinel_role: SentinelRole | null;
|
|
335
|
+
dispatch_log_id: string | null;
|
|
336
|
+
remote_task_id: string | null;
|
|
337
|
+
result: string | null;
|
|
338
|
+
status: DispatchUnitStatus;
|
|
339
|
+
started_at: string | null;
|
|
340
|
+
completed_at: string | null;
|
|
341
|
+
tokens_actual: number | null;
|
|
342
|
+
}
|
|
343
|
+
export interface ValidationError {
|
|
344
|
+
path: string;
|
|
345
|
+
message: string;
|
|
346
|
+
value?: unknown;
|
|
347
|
+
}
|
|
348
|
+
export interface ValidationResult {
|
|
349
|
+
valid: boolean;
|
|
350
|
+
errors: ValidationError[];
|
|
351
|
+
}
|
|
352
|
+
export interface IOptimizerDeps {
|
|
353
|
+
bPerTier: Record<string, number>;
|
|
354
|
+
contextWindowPerTier: Record<string, number>;
|
|
355
|
+
fileSizes?: (paths: string[]) => Map<string, number>;
|
|
356
|
+
readFiles?: (paths: string[]) => Map<string, string>;
|
|
357
|
+
dispatchLog?: DispatchLogEntry[];
|
|
358
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DagJson, DagSnapshot, ValidationResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
export declare function validateDagJson(dag: unknown): ValidationResult;
|
|
4
|
+
export declare function validateSnapshot(snapshot: unknown): ValidationResult;
|
|
5
|
+
export declare function assertValidDagJson(dag: unknown): asserts dag is DagJson;
|
|
6
|
+
export declare function assertValidSnapshot(s: unknown): asserts s is DagSnapshot;
|