ex-workflow 0.3.0-stage → 0.4.0-stage

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +16 -3
  3. package/dist/adapters/index.cjs +1 -1
  4. package/dist/adapters/index.mjs +1 -1
  5. package/dist/chunk-36M6OVUJ.mjs +2 -0
  6. package/dist/chunk-36M6OVUJ.mjs.map +1 -0
  7. package/dist/{chunk-4A4TD4MH.cjs → chunk-7KF5K3L7.cjs} +2 -2
  8. package/dist/{chunk-4A4TD4MH.cjs.map → chunk-7KF5K3L7.cjs.map} +1 -1
  9. package/dist/{chunk-2IKIBB73.cjs → chunk-CWBH7H52.cjs} +2 -2
  10. package/dist/{chunk-2IKIBB73.cjs.map → chunk-CWBH7H52.cjs.map} +1 -1
  11. package/dist/chunk-DXC2RSN5.cjs +3 -0
  12. package/dist/chunk-DXC2RSN5.cjs.map +1 -0
  13. package/dist/{chunk-UOGNVWVO.mjs → chunk-GATJZYTB.mjs} +2 -2
  14. package/dist/{chunk-UOGNVWVO.mjs.map → chunk-GATJZYTB.mjs.map} +1 -1
  15. package/dist/{chunk-ZX4DAMTG.mjs → chunk-GFH2FEZH.mjs} +2 -2
  16. package/dist/{chunk-ZX4DAMTG.mjs.map → chunk-GFH2FEZH.mjs.map} +1 -1
  17. package/dist/{chunk-NN3XJUHP.cjs → chunk-HHC5EZ54.cjs} +2 -2
  18. package/dist/{chunk-NN3XJUHP.cjs.map → chunk-HHC5EZ54.cjs.map} +1 -1
  19. package/dist/{chunk-TMKCALFT.cjs → chunk-KSKEFYY7.cjs} +2 -2
  20. package/dist/{chunk-TMKCALFT.cjs.map → chunk-KSKEFYY7.cjs.map} +1 -1
  21. package/dist/chunk-KUUIAKEJ.cjs +2 -0
  22. package/dist/chunk-KUUIAKEJ.cjs.map +1 -0
  23. package/dist/{chunk-R27STIER.mjs → chunk-L2ZN6HEL.mjs} +2 -2
  24. package/dist/{chunk-R27STIER.mjs.map → chunk-L2ZN6HEL.mjs.map} +1 -1
  25. package/dist/{chunk-BJEOTG6P.mjs → chunk-NDORREWR.mjs} +2 -2
  26. package/dist/{chunk-BJEOTG6P.mjs.map → chunk-NDORREWR.mjs.map} +1 -1
  27. package/dist/{chunk-WOKNWJKU.mjs → chunk-NZ2DIDOD.mjs} +2 -2
  28. package/dist/{chunk-WOKNWJKU.mjs.map → chunk-NZ2DIDOD.mjs.map} +1 -1
  29. package/dist/chunk-OHSQ52DW.mjs +6 -0
  30. package/dist/chunk-OHSQ52DW.mjs.map +1 -0
  31. package/dist/chunk-RSKZVOYC.cjs +6 -0
  32. package/dist/chunk-RSKZVOYC.cjs.map +1 -0
  33. package/dist/chunk-S22CPYXJ.mjs +3 -0
  34. package/dist/chunk-S22CPYXJ.mjs.map +1 -0
  35. package/dist/{chunk-FLCYD2QF.mjs → chunk-SHAPFMVP.mjs} +2 -2
  36. package/dist/{chunk-FLCYD2QF.mjs.map → chunk-SHAPFMVP.mjs.map} +1 -1
  37. package/dist/{chunk-23P7C25E.cjs → chunk-SJRRQZ3R.cjs} +2 -2
  38. package/dist/{chunk-23P7C25E.cjs.map → chunk-SJRRQZ3R.cjs.map} +1 -1
  39. package/dist/{chunk-7HZXZF3L.cjs → chunk-UM5X2JHB.cjs} +2 -2
  40. package/dist/{chunk-7HZXZF3L.cjs.map → chunk-UM5X2JHB.cjs.map} +1 -1
  41. package/dist/cli/bin.cjs +1 -1
  42. package/dist/cli/bin.cjs.map +1 -1
  43. package/dist/cli/bin.mjs +1 -1
  44. package/dist/cli/bin.mjs.map +1 -1
  45. package/dist/cli/index.cjs +1 -1
  46. package/dist/cli/index.mjs +1 -1
  47. package/dist/index.cjs +1 -1
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +5 -5
  50. package/dist/index.d.ts +5 -5
  51. package/dist/index.mjs +1 -1
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/kanban/index.cjs +1 -1
  54. package/dist/kanban/index.mjs +1 -1
  55. package/dist/schema/index.cjs +2 -0
  56. package/dist/schema/index.cjs.map +1 -0
  57. package/dist/schema/index.d.cts +57 -0
  58. package/dist/schema/index.d.ts +57 -0
  59. package/dist/schema/index.mjs +2 -0
  60. package/dist/schema/index.mjs.map +1 -0
  61. package/dist/scrum/index.cjs +1 -1
  62. package/dist/scrum/index.mjs +1 -1
  63. package/dist/types.d.cts +9 -2
  64. package/dist/types.d.ts +9 -2
  65. package/dist/waterfall/index.cjs +1 -1
  66. package/dist/waterfall/index.mjs +1 -1
  67. package/package.json +18 -2
  68. package/dist/chunk-6R3YFUUV.cjs +0 -6
  69. package/dist/chunk-6R3YFUUV.cjs.map +0 -1
  70. package/dist/chunk-AUZIQPFT.cjs +0 -2
  71. package/dist/chunk-AUZIQPFT.cjs.map +0 -1
  72. package/dist/chunk-P4P4JTE5.mjs +0 -2
  73. package/dist/chunk-P4P4JTE5.mjs.map +0 -1
  74. package/dist/chunk-VGD4V5BA.mjs +0 -6
  75. package/dist/chunk-VGD4V5BA.mjs.map +0 -1
@@ -1,2 +1,2 @@
1
- import {f,b as b$2,a as a$1}from'./chunk-ZX4DAMTG.mjs';import {c,u,x,o,n,i,j as j$1,G as G$1,M as M$1,a,I as I$1}from'./chunk-FLCYD2QF.mjs';import {b as b$1,c as c$1}from'./chunk-2FRRD6A3.mjs';import {timSort}from'exsorted';var je=["requirements","design","implementation","verification","deployment","maintenance"],se={requirements:["srs"],design:["design-doc","interface-spec"],implementation:["code-baseline"],verification:["test-report","traceability-matrix"],deployment:["release-notes","deployment-record"],maintenance:["change-log"]},oe={requirements:"business-analyst",design:"architect",deployment:"release-manager"},ae=e=>`${e}-gate`,de="change-control",Ie=["order-backlog","define-acceptance","facilitate","deliver","review","verify","approve-gate","manage-flow","control-change","escalate"],Ee=e=>e.charAt(0).toUpperCase()+e.slice(1);function Te(){return je.map(e=>{let t={id:e,name:Ee(e),deliverables:[...se[e]??[]],gate:{id:ae(e),requires:[{capability:"approve-gate"}],evidence:[],onFail:{action:"block"}}},i=oe[e];return i!==void 0&&(t.deliverBy=i),t})}function k(e){return e.config}var j=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),X=e=>Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.trim()!=="");function Ke(e,t){if(e===void 0)return;j(e)||b$1("config-invalid",`${t}.budget must be an object`,'e.g. { "tokens": 400000 }');let i={};for(let s of ["tokens","turns","wallclockMs"]){let f=e[s];f!==void 0&&((typeof f!="number"||!Number.isFinite(f)||f<0)&&b$1("config-invalid",`${t}.budget.${s} must be a non-negative number`,"omit it for no limit"),i[s]=f);}return i}function De(e,t){return (!Array.isArray(e)||e.length===0)&&b$1("config-invalid",`${t} must be a non-empty array of "human" | { capability }`,'e.g. ["human", { "capability": "approve-gate" }]'),e.map(i=>i==="human"?"human":j(i)&&typeof i.capability=="string"&&Ie.includes(i.capability)?{capability:i.capability}:b$1("config-invalid",`${t} entry ${JSON.stringify(i)} is not "human" or a known capability`,`use "human" or { "capability": one of ${Ie.join(", ")} }`))}function Oe(e,t,i){let s=`waterfall config.phases[${t}]`;j(e)||b$1("config-invalid",`${s} must be an object`,'e.g. { "id": "design" }'),c$1(e.id,`${s}.id`);let f=e.id,d=e.deliverables??se[f]??[];X(d)||b$1("config-invalid",`${s}.deliverables must be a string[] of evidence kinds`,'e.g. ["srs"]');let a;if(e.gate===void 0)a={id:ae(f),requires:[{capability:"approve-gate"}],evidence:[],onFail:{action:"block"}};else {let c=e.gate;(!j(c)||typeof c.id!="string"||c.id.trim()==="")&&b$1("config-invalid",`${s}.gate must be a Gate with an id`,'e.g. { "id": "design-gate", "requires": [{ "capability": "approve-gate" }], "evidence": [] }');let l=c.evidence??[];X(l)||b$1("config-invalid",`${s}.gate.evidence must be a string[]`,"list evidence kinds or omit it"),a={id:c.id,requires:De(c.requires??[{capability:"approve-gate"}],`${s}.gate.requires`),evidence:[...l],onFail:{action:"block"}};}i(f)&&!a.requires.includes("human")&&(a.requires=["human",...a.requires]);let n={id:f,name:typeof e.name=="string"&&e.name.trim()!==""?e.name:Ee(f),deliverables:[...d],gate:a},r=Ke(e.budget,s);r!==void 0&&(n.budget=r);let o=e.deliverBy??oe[f];return o!==void 0&&((typeof o!="string"||o.trim()==="")&&b$1("config-invalid",`${s}.deliverBy must be a role id`,"name the role that delivers this phase or omit it"),n.deliverBy=o),n}function ce(e){let t=e??{};t.phases!==void 0&&!Array.isArray(t.phases)&&b$1("config-invalid","waterfall config.phases must be an array of phases","omit phases for the six classic phases");let i=t.humanGates??"all";i!=="all"&&!X(i)&&b$1("config-invalid",'waterfall config.humanGates must be "all" or a string[] of phase ids','omit it for "all"');let s=i==="all"?()=>true:l=>i.includes(l),f=t.phases===void 0?Te().map((l,u)=>Oe(l,u,s)):t.phases.map((l,u)=>Oe(l,u,s));f.length===0&&b$1("config-invalid","waterfall config.phases needs at least one phase",'e.g. [{ "id": "requirements" }]');let d=f.map(l=>l.id),a=d.find((l,u)=>d.indexOf(l)!==u);if(a!==void 0&&b$1("config-invalid",`duplicate phase id "${a}"`,"give every phase a unique id"),i!=="all")for(let l of i)d.includes(l)||b$1("config-invalid",`waterfall config.humanGates names unknown phase "${l}"`,`phases are: ${d.join(", ")}`);let n=t.changeControl??{};j(n)||b$1("config-invalid","waterfall config.changeControl must be an object",'e.g. { "requiresImpactAnalysis": true, "approvers": ["human"] }'),n.requiresImpactAnalysis!==void 0&&typeof n.requiresImpactAnalysis!="boolean"&&b$1("config-invalid","waterfall config.changeControl.requiresImpactAnalysis must be a boolean","omit it for true");let r={requiresImpactAnalysis:n.requiresImpactAnalysis===void 0?true:n.requiresImpactAnalysis,approvers:De(n.approvers??["human",{capability:"control-change"}],"waterfall config.changeControl.approvers")},o=t.traceability,c;if(o===void 0)c=d.includes("requirements")&&d.includes("design")&&d.includes("verification")?{from:"requirements",to:["design","verification"]}:{from:d[0],to:[]};else {(!j(o)||typeof o.from!="string"||!d.includes(o.from))&&b$1("config-invalid","waterfall config.traceability.from must be a phase id",`phases are: ${d.join(", ")}`);let l=o.to??[];X(l)||b$1("config-invalid","waterfall config.traceability.to must be a string[] of phase ids",`phases are: ${d.join(", ")}`);for(let u of l)d.includes(u)||b$1("config-invalid",`waterfall config.traceability.to names unknown phase "${u}"`,`phases are: ${d.join(", ")}`),d.indexOf(u)<=d.indexOf(o.from)&&b$1("config-invalid",`waterfall config.traceability.to phase "${u}" must come after "${o.from}"`,"trace forward only: from an earlier phase to later ones");c={from:o.from,to:[...l]};}return {phases:f,changeControl:r,traceability:c,humanGates:i==="all"?"all":[...i]}}var L="work",_="review",M="done";function b(e){return e.phases?e.phases:k(e).phases.map(t=>{let i={id:t.id,name:t.name,deliverables:[...t.deliverables],gate:t.gate,status:"pending"};return t.budget&&(i.budget=t.budget),i})}function S(e,t){return {...e,phases:t}}function I(e,t){let i=b(e).findIndex(s=>s.id===t);return i<0&&b$1("config-invalid",`unknown phase "${t}"`,`phases are: ${b(e).map(s=>s.id).join(" \u2192 ")}`),i}function E(e,t){return b(e)[I(e,t)]}function R(e,t){let i=new Set,s=t;for(;s&&!i.has(s.id);){if(s.phase!==void 0)return s.phase;i.add(s.id),s=s.parent!==void 0&&Object.hasOwn(e.items,s.parent)?e.items[s.parent]:void 0;}}function A(e,t){return Object.values(e.items).filter(i=>i.status!=="dropped"&&R(e,i)===t)}function O(e){return b(e).find(t=>t.status==="open")}function le(e){return b(e).find(t=>t.status!=="baselined")}function Ye(e,t){let i=R(e,t);return i!==void 0&&b(e).find(s=>s.id===i)?.status==="baselined"}function Be(e,t){let i=new Set((t.produced??[]).map(s=>s.kind));for(let s of A(e,t.id))for(let f of s.evidence)i.add(f.kind);return i}function G(e,t,i=[]){let s=Be(e,t);for(let d of i)s.add(d);let f=[];for(let d of [...t.deliverables,...t.gate.evidence])f.includes(d)||f.push(d);return f.filter(d=>!s.has(d))}function N(e){let t=b(e).map(s=>s.id),i=k(e).traceability.to.filter(s=>t.includes(s));if(i.length!==0)return i.reduce((s,f)=>t.indexOf(s)>=t.indexOf(f)?s:f)}function Le(e,t,i,s){let f$1=f(e);return !f$1||!f$1.id.startsWith(`${t}#`)?e:{...e,iterations:e.iterations.map(d=>d.id===f$1.id?{...d,endedAt:s,outcome:i}:d)}}function ee(e,t,i,s){let f=E(e,t);f.status!=="open"&&b$1("invalid-transition",`phase "${t}" is ${f.status}, not open`,f.status==="baselined"?"it is already baselined; a change-request reopens it":"kickoff the phase first");let d=A(e,t),a={};for(let c of d)a[c.id]=c;let n=(e.baselines??[]).filter(c=>c.phase===t).length,r={phase:t,version:n+1,at:s,approvedBy:i,itemSnapshot:a},o=S(e,b(e).map(c=>c.id===t?{...c,status:"baselined"}:c));return o={...o,baseline:r,baselines:[...o.baselines??[],r]},o=Le(o,t,"completed",s),c(o,"phase.baselined",i[i.length-1]??"system",{phase:t,version:r.version,approvedBy:i,items:d.map(c=>c.id)},s)}function pe(e,t,i){let s=[];for(let n of t){let r=E(e,n);r.status==="pending"&&b$1("invalid-input",`phase "${n}" was never baselined; there is nothing to reopen`,"remove it from impactAnalysis.reopen"),r.status==="baselined"&&!s.includes(n)&&s.push(n);}let f=b(e).map(n=>s.includes(n.id)?{...n,status:"reopened"}:n),d=null,a=e;if(s.length){let n=Math.min(...s.map(o=>I(e,o))),r=f.find((o,c)=>o.status==="open"&&c>n);r&&(d=r.id,f=f.map(o=>o.id===r.id?{...o,status:"reopened"}:o),a=Le(a,r.id,"cancelled",i));}return {state:S(a,f),reopened:s,suspended:d}}function F(e,t,i,s,f){let d=u(e,t),a=d.impactAnalysis,n=pe(e,a?.reopen??[],f),r=x(n.state,t,{stage:M,status:"done"},i,f);for(let o of n.reopened)r=c(r,"phase.reopened",i,{phase:o,change:t},f);return n.suspended!==null&&(r=c(r,"phase.suspended",i,{phase:n.suspended,change:t},f)),c(r,"change.decided",i,{change:t,decision:"approve",by:i,note:s,reopened:n.reopened,suspended:n.suspended,weight:a?.weight??0,affects:d.affects??[]},f)}function V(e,t,i,s,f){let d=u(e,t),a=x(e,t,{status:"dropped"},i,f);return c(a,"change.decided",i,{change:t,decision:"reject",by:i,note:s,reopened:[],suspended:null,weight:0,affects:d.affects??[]},f)}var _e=["policy","skill","memory","spec","review"],Me=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Je(e){return Array.isArray(e)&&e.every(t=>Me(t)&&typeof t.text=="string"&&t.text.trim()!==""&&_e.includes(t.scope))}function Qe(e,t,i){let s=[...t.map(d=>d.id),...i],f=s.find((d,a)=>s.indexOf(d)!==a);f!==void 0&&b$1("invalid-input",`lesson "${f}" is referenced more than once`,"adopt or dismiss each lesson once");for(let d of s){let a=e.lessons.find(n=>n.id===d);a||b$1("invalid-input",`no lesson "${d}"`,`raised lessons: ${e.lessons.filter(n=>n.status==="raised").map(n=>n.id).join(", ")||"(none)"}`),a.status!=="raised"&&b$1("invalid-input",`lesson "${d}" is already ${a.status}`,"only raised lessons can be adopted or dismissed");}}function Ge(e){return (t,i)=>{o(t,i.by,"facilitate");let s=i.phase===void 0?void 0:H(t,i,"phaseRetrospective"),f=i.lessons??[];Je(f)||b$1("invalid-input","phaseRetrospective.lessons entries need a text and a scope",`scope is one of: ${_e.join(", ")}`);let d=i.adopt??[],a$1=i.dismiss??[];return (!Array.isArray(d)||!d.every(n=>Me(n)&&typeof n.id=="string")||!Array.isArray(a$1)||!a$1.every(n=>typeof n=="string"))&&b$1("invalid-input","phaseRetrospective.adopt must be [{ id, suggestedChange? }] and dismiss a string[]",'e.g. { "adopt": [{ "id": "L1" }], "dismiss": ["L2"] }'),Qe(t,d,a$1),M$1(t,e(),{type:"ceremony.phaseRetrospective",by:i.by,payload:i},n=>{let r=n,o=a(i.now),c$1=[],l=m=>{!m||m.kind!=="agreement"||(r.agreements.includes(m.text)||(r={...r,agreements:[...r.agreements,m.text]}),c$1.push(m.text));},u=[];for(let m of f){let g=`L${r.lessons.length+1}`,x={id:g,at:o,text:m.text,scope:m.scope,status:"adopted",from:i.by};m.suggestedChange&&(x.suggestedChange=m.suggestedChange),r={...r,lessons:[...r.lessons,x]},u.push(g),l(m.suggestedChange);}let p=[];for(let m of d)r={...r,lessons:r.lessons.map(g=>g.id===m.id?{...g,status:"adopted",...m.suggestedChange?{suggestedChange:m.suggestedChange}:{}}:g)},p.push(m.id),l(m.suggestedChange??r.lessons.find(g=>g.id===m.id)?.suggestedChange);for(let m of a$1)r={...r,lessons:r.lessons.map(g=>g.id===m?{...g,status:"dismissed"}:g)};return c(r,"phase.retrospective",i.by,{phase:s?.id??null,lessons:u,adopted:p,dismissed:a$1,agreements:c$1},o)})}}var Xe=(e,t)=>e.id<t.id?-1:e.id>t.id?1:0,Ne=(e,t)=>timSort(A(e,t).filter(i=>i.type!=="question"),Xe),et=(e,t)=>(e.traces??[]).includes(t.id)||(t.traces??[]).includes(e.id);function T(e){let t=k(e).traceability,i=b(e).map(a=>a.id),s=t.to.filter(a=>i.includes(a)),f=Ne(e,t.from).map(a=>{let n={};for(let r of s)n[r]=Ne(e,r).filter(o=>et(a,o)).map(o=>o.id);return {item:a.id,links:n}}),d=f.map(a=>({item:a.item,phases:s.filter(n=>a.links[n].length===0)})).filter(a=>a.phases.length>0);return {from:t.from,to:s,rows:f,missing:d,coverage:{traced:f.length-d.length,total:f.length}}}function fe(e,t){return T(e).rows.filter(i=>(i.links[t]??[]).length===0).map(i=>i.item)}var tt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function H(e,t,i){let s=t.phase;return (typeof s!="string"||s.trim()==="")&&b$1("invalid-input",`${i} needs phase: string`,`pass one of: ${b(e).map(f=>f.id).join(", ")}`),E(e,s)}function Fe(e,t,i,s,f,d){let a=S(e,b(e).map(n=>n.id===t?{...n,produced:[...n.produced??[],{kind:i,ref:s,by:f,at:d}]}:n));return c(a,"phase.deliverable",f,{phase:t,kind:i,ref:s},d)}function ue(e){let t=(d,a$1,n,r)=>M$1(d,e(),{type:a$1,by:n.by,payload:n},o=>r(o,a(n.now)));return {kickoff:(d,a)=>{o(d,a.by,"facilitate");let n=H(d,a,"kickoff");return t(d,"ceremony.kickoff",a,(r,o)=>{let c$1=r.events.filter(p=>p.type==="phase.opened"&&p.payload.phase===n.id).length+1,l=A(r,n.id).filter(p=>p.status!=="done").map(p=>p.id);r=S(r,b(r).map(p=>p.id===n.id?{...p,status:"open"}:p));let u=n.budget??{};return r={...r,iterations:[...r.iterations,{id:`${n.id}#${c$1}`,goal:n.name,budget:u,spent:a$1,startedAt:o,committed:l,carryover:[]}]},c(r,"phase.opened",a.by,{phase:n.id,version:c$1,items:l,budget:u},o)})},gateReview:(d,a)=>{let n=H(d,a,"gateReview");n.status!=="open"&&b$1("invalid-transition",`phase "${n.id}" is ${n.status}, not open`,n.status==="baselined"?"it is already baselined; a change-request reopens it":`kickoff "${n.id}" first`);let r=n.gate,o=j$1(d,r.id,"approve-gate");a.by!=="human"&&!o.includes(a.by)&&b$1("gate-unmet",`"${a.by}" may not review gate "${r.id}"`,`review as one of: human${o.map(p=>`, ${p}`).join("")}`,{rule:"gate"});let c$1=d.pending.find(p=>p.kind==="gate"&&p.item===void 0&&p.gate===r.id);c$1&&b$1("no-op",`gate "${r.id}" is already awaiting a decision (${c$1.id})`,`decide ${c$1.id} approve|reject`);let l=a.deliverables??[];(!Array.isArray(l)||!l.every(p=>tt(p)&&typeof p.kind=="string"&&p.kind.trim()!==""&&typeof p.ref=="string"))&&b$1("invalid-input","gateReview.deliverables must be [{ kind, ref }]",'e.g. { "deliverables": [{ "kind": "srs", "ref": "docs/srs.md" }] }');let u=l;return t(d,"ceremony.gateReview",a,(p,m)=>{for(let g of u)p=Fe(p,n.id,g.kind,g.ref,a.by,m);if(k(p).traceability.to.includes(n.id)){let g=T(p);p=c(p,"traceability.computed",a.by,{phase:n.id,from:g.from,to:g.to,coverage:g.coverage,missing:g.missing,rows:g.rows},m),n.id===N(p)&&g.missing.length===0&&(p=Fe(p,n.id,"traceability-matrix",`traceability.computed#${p.events[p.events.length-1].seq}`,a.by,m));}if(r.requires.includes("human")&&a.by!=="human"){p=I$1(p,{kind:"gate",gate:r.id,question:`Approve gate "${r.id}" and baseline phase "${n.name}"?`},m);let g=p.pending[p.pending.length-1].id;return c(p,"phase.gate-pending",a.by,{phase:n.id,gate:r.id,by:a.by,pending:g},m)}return ee(p,n.id,[a.by],m)})},changeControlBoard:(d,a)=>{o(d,a.by,"control-change");let n$1=a.change;(typeof n$1!="string"||n$1.trim()==="")&&b$1("invalid-input","changeControlBoard needs change: string (a change-request id)",'e.g. { "change": "CR-1", "decision": "approve", "note": "why" }');let r=u(d,n$1);if(r.type!=="change-request"&&b$1("invalid-input",`item "${n$1}" is a ${r.type}, not a change-request`,"only change-request items go through the board",{items:[n$1]}),(r.status==="done"||r.status==="dropped")&&b$1("invalid-transition",`change "${n$1}" is already ${r.status==="done"?"approved":"rejected"}`,"raise a new change-request",{items:[n$1]}),r.status==="awaiting_human"){let p=d.pending.find(m=>m.item===n$1);b$1("no-op",`change "${n$1}" is awaiting the human decision${p?` (${p.id})`:""}`,`decide ${p?.id??"<pending id>"} approve|reject`,{items:[n$1]});}let o$1=a.decision;o$1!=="approve"&&o$1!=="reject"&&b$1("invalid-input",'changeControlBoard.decision must be "approve" or "reject"',"state the board's decision");let c$1=typeof a.note=="string"?a.note:"",l=k(d).changeControl.approvers;for(let p of l)p==="human"||a.by==="human"||n(d,a.by,p.capability)||b$1("gate-unmet",`"${a.by}" lacks capability "${p.capability}" required by change control`,`decide as one of: human${i(d,p.capability).map(m=>`, ${m.id}`).join("")}`,{rule:"change-control",items:[n$1]});let u$1=l.includes("human")&&a.by!=="human";return t(d,"ceremony.changeControlBoard",a,(p,m)=>{if(u$1){p=I$1(p,{kind:"decision",item:n$1,question:`Change "${n$1}" (${r.title}): the board (${a.by}) recommends ${o$1}${c$1?`: ${c$1}`:""}. Approve or reject the change?`},m);let g=p.pending[p.pending.length-1].id;return c(p,"change.recommended",a.by,{change:n$1,decision:o$1,note:c$1,pending:g},m)}return o$1==="approve"?F(p,n$1,a.by,c$1,m):V(p,n$1,a.by,c$1,m)})},phaseRetrospective:Ge(e)}}function ge(e,t,i,s,f,d){if(t.kind==="gate"&&t.item===void 0&&t.gate!==void 0){let a=b(e).find(o=>o.gate.id===t.gate);if(!a)return e;s!=="human"&&b$1("gate-unmet",`"${s}" may not decide phase gate "${t.gate}" (${t.id}); it awaits a human`,`decide ${t.id} as human`,{rule:"gate"});let n;for(let o=e.events.length-1;o>=0;o--){let c=e.events[o];if(c.type==="phase.gate-pending"&&c.payload.pending===t.id){n=c.by;break}}let r=n!==void 0&&n!==s?[n,s]:[s];return i==="approve"?ee(e,a.id,r,d):c(e,"phase.gate-failed",s,{phase:a.id,gate:t.gate,note:f},d)}if(t.kind==="decision"&&t.item!==void 0&&Object.hasOwn(e.items,t.item)){let a=e.items[t.item];return a.type!=="change-request"?e:(s!=="human"&&b$1("gate-unmet",`"${s}" may not decide change "${a.id}" (${t.id}); change control awaits a human`,`decide ${t.id} as human`,{rule:"change-control",items:[a.id]}),i==="approve"?F(e,a.id,s,f,d):V(e,a.id,s,f,d))}return e}function me(e){let t=k(e).phases.map($=>$.id),i=()=>Object.fromEntries(t.map($=>[$,0])),s=i(),f=i(),d=i(),a=i(),n=i(),r=new Map,o=new Map,c=new Map,l=0,u=0,p=0,m=0,g=0,x=0,we=0,ke=$=>{let w=o.get($),y=r.get($);return w!=="question"&&w!=="change-request"&&y!==void 0&&y in s};for(let $ of e.events){let w=$.payload??{};switch($.type){case "item.added":{let y=w,q=y.phase??(y.parent!==null?r.get(y.parent):void 0);r.set(y.id,q),o.set(y.id,y.type),c.set(y.id,"todo"),y.type==="change-request"&&(p+=1),ke(y.id)&&(s[q]+=1,y.type==="bug"&&(n[q]+=1));break}case "item.transition":{let y=w.id,q=w.to.status,Re=c.get(y);if(c.set(y,q),!ke(y))break;let ne=r.get(y);q==="done"&&Re!=="done"&&(f[ne]+=1),q==="dropped"&&(s[ne]-=1,Re==="done"&&(f[ne]-=1));break}case "item.completed":{let y=r.get(w.id);y!==void 0&&y in a&&(a[y]+=w.tokens??0);break}case "phase.opened":{let y=w.phase;y in d&&(d[y]=(w.budget??{}).tokens??0);break}case "traceability.computed":{let y=w.coverage;l=y.traced,u=y.total;break}case "change.decided":{w.decision==="approve"?(m+=1,x+=w.weight??0,we+=(w.reopened??[]).length):g+=1;break}}}let $e=i(),We=i();for(let $ of t){let w=s[$]??0;$e[$]=w===0?0:(f[$]??0)/w*100,We[$]=a[$]-d[$];}let Ae=m+g;return {phaseCompletion:$e,budgetPlanned:d,budgetSpent:a,scheduleVariance:We,requirementCoverage:u===0?0:l/u,requirementsTraced:l,requirementsTotal:u,defectsPerPhase:n,changeRequests:p,changesApproved:m,changesRejected:g,changeApprovalRate:Ae===0?0:m/Ae,reworkWeight:x,phasesReopened:we}}function he(e){let t=e.phases.map(i=>i.gate.id);return [{id:"project-manager",name:"Project Manager",modelTier:"large",capabilities:["facilitate","control-change","approve-gate","escalate"],canApprove:[...t,de],inputs:["phase-plan","deliverables","change-requests"],outputs:["gate-decisions","baselines","change-decisions"],do_not:["do not implement items yourself","do not reopen a phase without an approved change-request"]},{id:"developer",name:"Developer",modelTier:"small",capabilities:["deliver"],canApprove:[],inputs:["design-doc","interface-spec","brief"],outputs:["code","code-baseline","test-output"],do_not:["do not change requirements or designs; raise a change-request","do not approve your own work"]},{id:"business-analyst",name:"Business Analyst",modelTier:"medium",capabilities:["define-acceptance","deliver"],canApprove:[],inputs:["stakeholder-needs"],outputs:["srs","acceptance-criteria"],do_not:["do not design or implement","do not edit a baselined requirement; raise a change-request"]},{id:"architect",name:"Architect",modelTier:"medium",capabilities:["deliver"],canApprove:[],inputs:["srs"],outputs:["design-doc","interface-spec"],do_not:["do not change requirements; raise a change-request","do not implement"]},{id:"qa",name:"QA",modelTier:"small",capabilities:["verify","review"],canApprove:[],inputs:["srs","design-doc","code-baseline"],outputs:["test-report","review-notes"],do_not:["do not fix defects yourself; raise bugs","do not approve phase gates"]},{id:"release-manager",name:"Release Manager",modelTier:"small",capabilities:["deliver"],canApprove:[],inputs:["code-baseline","test-report"],outputs:["release-notes","deployment-record"],do_not:["do not deploy an unbaselined verification phase"]}]}var v=(e,t,i,s)=>s?{rule:e,severity:"error",item:s,message:t,fix:i}:{rule:e,severity:"error",message:t,fix:i},C=e=>e.payload??{},U=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),z=e=>{let t=C(e).phase;return typeof t=="string"?t:void 0},P=(e,t)=>b(e).find(i=>i.id===t),ye=e=>b(e).map(t=>t.id).join(", "),te=(e,t)=>typeof t=="string"&&Object.hasOwn(e.items,t)?e.items[t]:void 0;function Ve(e,t){if(t.phase!==void 0)return t.phase;let i=te(e,t.parent);return i?R(e,i):void 0}var He=e=>e.type!=="change-request"&&e.type!=="question",Ue=(e,t)=>`raise a change-request: addItem({ type: "change-request", affects: ["${e}"], impactAnalysis: { summary, reopen: ["${t}"], weight } }) and decide it in changeControlBoard`;function ze(e,t){let i=te(e,C(t).change);return i&&i.type==="change-request"?i:void 0}function be(){return [{id:"phase-sequential",severity:"error",check(n,r){let o=[];if(r.type==="ceremony.kickoff"){let c=z(r),l=c===void 0?void 0:P(n,c);if(!l)return [];l.status==="open"&&o.push(v("phase-sequential",`phase "${l.id}" is already open`,`gateReview "${l.id}" when its work is done`)),l.status==="baselined"&&o.push(v("phase-sequential",`phase "${l.id}" is baselined`,"only an approved change-request reopens a baselined phase"));let u=O(n);u&&u.id!==l.id&&o.push(v("phase-sequential",`phase "${u.id}" is still open`,`pass its gate (gateReview "${u.id}") before opening "${l.id}"`));}else if(r.type==="item.add"){let c=C(r).item;if(!U(c)||!He(c))return [];let l=Ve(n,c);l===void 0?o.push(v("phase-sequential",`item "${c.id}" belongs to no phase`,`set phase to one of: ${ye(n)}`,c.id)):P(n,l)||o.push(v("phase-sequential",`item "${c.id}" names unknown phase "${l}"`,`phases are: ${ye(n)}`,c.id));}else if(r.type==="item.edit"){let c=C(r).id,l=C(r).patch,u=te(n,c);if(!u||!U(l)||l.phase===void 0||l.phase===u.phase)return [];o.push(v("phase-sequential",`item "${u.id}" cannot move from phase "${u.phase??"(none)"}" to "${String(l.phase)}"`,`drop "${u.id}" and add a new item in phase "${String(l.phase)}"`,u.id));}return o}},{id:"gate-before-next-phase",severity:"error",check(n,r){if(r.type!=="ceremony.kickoff")return [];let o=z(r),c=b(n),l=o===void 0?-1:c.findIndex(p=>p.id===o);if(l<0)return [];let u=c.slice(0,l).filter(p=>p.status!=="baselined").map(p=>p.id);return u.length===0?[]:[v("gate-before-next-phase",`phase(s) ${u.join(", ")} before "${o}" are not baselined`,`kickoff and gateReview them in order, starting with "${u[0]}"`)]}},{id:"baseline-immutable",severity:"error",check(n,r){let o=c=>(n.baselines??[]).filter(l=>l.phase===c).length||1;if(r.type==="item.edit"){let c=te(n,C(r).id);if(!c)return [];let l=R(n,c);return l===void 0||P(n,l)?.status!=="baselined"?[]:[v("baseline-immutable",`item "${c.id}" is frozen: phase "${l}" is baselined (v${o(l)})`,Ue(c.id,l),c.id)]}if(r.type==="item.add"){let c=C(r).item;if(!U(c)||!He(c))return [];let l=Ve(n,c);return l===void 0||P(n,l)?.status!=="baselined"?[]:[v("baseline-immutable",`cannot add "${c.id}" to baselined phase "${l}" (v${o(l)})`,Ue(c.id,l),c.id)]}return []}},{id:"change-needs-impact-analysis",severity:"error",check(n,r){if(r.type!=="ceremony.changeControlBoard")return [];let o=ze(n,r);if(!o)return [];let c=k(n).changeControl,l=o.impactAnalysis,u=`editItem("${o.id}", { impactAnalysis: { summary: "what changes and why", reopen: ["<phase>"], weight: <points> } })`;if(l===void 0)return c.requiresImpactAnalysis?[v("change-needs-impact-analysis",`change "${o.id}" has no impact analysis`,u,o.id)]:[];let p=[];if((!U(l)||typeof l.summary!="string"||l.summary.trim()==="")&&p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.summary is empty`,u,o.id)),(!Array.isArray(l.reopen)||!l.reopen.every(g=>typeof g=="string"))&&p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.reopen must be a string[] of phase ids`,u,o.id)),(typeof l.weight!="number"||!Number.isFinite(l.weight)||l.weight<0)&&p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.weight must be a non-negative number`,u,o.id)),p.length)return p;let m=C(r).decision==="approve";for(let g of l.reopen){let x=P(n,g);x?m&&x.status==="pending"&&p.push(v("change-needs-impact-analysis",`phase "${g}" was never baselined; it cannot be reopened`,`remove "${g}" from impactAnalysis.reopen`,o.id)):p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.reopen names unknown phase "${g}"`,`phases are: ${ye(n)}`,o.id));}return p}},{id:"requirement-traced",severity:"error",check(n,r){if(r.type!=="ceremony.gateReview")return [];let o=z(r),c=k(n).traceability;return o===void 0||!c.to.includes(o)||!P(n,o)?[]:fe(n,o).map(l=>v("requirement-traced",`item "${l}" of phase "${c.from}" has no trace into "${o}"`,`editItem a "${o}" item with traces: ["${l}"] (or editItem("${l}", { traces: [...] }) while "${c.from}" is not baselined)`,l))}},{id:"deliverables-present",severity:"error",check(n,r){if(r.type!=="ceremony.gateReview")return [];let o=z(r),c=o===void 0?void 0:P(n,o);if(!c)return [];let l=[],u=A(n,c.id).filter(g=>g.status!=="done").map(g=>g.id);u.length&&l.push(v("deliverables-present",`${u.length} item(s) in phase "${c.id}" are not done: ${u.join(", ")}`,"finish them (next/complete) or drop them before the gate"));let p=C(r).deliverables,m=Array.isArray(p)?p.filter(g=>U(g)&&typeof g.kind=="string").map(g=>g.kind):[];c.id===N(n)&&m.push("traceability-matrix");for(let g of G(n,c,m))l.push(v("deliverables-present",`phase "${c.id}" has no deliverable "${g}"`,`pass deliverables: [{ "kind": "${g}", "ref": "<where it lives>" }] to gateReview, or attach evidence of kind "${g}" on an item of the phase`));return l}},{id:"approver-not-author",severity:"error",check(n,r){if(r.by==="human")return [];if(r.type==="ceremony.gateReview"){let o=z(r),c=o===void 0?void 0:P(n,o);if(!c)return [];let l=A(n,c.id).filter(p=>G$1(n,p)===r.by).map(p=>p.id);if(l.length===0)return [];let u=j$1(n,c.gate.id,"approve-gate",r.by);return [v("approver-not-author",`"${r.by}" authored ${l.join(", ")} in phase "${c.id}" and may not approve its gate`,`review the gate as one of: human${u.map(p=>`, ${p}`).join("")}`)]}if(r.type==="ceremony.changeControlBoard"){let o=ze(n,r);if(!o)return [];let c=n.events.find(u=>u.type==="item.added"&&u.payload.id===o.id);if(!c||c.by!==r.by)return [];let l=i(n,"control-change").map(u=>u.id).filter(u=>u!==r.by);return [v("approver-not-author",`"${r.by}" raised change "${o.id}" and may not decide it`,`decide as human${l.map(u=>`, ${u}`).join("")}`,o.id)]}return []}}]}function ve(e){return [{id:L,name:"Work",entryPolicy:[{kind:"dependencies-done"}],exitPolicy:[]},{id:_,name:"Review",entryPolicy:[],exitPolicy:[{kind:"no-open-blockers"}],review:true},{id:M,name:"Done",entryPolicy:[],exitPolicy:[]}]}var nt={backlog:"Requirements Baseline",item:"Work Package",stage:"Step",iteration:"Phase",increment:"Deliverable",ceremony:"Review",gate:"Phase Gate"};function it(e,t){let i=R(e,t);if(i!==void 0)return k(e).phases.find(s=>s.id===i)?.deliverBy}function rt(e){return {phases:b(e).map(i=>{let s=A(e,i.id),f=s.filter(a=>a.status==="done").length,d=G(e,i);return {id:i.id,name:i.name,status:i.status,items:s.length,done:f,missingDeliverables:d,readyForGate:i.status==="open"&&f===s.length&&d.length===0}}),current:le(e)?.id??null,open:O(e)?.id??null,pendingGates:e.pending.filter(i=>i.kind==="gate"&&i.item===void 0&&i.gate!==void 0).map(i=>({pending:i.id,gate:i.gate}))}}function st(){return {name:"waterfall",vocabulary:nt,validateConfig:ce,defaultStages:ve,defaultRoles:he,requiredCapabilities:["facilitate","control-change","approve-gate","deliver","verify"],exclusiveCapabilities:[],plannerOptions(e){return {schedulerMode:"level",roleFor:t=>t.status==="todo"&&t.type!=="question"?it(e,t):void 0}},candidates(e){let t=O(e);return t?Object.values(e.items).filter(i=>(i.status==="todo"||i.status==="review")&&(i.stage===L||i.stage===_)&&i.type!=="change-request"&&R(e,i)===t.id):[]},invariants(e,t){let i=k(e),s=b(e),f=R(e,t),d=f===void 0?void 0:s[I(e,f)],a=s.filter(r=>r.status==="baselined").map(r=>r.id),n=d?.gate.requires.includes("human");return [d?`Phase "${d.name}" (${I(e,d.id)+1}/${s.length}); deliverables: ${d.deliverables.join(", ")||"(none)"}; gate "${d.gate.id}"${n?" needs human approval":""}`:"This item belongs to no phase; it is dispatched only through its parent's phase",`Baselined phases are frozen: ${a.join(", ")||"(none yet)"}; to change their items, raise a change-request with an impact analysis`,i.traceability.to.length?`Traceability: every item of phase "${i.traceability.from}" must trace to an item in ${i.traceability.to.join(", ")} (set traces on either side)`:"Traceability: none configured",`Do not change the scope of "${t.id}" or its acceptance criteria; raise open_questions instead`]},ceremonies:ue(st),rules:be(),metrics:e=>({...me(e)}),humanDefaults:{gates:"all"},report:e=>({...rt(e),coverage:T(e).coverage}),afterDecide:ge,afterComplete(e,t,i){let s=f(e),f$1=O(e);if(!s||!f$1||s.committed.includes(t))return e;let d=e.items[t];if(!d||R(e,d)!==f$1.id)return e;let a=e.accounting[e.accounting.length-1];return !a||a.item!==t?e:{...e,iterations:e.iterations.map(n=>n.id===s.id?{...n,committed:[...n.committed,t],spent:b$2(n.spent,a)}:n)}}}}export{V as A,T as B,fe as C,H as D,ue as E,ge as F,me as G,he as H,be as I,ve as J,nt as K,it as L,rt as M,st as N,je as a,se as b,oe as c,ae as d,de as e,Te as f,k as g,ce as h,L as i,_ as j,M as k,b as l,S as m,I as n,E as o,R as p,A as q,O as r,le as s,Ye as t,Be as u,G as v,N as w,ee as x,pe as y,F as z};//# sourceMappingURL=chunk-BJEOTG6P.mjs.map
2
- //# sourceMappingURL=chunk-BJEOTG6P.mjs.map
1
+ import {f,b as b$2,a as a$1}from'./chunk-GFH2FEZH.mjs';import {c,u,x,o,n,i,j as j$1,G as G$1,M as M$1,a,I as I$1}from'./chunk-SHAPFMVP.mjs';import {b as b$1,c as c$1}from'./chunk-2FRRD6A3.mjs';import {timSort}from'exsorted';var je=["requirements","design","implementation","verification","deployment","maintenance"],se={requirements:["srs"],design:["design-doc","interface-spec"],implementation:["code-baseline"],verification:["test-report","traceability-matrix"],deployment:["release-notes","deployment-record"],maintenance:["change-log"]},oe={requirements:"business-analyst",design:"architect",deployment:"release-manager"},ae=e=>`${e}-gate`,de="change-control",Ie=["order-backlog","define-acceptance","facilitate","deliver","review","verify","approve-gate","manage-flow","control-change","escalate"],Ee=e=>e.charAt(0).toUpperCase()+e.slice(1);function Te(){return je.map(e=>{let t={id:e,name:Ee(e),deliverables:[...se[e]??[]],gate:{id:ae(e),requires:[{capability:"approve-gate"}],evidence:[],onFail:{action:"block"}}},i=oe[e];return i!==void 0&&(t.deliverBy=i),t})}function k(e){return e.config}var j=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),X=e=>Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.trim()!=="");function Ke(e,t){if(e===void 0)return;j(e)||b$1("config-invalid",`${t}.budget must be an object`,'e.g. { "tokens": 400000 }');let i={};for(let s of ["tokens","turns","wallclockMs"]){let f=e[s];f!==void 0&&((typeof f!="number"||!Number.isFinite(f)||f<0)&&b$1("config-invalid",`${t}.budget.${s} must be a non-negative number`,"omit it for no limit"),i[s]=f);}return i}function De(e,t){return (!Array.isArray(e)||e.length===0)&&b$1("config-invalid",`${t} must be a non-empty array of "human" | { capability }`,'e.g. ["human", { "capability": "approve-gate" }]'),e.map(i=>i==="human"?"human":j(i)&&typeof i.capability=="string"&&Ie.includes(i.capability)?{capability:i.capability}:b$1("config-invalid",`${t} entry ${JSON.stringify(i)} is not "human" or a known capability`,`use "human" or { "capability": one of ${Ie.join(", ")} }`))}function Oe(e,t,i){let s=`waterfall config.phases[${t}]`;j(e)||b$1("config-invalid",`${s} must be an object`,'e.g. { "id": "design" }'),c$1(e.id,`${s}.id`);let f=e.id,d=e.deliverables??se[f]??[];X(d)||b$1("config-invalid",`${s}.deliverables must be a string[] of evidence kinds`,'e.g. ["srs"]');let a;if(e.gate===void 0)a={id:ae(f),requires:[{capability:"approve-gate"}],evidence:[],onFail:{action:"block"}};else {let c=e.gate;(!j(c)||typeof c.id!="string"||c.id.trim()==="")&&b$1("config-invalid",`${s}.gate must be a Gate with an id`,'e.g. { "id": "design-gate", "requires": [{ "capability": "approve-gate" }], "evidence": [] }');let l=c.evidence??[];X(l)||b$1("config-invalid",`${s}.gate.evidence must be a string[]`,"list evidence kinds or omit it"),a={id:c.id,requires:De(c.requires??[{capability:"approve-gate"}],`${s}.gate.requires`),evidence:[...l],onFail:{action:"block"}};}i(f)&&!a.requires.includes("human")&&(a.requires=["human",...a.requires]);let n={id:f,name:typeof e.name=="string"&&e.name.trim()!==""?e.name:Ee(f),deliverables:[...d],gate:a},r=Ke(e.budget,s);r!==void 0&&(n.budget=r);let o=e.deliverBy??oe[f];return o!==void 0&&((typeof o!="string"||o.trim()==="")&&b$1("config-invalid",`${s}.deliverBy must be a role id`,"name the role that delivers this phase or omit it"),n.deliverBy=o),n}function ce(e){let t=e??{};t.phases!==void 0&&!Array.isArray(t.phases)&&b$1("config-invalid","waterfall config.phases must be an array of phases","omit phases for the six classic phases");let i=t.humanGates??"all";i!=="all"&&!X(i)&&b$1("config-invalid",'waterfall config.humanGates must be "all" or a string[] of phase ids','omit it for "all"');let s=i==="all"?()=>true:l=>i.includes(l),f=t.phases===void 0?Te().map((l,u)=>Oe(l,u,s)):t.phases.map((l,u)=>Oe(l,u,s));f.length===0&&b$1("config-invalid","waterfall config.phases needs at least one phase",'e.g. [{ "id": "requirements" }]');let d=f.map(l=>l.id),a=d.find((l,u)=>d.indexOf(l)!==u);if(a!==void 0&&b$1("config-invalid",`duplicate phase id "${a}"`,"give every phase a unique id"),i!=="all")for(let l of i)d.includes(l)||b$1("config-invalid",`waterfall config.humanGates names unknown phase "${l}"`,`phases are: ${d.join(", ")}`);let n=t.changeControl??{};j(n)||b$1("config-invalid","waterfall config.changeControl must be an object",'e.g. { "requiresImpactAnalysis": true, "approvers": ["human"] }'),n.requiresImpactAnalysis!==void 0&&typeof n.requiresImpactAnalysis!="boolean"&&b$1("config-invalid","waterfall config.changeControl.requiresImpactAnalysis must be a boolean","omit it for true");let r={requiresImpactAnalysis:n.requiresImpactAnalysis===void 0?true:n.requiresImpactAnalysis,approvers:De(n.approvers??["human",{capability:"control-change"}],"waterfall config.changeControl.approvers")},o=t.traceability,c;if(o===void 0)c=d.includes("requirements")&&d.includes("design")&&d.includes("verification")?{from:"requirements",to:["design","verification"]}:{from:d[0],to:[]};else {(!j(o)||typeof o.from!="string"||!d.includes(o.from))&&b$1("config-invalid","waterfall config.traceability.from must be a phase id",`phases are: ${d.join(", ")}`);let l=o.to??[];X(l)||b$1("config-invalid","waterfall config.traceability.to must be a string[] of phase ids",`phases are: ${d.join(", ")}`);for(let u of l)d.includes(u)||b$1("config-invalid",`waterfall config.traceability.to names unknown phase "${u}"`,`phases are: ${d.join(", ")}`),d.indexOf(u)<=d.indexOf(o.from)&&b$1("config-invalid",`waterfall config.traceability.to phase "${u}" must come after "${o.from}"`,"trace forward only: from an earlier phase to later ones");c={from:o.from,to:[...l]};}return {phases:f,changeControl:r,traceability:c,humanGates:i==="all"?"all":[...i]}}var L="work",_="review",M="done";function b(e){return e.phases?e.phases:k(e).phases.map(t=>{let i={id:t.id,name:t.name,deliverables:[...t.deliverables],gate:t.gate,status:"pending"};return t.budget&&(i.budget=t.budget),i})}function S(e,t){return {...e,phases:t}}function I(e,t){let i=b(e).findIndex(s=>s.id===t);return i<0&&b$1("config-invalid",`unknown phase "${t}"`,`phases are: ${b(e).map(s=>s.id).join(" \u2192 ")}`),i}function E(e,t){return b(e)[I(e,t)]}function R(e,t){let i=new Set,s=t;for(;s&&!i.has(s.id);){if(s.phase!==void 0)return s.phase;i.add(s.id),s=s.parent!==void 0&&Object.hasOwn(e.items,s.parent)?e.items[s.parent]:void 0;}}function A(e,t){return Object.values(e.items).filter(i=>i.status!=="dropped"&&R(e,i)===t)}function O(e){return b(e).find(t=>t.status==="open")}function le(e){return b(e).find(t=>t.status!=="baselined")}function Ye(e,t){let i=R(e,t);return i!==void 0&&b(e).find(s=>s.id===i)?.status==="baselined"}function Be(e,t){let i=new Set((t.produced??[]).map(s=>s.kind));for(let s of A(e,t.id))for(let f of s.evidence)i.add(f.kind);return i}function G(e,t,i=[]){let s=Be(e,t);for(let d of i)s.add(d);let f=[];for(let d of [...t.deliverables,...t.gate.evidence])f.includes(d)||f.push(d);return f.filter(d=>!s.has(d))}function N(e){let t=b(e).map(s=>s.id),i=k(e).traceability.to.filter(s=>t.includes(s));if(i.length!==0)return i.reduce((s,f)=>t.indexOf(s)>=t.indexOf(f)?s:f)}function Le(e,t,i,s){let f$1=f(e);return !f$1||!f$1.id.startsWith(`${t}#`)?e:{...e,iterations:e.iterations.map(d=>d.id===f$1.id?{...d,endedAt:s,outcome:i}:d)}}function ee(e,t,i,s){let f=E(e,t);f.status!=="open"&&b$1("invalid-transition",`phase "${t}" is ${f.status}, not open`,f.status==="baselined"?"it is already baselined; a change-request reopens it":"kickoff the phase first");let d=A(e,t),a={};for(let c of d)a[c.id]=c;let n=(e.baselines??[]).filter(c=>c.phase===t).length,r={phase:t,version:n+1,at:s,approvedBy:i,itemSnapshot:a},o=S(e,b(e).map(c=>c.id===t?{...c,status:"baselined"}:c));return o={...o,baseline:r,baselines:[...o.baselines??[],r]},o=Le(o,t,"completed",s),c(o,"phase.baselined",i[i.length-1]??"system",{phase:t,version:r.version,approvedBy:i,items:d.map(c=>c.id)},s)}function pe(e,t,i){let s=[];for(let n of t){let r=E(e,n);r.status==="pending"&&b$1("invalid-input",`phase "${n}" was never baselined; there is nothing to reopen`,"remove it from impactAnalysis.reopen"),r.status==="baselined"&&!s.includes(n)&&s.push(n);}let f=b(e).map(n=>s.includes(n.id)?{...n,status:"reopened"}:n),d=null,a=e;if(s.length){let n=Math.min(...s.map(o=>I(e,o))),r=f.find((o,c)=>o.status==="open"&&c>n);r&&(d=r.id,f=f.map(o=>o.id===r.id?{...o,status:"reopened"}:o),a=Le(a,r.id,"cancelled",i));}return {state:S(a,f),reopened:s,suspended:d}}function F(e,t,i,s,f){let d=u(e,t),a=d.impactAnalysis,n=pe(e,a?.reopen??[],f),r=x(n.state,t,{stage:M,status:"done"},i,f);for(let o of n.reopened)r=c(r,"phase.reopened",i,{phase:o,change:t},f);return n.suspended!==null&&(r=c(r,"phase.suspended",i,{phase:n.suspended,change:t},f)),c(r,"change.decided",i,{change:t,decision:"approve",by:i,note:s,reopened:n.reopened,suspended:n.suspended,weight:a?.weight??0,affects:d.affects??[]},f)}function V(e,t,i,s,f){let d=u(e,t),a=x(e,t,{status:"dropped"},i,f);return c(a,"change.decided",i,{change:t,decision:"reject",by:i,note:s,reopened:[],suspended:null,weight:0,affects:d.affects??[]},f)}var _e=["policy","skill","memory","spec","review"],Me=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Je(e){return Array.isArray(e)&&e.every(t=>Me(t)&&typeof t.text=="string"&&t.text.trim()!==""&&_e.includes(t.scope))}function Qe(e,t,i){let s=[...t.map(d=>d.id),...i],f=s.find((d,a)=>s.indexOf(d)!==a);f!==void 0&&b$1("invalid-input",`lesson "${f}" is referenced more than once`,"adopt or dismiss each lesson once");for(let d of s){let a=e.lessons.find(n=>n.id===d);a||b$1("invalid-input",`no lesson "${d}"`,`raised lessons: ${e.lessons.filter(n=>n.status==="raised").map(n=>n.id).join(", ")||"(none)"}`),a.status!=="raised"&&b$1("invalid-input",`lesson "${d}" is already ${a.status}`,"only raised lessons can be adopted or dismissed");}}function Ge(e){return (t,i)=>{o(t,i.by,"facilitate");let s=i.phase===void 0?void 0:H(t,i,"phaseRetrospective"),f=i.lessons??[];Je(f)||b$1("invalid-input","phaseRetrospective.lessons entries need a text and a scope",`scope is one of: ${_e.join(", ")}`);let d=i.adopt??[],a$1=i.dismiss??[];return (!Array.isArray(d)||!d.every(n=>Me(n)&&typeof n.id=="string")||!Array.isArray(a$1)||!a$1.every(n=>typeof n=="string"))&&b$1("invalid-input","phaseRetrospective.adopt must be [{ id, suggestedChange? }] and dismiss a string[]",'e.g. { "adopt": [{ "id": "L1" }], "dismiss": ["L2"] }'),Qe(t,d,a$1),M$1(t,e(),{type:"ceremony.phaseRetrospective",by:i.by,payload:i},n=>{let r=n,o=a(i.now),c$1=[],l=m=>{!m||m.kind!=="agreement"||(r.agreements.includes(m.text)||(r={...r,agreements:[...r.agreements,m.text]}),c$1.push(m.text));},u=[];for(let m of f){let g=`L${r.lessons.length+1}`,x={id:g,at:o,text:m.text,scope:m.scope,status:"adopted",from:i.by};m.suggestedChange&&(x.suggestedChange=m.suggestedChange),r={...r,lessons:[...r.lessons,x]},u.push(g),l(m.suggestedChange);}let p=[];for(let m of d)r={...r,lessons:r.lessons.map(g=>g.id===m.id?{...g,status:"adopted",...m.suggestedChange?{suggestedChange:m.suggestedChange}:{}}:g)},p.push(m.id),l(m.suggestedChange??r.lessons.find(g=>g.id===m.id)?.suggestedChange);for(let m of a$1)r={...r,lessons:r.lessons.map(g=>g.id===m?{...g,status:"dismissed"}:g)};return c(r,"phase.retrospective",i.by,{phase:s?.id??null,lessons:u,adopted:p,dismissed:a$1,agreements:c$1},o)})}}var Xe=(e,t)=>e.id<t.id?-1:e.id>t.id?1:0,Ne=(e,t)=>timSort(A(e,t).filter(i=>i.type!=="question"),Xe),et=(e,t)=>(e.traces??[]).includes(t.id)||(t.traces??[]).includes(e.id);function T(e){let t=k(e).traceability,i=b(e).map(a=>a.id),s=t.to.filter(a=>i.includes(a)),f=Ne(e,t.from).map(a=>{let n={};for(let r of s)n[r]=Ne(e,r).filter(o=>et(a,o)).map(o=>o.id);return {item:a.id,links:n}}),d=f.map(a=>({item:a.item,phases:s.filter(n=>a.links[n].length===0)})).filter(a=>a.phases.length>0);return {from:t.from,to:s,rows:f,missing:d,coverage:{traced:f.length-d.length,total:f.length}}}function fe(e,t){return T(e).rows.filter(i=>(i.links[t]??[]).length===0).map(i=>i.item)}var tt=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function H(e,t,i){let s=t.phase;return (typeof s!="string"||s.trim()==="")&&b$1("invalid-input",`${i} needs phase: string`,`pass one of: ${b(e).map(f=>f.id).join(", ")}`),E(e,s)}function Fe(e,t,i,s,f,d){let a=S(e,b(e).map(n=>n.id===t?{...n,produced:[...n.produced??[],{kind:i,ref:s,by:f,at:d}]}:n));return c(a,"phase.deliverable",f,{phase:t,kind:i,ref:s},d)}function ue(e){let t=(d,a$1,n,r)=>M$1(d,e(),{type:a$1,by:n.by,payload:n},o=>r(o,a(n.now)));return {kickoff:(d,a)=>{o(d,a.by,"facilitate");let n=H(d,a,"kickoff");return t(d,"ceremony.kickoff",a,(r,o)=>{let c$1=r.events.filter(p=>p.type==="phase.opened"&&p.payload.phase===n.id).length+1,l=A(r,n.id).filter(p=>p.status!=="done").map(p=>p.id);r=S(r,b(r).map(p=>p.id===n.id?{...p,status:"open"}:p));let u=n.budget??{};return r={...r,iterations:[...r.iterations,{id:`${n.id}#${c$1}`,goal:n.name,budget:u,spent:a$1,startedAt:o,committed:l,carryover:[]}]},c(r,"phase.opened",a.by,{phase:n.id,version:c$1,items:l,budget:u},o)})},gateReview:(d,a)=>{let n=H(d,a,"gateReview");n.status!=="open"&&b$1("invalid-transition",`phase "${n.id}" is ${n.status}, not open`,n.status==="baselined"?"it is already baselined; a change-request reopens it":`kickoff "${n.id}" first`);let r=n.gate,o=j$1(d,r.id,"approve-gate");a.by!=="human"&&!o.includes(a.by)&&b$1("gate-unmet",`"${a.by}" may not review gate "${r.id}"`,`review as one of: human${o.map(p=>`, ${p}`).join("")}`,{rule:"gate"});let c$1=d.pending.find(p=>p.kind==="gate"&&p.item===void 0&&p.gate===r.id);c$1&&b$1("no-op",`gate "${r.id}" is already awaiting a decision (${c$1.id})`,`decide ${c$1.id} approve|reject`);let l=a.deliverables??[];(!Array.isArray(l)||!l.every(p=>tt(p)&&typeof p.kind=="string"&&p.kind.trim()!==""&&typeof p.ref=="string"))&&b$1("invalid-input","gateReview.deliverables must be [{ kind, ref }]",'e.g. { "deliverables": [{ "kind": "srs", "ref": "docs/srs.md" }] }');let u=l;return t(d,"ceremony.gateReview",a,(p,m)=>{for(let g of u)p=Fe(p,n.id,g.kind,g.ref,a.by,m);if(k(p).traceability.to.includes(n.id)){let g=T(p);p=c(p,"traceability.computed",a.by,{phase:n.id,from:g.from,to:g.to,coverage:g.coverage,missing:g.missing,rows:g.rows},m),n.id===N(p)&&g.missing.length===0&&(p=Fe(p,n.id,"traceability-matrix",`traceability.computed#${p.events[p.events.length-1].seq}`,a.by,m));}if(r.requires.includes("human")&&a.by!=="human"){p=I$1(p,{kind:"gate",gate:r.id,question:`Approve gate "${r.id}" and baseline phase "${n.name}"?`},m);let g=p.pending[p.pending.length-1].id;return c(p,"phase.gate-pending",a.by,{phase:n.id,gate:r.id,by:a.by,pending:g},m)}return ee(p,n.id,[a.by],m)})},changeControlBoard:(d,a)=>{o(d,a.by,"control-change");let n$1=a.change;(typeof n$1!="string"||n$1.trim()==="")&&b$1("invalid-input","changeControlBoard needs change: string (a change-request id)",'e.g. { "change": "CR-1", "decision": "approve", "note": "why" }');let r=u(d,n$1);if(r.type!=="change-request"&&b$1("invalid-input",`item "${n$1}" is a ${r.type}, not a change-request`,"only change-request items go through the board",{items:[n$1]}),(r.status==="done"||r.status==="dropped")&&b$1("invalid-transition",`change "${n$1}" is already ${r.status==="done"?"approved":"rejected"}`,"raise a new change-request",{items:[n$1]}),r.status==="awaiting_human"){let p=d.pending.find(m=>m.item===n$1);b$1("no-op",`change "${n$1}" is awaiting the human decision${p?` (${p.id})`:""}`,`decide ${p?.id??"<pending id>"} approve|reject`,{items:[n$1]});}let o$1=a.decision;o$1!=="approve"&&o$1!=="reject"&&b$1("invalid-input",'changeControlBoard.decision must be "approve" or "reject"',"state the board's decision");let c$1=typeof a.note=="string"?a.note:"",l=k(d).changeControl.approvers;for(let p of l)p==="human"||a.by==="human"||n(d,a.by,p.capability)||b$1("gate-unmet",`"${a.by}" lacks capability "${p.capability}" required by change control`,`decide as one of: human${i(d,p.capability).map(m=>`, ${m.id}`).join("")}`,{rule:"change-control",items:[n$1]});let u$1=l.includes("human")&&a.by!=="human";return t(d,"ceremony.changeControlBoard",a,(p,m)=>{if(u$1){p=I$1(p,{kind:"decision",item:n$1,question:`Change "${n$1}" (${r.title}): the board (${a.by}) recommends ${o$1}${c$1?`: ${c$1}`:""}. Approve or reject the change?`},m);let g=p.pending[p.pending.length-1].id;return c(p,"change.recommended",a.by,{change:n$1,decision:o$1,note:c$1,pending:g},m)}return o$1==="approve"?F(p,n$1,a.by,c$1,m):V(p,n$1,a.by,c$1,m)})},phaseRetrospective:Ge(e)}}function ge(e,t,i,s,f,d){if(t.kind==="gate"&&t.item===void 0&&t.gate!==void 0){let a=b(e).find(o=>o.gate.id===t.gate);if(!a)return e;s!=="human"&&b$1("gate-unmet",`"${s}" may not decide phase gate "${t.gate}" (${t.id}); it awaits a human`,`decide ${t.id} as human`,{rule:"gate"});let n;for(let o=e.events.length-1;o>=0;o--){let c=e.events[o];if(c.type==="phase.gate-pending"&&c.payload.pending===t.id){n=c.by;break}}let r=n!==void 0&&n!==s?[n,s]:[s];return i==="approve"?ee(e,a.id,r,d):c(e,"phase.gate-failed",s,{phase:a.id,gate:t.gate,note:f},d)}if(t.kind==="decision"&&t.item!==void 0&&Object.hasOwn(e.items,t.item)){let a=e.items[t.item];return a.type!=="change-request"?e:(s!=="human"&&b$1("gate-unmet",`"${s}" may not decide change "${a.id}" (${t.id}); change control awaits a human`,`decide ${t.id} as human`,{rule:"change-control",items:[a.id]}),i==="approve"?F(e,a.id,s,f,d):V(e,a.id,s,f,d))}return e}function me(e){let t=k(e).phases.map($=>$.id),i=()=>Object.fromEntries(t.map($=>[$,0])),s=i(),f=i(),d=i(),a=i(),n=i(),r=new Map,o=new Map,c=new Map,l=0,u=0,p=0,m=0,g=0,x=0,we=0,ke=$=>{let w=o.get($),y=r.get($);return w!=="question"&&w!=="change-request"&&y!==void 0&&y in s};for(let $ of e.events){let w=$.payload??{};switch($.type){case "item.added":{let y=w,q=y.phase??(y.parent!==null?r.get(y.parent):void 0);r.set(y.id,q),o.set(y.id,y.type),c.set(y.id,"todo"),y.type==="change-request"&&(p+=1),ke(y.id)&&(s[q]+=1,y.type==="bug"&&(n[q]+=1));break}case "item.transition":{let y=w.id,q=w.to.status,Re=c.get(y);if(c.set(y,q),!ke(y))break;let ne=r.get(y);q==="done"&&Re!=="done"&&(f[ne]+=1),q==="dropped"&&(s[ne]-=1,Re==="done"&&(f[ne]-=1));break}case "item.completed":{let y=r.get(w.id);y!==void 0&&y in a&&(a[y]+=w.tokens??0);break}case "phase.opened":{let y=w.phase;y in d&&(d[y]=(w.budget??{}).tokens??0);break}case "traceability.computed":{let y=w.coverage;l=y.traced,u=y.total;break}case "change.decided":{w.decision==="approve"?(m+=1,x+=w.weight??0,we+=(w.reopened??[]).length):g+=1;break}}}let $e=i(),We=i();for(let $ of t){let w=s[$]??0;$e[$]=w===0?0:(f[$]??0)/w*100,We[$]=a[$]-d[$];}let Ae=m+g;return {phaseCompletion:$e,budgetPlanned:d,budgetSpent:a,scheduleVariance:We,requirementCoverage:u===0?0:l/u,requirementsTraced:l,requirementsTotal:u,defectsPerPhase:n,changeRequests:p,changesApproved:m,changesRejected:g,changeApprovalRate:Ae===0?0:m/Ae,reworkWeight:x,phasesReopened:we}}function he(e){let t=e.phases.map(i=>i.gate.id);return [{id:"project-manager",name:"Project Manager",modelTier:"large",capabilities:["facilitate","control-change","approve-gate","escalate"],canApprove:[...t,de],inputs:["phase-plan","deliverables","change-requests"],outputs:["gate-decisions","baselines","change-decisions"],do_not:["do not implement items yourself","do not reopen a phase without an approved change-request"]},{id:"developer",name:"Developer",modelTier:"small",capabilities:["deliver"],canApprove:[],inputs:["design-doc","interface-spec","brief"],outputs:["code","code-baseline","test-output"],do_not:["do not change requirements or designs; raise a change-request","do not approve your own work"]},{id:"business-analyst",name:"Business Analyst",modelTier:"medium",capabilities:["define-acceptance","deliver"],canApprove:[],inputs:["stakeholder-needs"],outputs:["srs","acceptance-criteria"],do_not:["do not design or implement","do not edit a baselined requirement; raise a change-request"]},{id:"architect",name:"Architect",modelTier:"medium",capabilities:["deliver"],canApprove:[],inputs:["srs"],outputs:["design-doc","interface-spec"],do_not:["do not change requirements; raise a change-request","do not implement"]},{id:"qa",name:"QA",modelTier:"small",capabilities:["verify","review"],canApprove:[],inputs:["srs","design-doc","code-baseline"],outputs:["test-report","review-notes"],do_not:["do not fix defects yourself; raise bugs","do not approve phase gates"]},{id:"release-manager",name:"Release Manager",modelTier:"small",capabilities:["deliver"],canApprove:[],inputs:["code-baseline","test-report"],outputs:["release-notes","deployment-record"],do_not:["do not deploy an unbaselined verification phase"]}]}var v=(e,t,i,s)=>s?{rule:e,severity:"error",item:s,message:t,fix:i}:{rule:e,severity:"error",message:t,fix:i},C=e=>e.payload??{},U=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),z=e=>{let t=C(e).phase;return typeof t=="string"?t:void 0},P=(e,t)=>b(e).find(i=>i.id===t),ye=e=>b(e).map(t=>t.id).join(", "),te=(e,t)=>typeof t=="string"&&Object.hasOwn(e.items,t)?e.items[t]:void 0;function Ve(e,t){if(t.phase!==void 0)return t.phase;let i=te(e,t.parent);return i?R(e,i):void 0}var He=e=>e.type!=="change-request"&&e.type!=="question",Ue=(e,t)=>`raise a change-request: addItem({ type: "change-request", affects: ["${e}"], impactAnalysis: { summary, reopen: ["${t}"], weight } }) and decide it in changeControlBoard`;function ze(e,t){let i=te(e,C(t).change);return i&&i.type==="change-request"?i:void 0}function be(){return [{id:"phase-sequential",severity:"error",check(n,r){let o=[];if(r.type==="ceremony.kickoff"){let c=z(r),l=c===void 0?void 0:P(n,c);if(!l)return [];l.status==="open"&&o.push(v("phase-sequential",`phase "${l.id}" is already open`,`gateReview "${l.id}" when its work is done`)),l.status==="baselined"&&o.push(v("phase-sequential",`phase "${l.id}" is baselined`,"only an approved change-request reopens a baselined phase"));let u=O(n);u&&u.id!==l.id&&o.push(v("phase-sequential",`phase "${u.id}" is still open`,`pass its gate (gateReview "${u.id}") before opening "${l.id}"`));}else if(r.type==="item.add"){let c=C(r).item;if(!U(c)||!He(c))return [];let l=Ve(n,c);l===void 0?o.push(v("phase-sequential",`item "${c.id}" belongs to no phase`,`set phase to one of: ${ye(n)}`,c.id)):P(n,l)||o.push(v("phase-sequential",`item "${c.id}" names unknown phase "${l}"`,`phases are: ${ye(n)}`,c.id));}else if(r.type==="item.edit"){let c=C(r).id,l=C(r).patch,u=te(n,c);if(!u||!U(l)||l.phase===void 0||l.phase===u.phase)return [];o.push(v("phase-sequential",`item "${u.id}" cannot move from phase "${u.phase??"(none)"}" to "${String(l.phase)}"`,`drop "${u.id}" and add a new item in phase "${String(l.phase)}"`,u.id));}return o}},{id:"gate-before-next-phase",severity:"error",check(n,r){if(r.type!=="ceremony.kickoff")return [];let o=z(r),c=b(n),l=o===void 0?-1:c.findIndex(p=>p.id===o);if(l<0)return [];let u=c.slice(0,l).filter(p=>p.status!=="baselined").map(p=>p.id);return u.length===0?[]:[v("gate-before-next-phase",`phase(s) ${u.join(", ")} before "${o}" are not baselined`,`kickoff and gateReview them in order, starting with "${u[0]}"`)]}},{id:"baseline-immutable",severity:"error",check(n,r){let o=c=>(n.baselines??[]).filter(l=>l.phase===c).length||1;if(r.type==="item.edit"){let c=te(n,C(r).id);if(!c)return [];let l=R(n,c);return l===void 0||P(n,l)?.status!=="baselined"?[]:[v("baseline-immutable",`item "${c.id}" is frozen: phase "${l}" is baselined (v${o(l)})`,Ue(c.id,l),c.id)]}if(r.type==="item.add"){let c=C(r).item;if(!U(c)||!He(c))return [];let l=Ve(n,c);return l===void 0||P(n,l)?.status!=="baselined"?[]:[v("baseline-immutable",`cannot add "${c.id}" to baselined phase "${l}" (v${o(l)})`,Ue(c.id,l),c.id)]}return []}},{id:"change-needs-impact-analysis",severity:"error",check(n,r){if(r.type!=="ceremony.changeControlBoard")return [];let o=ze(n,r);if(!o)return [];let c=k(n).changeControl,l=o.impactAnalysis,u=`editItem("${o.id}", { impactAnalysis: { summary: "what changes and why", reopen: ["<phase>"], weight: <points> } })`;if(l===void 0)return c.requiresImpactAnalysis?[v("change-needs-impact-analysis",`change "${o.id}" has no impact analysis`,u,o.id)]:[];let p=[];if((!U(l)||typeof l.summary!="string"||l.summary.trim()==="")&&p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.summary is empty`,u,o.id)),(!Array.isArray(l.reopen)||!l.reopen.every(g=>typeof g=="string"))&&p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.reopen must be a string[] of phase ids`,u,o.id)),(typeof l.weight!="number"||!Number.isFinite(l.weight)||l.weight<0)&&p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.weight must be a non-negative number`,u,o.id)),p.length)return p;let m=C(r).decision==="approve";for(let g of l.reopen){let x=P(n,g);x?m&&x.status==="pending"&&p.push(v("change-needs-impact-analysis",`phase "${g}" was never baselined; it cannot be reopened`,`remove "${g}" from impactAnalysis.reopen`,o.id)):p.push(v("change-needs-impact-analysis",`change "${o.id}" impactAnalysis.reopen names unknown phase "${g}"`,`phases are: ${ye(n)}`,o.id));}return p}},{id:"requirement-traced",severity:"error",check(n,r){if(r.type!=="ceremony.gateReview")return [];let o=z(r),c=k(n).traceability;return o===void 0||!c.to.includes(o)||!P(n,o)?[]:fe(n,o).map(l=>v("requirement-traced",`item "${l}" of phase "${c.from}" has no trace into "${o}"`,`editItem a "${o}" item with traces: ["${l}"] (or editItem("${l}", { traces: [...] }) while "${c.from}" is not baselined)`,l))}},{id:"deliverables-present",severity:"error",check(n,r){if(r.type!=="ceremony.gateReview")return [];let o=z(r),c=o===void 0?void 0:P(n,o);if(!c)return [];let l=[],u=A(n,c.id).filter(g=>g.status!=="done").map(g=>g.id);u.length&&l.push(v("deliverables-present",`${u.length} item(s) in phase "${c.id}" are not done: ${u.join(", ")}`,"finish them (next/complete) or drop them before the gate"));let p=C(r).deliverables,m=Array.isArray(p)?p.filter(g=>U(g)&&typeof g.kind=="string").map(g=>g.kind):[];c.id===N(n)&&m.push("traceability-matrix");for(let g of G(n,c,m))l.push(v("deliverables-present",`phase "${c.id}" has no deliverable "${g}"`,`pass deliverables: [{ "kind": "${g}", "ref": "<where it lives>" }] to gateReview, or attach evidence of kind "${g}" on an item of the phase`));return l}},{id:"approver-not-author",severity:"error",check(n,r){if(r.by==="human")return [];if(r.type==="ceremony.gateReview"){let o=z(r),c=o===void 0?void 0:P(n,o);if(!c)return [];let l=A(n,c.id).filter(p=>G$1(n,p)===r.by).map(p=>p.id);if(l.length===0)return [];let u=j$1(n,c.gate.id,"approve-gate",r.by);return [v("approver-not-author",`"${r.by}" authored ${l.join(", ")} in phase "${c.id}" and may not approve its gate`,`review the gate as one of: human${u.map(p=>`, ${p}`).join("")}`)]}if(r.type==="ceremony.changeControlBoard"){let o=ze(n,r);if(!o)return [];let c=n.events.find(u=>u.type==="item.added"&&u.payload.id===o.id);if(!c||c.by!==r.by)return [];let l=i(n,"control-change").map(u=>u.id).filter(u=>u!==r.by);return [v("approver-not-author",`"${r.by}" raised change "${o.id}" and may not decide it`,`decide as human${l.map(u=>`, ${u}`).join("")}`,o.id)]}return []}}]}function ve(e){return [{id:L,name:"Work",entryPolicy:[{kind:"dependencies-done"}],exitPolicy:[]},{id:_,name:"Review",entryPolicy:[],exitPolicy:[{kind:"no-open-blockers"}],review:true},{id:M,name:"Done",entryPolicy:[],exitPolicy:[]}]}var nt={backlog:"Requirements Baseline",item:"Work Package",stage:"Step",iteration:"Phase",increment:"Deliverable",ceremony:"Review",gate:"Phase Gate"};function it(e,t){let i=R(e,t);if(i!==void 0)return k(e).phases.find(s=>s.id===i)?.deliverBy}function rt(e){return {phases:b(e).map(i=>{let s=A(e,i.id),f=s.filter(a=>a.status==="done").length,d=G(e,i);return {id:i.id,name:i.name,status:i.status,items:s.length,done:f,missingDeliverables:d,readyForGate:i.status==="open"&&f===s.length&&d.length===0}}),current:le(e)?.id??null,open:O(e)?.id??null,pendingGates:e.pending.filter(i=>i.kind==="gate"&&i.item===void 0&&i.gate!==void 0).map(i=>({pending:i.id,gate:i.gate}))}}function st(){return {name:"waterfall",vocabulary:nt,validateConfig:ce,defaultStages:ve,defaultRoles:he,requiredCapabilities:["facilitate","control-change","approve-gate","deliver","verify"],exclusiveCapabilities:[],plannerOptions(e){return {schedulerMode:"level",roleFor:t=>t.status==="todo"&&t.type!=="question"?it(e,t):void 0}},candidates(e){let t=O(e);return t?Object.values(e.items).filter(i=>(i.status==="todo"||i.status==="review")&&(i.stage===L||i.stage===_)&&i.type!=="change-request"&&R(e,i)===t.id):[]},invariants(e,t){let i=k(e),s=b(e),f=R(e,t),d=f===void 0?void 0:s[I(e,f)],a=s.filter(r=>r.status==="baselined").map(r=>r.id),n=d?.gate.requires.includes("human");return [d?`Phase "${d.name}" (${I(e,d.id)+1}/${s.length}); deliverables: ${d.deliverables.join(", ")||"(none)"}; gate "${d.gate.id}"${n?" needs human approval":""}`:"This item belongs to no phase; it is dispatched only through its parent's phase",`Baselined phases are frozen: ${a.join(", ")||"(none yet)"}; to change their items, raise a change-request with an impact analysis`,i.traceability.to.length?`Traceability: every item of phase "${i.traceability.from}" must trace to an item in ${i.traceability.to.join(", ")} (set traces on either side)`:"Traceability: none configured",`Do not change the scope of "${t.id}" or its acceptance criteria; raise open_questions instead`]},ceremonies:ue(st),rules:be(),metrics:e=>({...me(e)}),humanDefaults:{gates:"all"},report:e=>({...rt(e),coverage:T(e).coverage}),afterDecide:ge,afterComplete(e,t,i){let s=f(e),f$1=O(e);if(!s||!f$1||s.committed.includes(t))return e;let d=e.items[t];if(!d||R(e,d)!==f$1.id)return e;let a=e.accounting[e.accounting.length-1];return !a||a.item!==t?e:{...e,iterations:e.iterations.map(n=>n.id===s.id?{...n,committed:[...n.committed,t],spent:b$2(n.spent,a)}:n)}}}}export{V as A,T as B,fe as C,H as D,ue as E,ge as F,me as G,he as H,be as I,ve as J,nt as K,it as L,rt as M,st as N,je as a,se as b,oe as c,ae as d,de as e,Te as f,k as g,ce as h,L as i,_ as j,M as k,b as l,S as m,I as n,E as o,R as p,A as q,O as r,le as s,Ye as t,Be as u,G as v,N as w,ee as x,pe as y,F as z};//# sourceMappingURL=chunk-NDORREWR.mjs.map
2
+ //# sourceMappingURL=chunk-NDORREWR.mjs.map