yaaw-se 0.3.11 → 0.3.13
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/dist/installer/migrations/index.d.ts +2 -2
- package/dist/installer/migrations/index.js +2 -2
- package/dist/installer/migrations/index.js.map +1 -1
- package/dist/installer/migrations/project/index.js +2 -1
- package/dist/installer/migrations/project/index.js.map +1 -1
- package/dist/installer/migrations/project/v2-to-v3.d.ts +2 -0
- package/dist/installer/migrations/project/v2-to-v3.js +56 -0
- package/dist/installer/migrations/project/v2-to-v3.js.map +1 -0
- package/dist/installer/plan.js +98 -268
- package/dist/installer/plan.js.map +1 -1
- package/dist/installer/project-state.js +3 -13
- package/dist/installer/project-state.js.map +1 -1
- package/dist/installer/status.js +67 -231
- package/dist/installer/status.js.map +1 -1
- package/dist/installer/transaction.js +58 -109
- package/dist/installer/transaction.js.map +1 -1
- package/dist/installer/types.d.ts +5 -2
- package/dist/installer/verify.js +27 -27
- package/dist/installer/verify.js.map +1 -1
- package/dist/payload/bootstrap/claude-code.md +6 -6
- package/dist/payload/bootstrap/cline.md +8 -8
- package/dist/payload/bootstrap/codex.md +7 -7
- package/dist/payload/bootstrap/gemini-cli.md +6 -6
- package/dist/payload/payload-files.json +97 -417
- package/dist/payload/payload.json +1 -1
- package/dist/payload/skills/yaaw-create-spec/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-create-ticket/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-create-tickets/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-implement/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-orchestrator/SKILL.md +2 -3
- package/dist/payload/skills/yaaw-planner/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-planning-review/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-prd/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-refine-prd/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-repair/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-review/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-revise-prd/SKILL.md +2 -6
- package/dist/payload/yaaw-core/registries/skills.json +38 -0
- package/dist/payload/yaaw-core/system/SYSTEM.md +121 -0
- package/dist/payload/yaaw-core/system/engine/contracts.mjs +147 -0
- package/dist/payload/yaaw-core/system/engine/repository-identity.mjs +24 -0
- package/dist/payload/yaaw-core/system/engine/routing.mjs +153 -0
- package/dist/payload/yaaw-core/system/engine/runtime.mjs +66 -0
- package/dist/payload/yaaw-core/system/kernel.yaml +145 -0
- package/dist/payload/yaaw-core/system/modules/changeability.md +27 -0
- package/dist/payload/yaaw-core/system/roles/implementer.md +16 -12
- package/dist/payload/yaaw-core/system/roles/orchestrator.md +24 -14
- package/dist/payload/yaaw-core/system/roles/planner.md +37 -11
- package/dist/payload/yaaw-core/system/roles/prd.md +26 -18
- package/dist/payload/yaaw-core/system/roles/reviewer.md +16 -15
- package/dist/payload/yaaw-core/system/schemas/handoff.schema.json +24 -161
- package/dist/payload/yaaw-core/system/schemas/intent.schema.json +11 -64
- package/dist/payload/yaaw-core/system/schemas/observed-state.schema.json +12 -162
- package/dist/payload/yaaw-core/system/schemas/repository-identity.schema.json +12 -39
- package/dist/payload/yaaw-core/system/templates/evidence.json +1 -18
- package/dist/payload/yaaw-core/system/templates/handoff.json +11 -27
- package/dist/payload/yaaw-core/system/templates/intent.json +2 -2
- package/dist/payload/yaaw-core/system/templates/observed-state.json +5 -28
- package/dist/payload/yaaw-core/system/templates/review.md +2 -2
- package/package.json +5 -2
- package/dist/payload/yaaw-core/system/core/artifact-model.md +0 -43
- package/dist/payload/yaaw-core/system/core/authority.md +0 -21
- package/dist/payload/yaaw-core/system/core/context-loading.md +0 -56
- package/dist/payload/yaaw-core/system/core/dispatch-execution.md +0 -28
- package/dist/payload/yaaw-core/system/core/execution-context.md +0 -61
- package/dist/payload/yaaw-core/system/core/framework-integrity.md +0 -60
- package/dist/payload/yaaw-core/system/core/invalidation.md +0 -13
- package/dist/payload/yaaw-core/system/core/io-contract.md +0 -23
- package/dist/payload/yaaw-core/system/core/lifecycle.md +0 -23
- package/dist/payload/yaaw-core/system/core/recovery.md +0 -17
- package/dist/payload/yaaw-core/system/core/routing.md +0 -21
- package/dist/payload/yaaw-core/system/core/state-model.md +0 -14
- package/dist/payload/yaaw-core/system/core/transitions.md +0 -36
- package/dist/payload/yaaw-core/system/expertise/changeability/MODULE.md +0 -58
- package/dist/payload/yaaw-core/system/registries/artifacts.json +0 -99
- package/dist/payload/yaaw-core/system/registries/execution-policy.json +0 -169
- package/dist/payload/yaaw-core/system/registries/expertise.json +0 -47
- package/dist/payload/yaaw-core/system/registries/handoff-policy.json +0 -67
- package/dist/payload/yaaw-core/system/registries/paths.json +0 -18
- package/dist/payload/yaaw-core/system/registries/reconciliation-policy.json +0 -18
- package/dist/payload/yaaw-core/system/registries/role-io.json +0 -30
- package/dist/payload/yaaw-core/system/registries/routing-policy.json +0 -74
- package/dist/payload/yaaw-core/system/registries/skills.json +0 -110
- package/dist/payload/yaaw-core/system/registries/transitions.json +0 -178
- package/dist/payload/yaaw-core/system/registries/workflows.json +0 -38
- package/dist/payload/yaaw-core/system/rules/artifact-writing.md +0 -10
- package/dist/payload/yaaw-core/system/rules/assumption-challenge.md +0 -109
- package/dist/payload/yaaw-core/system/rules/changeability.md +0 -38
- package/dist/payload/yaaw-core/system/rules/durable-memory.md +0 -9
- package/dist/payload/yaaw-core/system/rules/question-format.md +0 -20
- package/dist/payload/yaaw-core/system/rules/recovery-evidence.md +0 -9
- package/dist/payload/yaaw-core/system/rules/repository-identity.md +0 -42
- package/dist/payload/yaaw-core/system/rules/research-admission.md +0 -30
- package/dist/payload/yaaw-core/system/rules/review-independence.md +0 -11
- package/dist/payload/yaaw-core/system/rules/ticket-sizing.md +0 -9
- package/dist/payload/yaaw-core/system/schemas/project-state.schema.json +0 -12
- package/dist/payload/yaaw-core/system/templates/project-state.json +0 -13
- package/dist/payload/yaaw-core/system/tools/orchestration-engine.mjs +0 -210
- package/dist/payload/yaaw-core/system/tools/orchestration-runtime.mjs +0 -46
- package/dist/payload/yaaw-core/system/tools/repository-identity.mjs +0 -92
- package/dist/payload/yaaw-core/system/workflows/implementation/implement-ticket.md +0 -18
- package/dist/payload/yaaw-core/system/workflows/implementation/repair-ticket.md +0 -17
- package/dist/payload/yaaw-core/system/workflows/implementation/select-ticket.md +0 -17
- package/dist/payload/yaaw-core/system/workflows/implementation/verify-ticket.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/orchestration/determine-next-action.md +0 -24
- package/dist/payload/yaaw-core/system/workflows/orchestration/dispatch.md +0 -35
- package/dist/payload/yaaw-core/system/workflows/orchestration/inspect-state.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/orchestration/reconcile-state.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/orchestration/recover-interruption.md +0 -32
- package/dist/payload/yaaw-core/system/workflows/orchestration/route.md +0 -27
- package/dist/payload/yaaw-core/system/workflows/planning/create-spec.md +0 -21
- package/dist/payload/yaaw-core/system/workflows/planning/create-tickets.md +0 -50
- package/dist/payload/yaaw-core/system/workflows/planning/decision-frontier.md +0 -33
- package/dist/payload/yaaw-core/system/workflows/planning/discover.md +0 -21
- package/dist/payload/yaaw-core/system/workflows/planning/question-round.md +0 -22
- package/dist/payload/yaaw-core/system/workflows/planning/readiness-review.md +0 -33
- package/dist/payload/yaaw-core/system/workflows/planning/record-decisions.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/planning/replan.md +0 -24
- package/dist/payload/yaaw-core/system/workflows/planning/research.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/planning/route.md +0 -28
- package/dist/payload/yaaw-core/system/workflows/planning/write-understanding.md +0 -26
- package/dist/payload/yaaw-core/system/workflows/prd/create.md +0 -22
- package/dist/payload/yaaw-core/system/workflows/prd/question-round.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/prd/readiness.md +0 -22
- package/dist/payload/yaaw-core/system/workflows/prd/record-decisions.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/prd/refine.md +0 -15
- package/dist/payload/yaaw-core/system/workflows/prd/revise.md +0 -18
- package/dist/payload/yaaw-core/system/workflows/prd/route.md +0 -23
- package/dist/payload/yaaw-core/system/workflows/review/classify-findings.md +0 -17
- package/dist/payload/yaaw-core/system/workflows/review/inspect-change.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/review/record-review.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/review/review-ticket.md +0 -24
- /package/dist/payload/yaaw-core/system/{tools → engine}/frontmatter.mjs +0 -0
- /package/dist/payload/yaaw-core/system/{tools/framework-integrity.mjs → engine/integrity.mjs} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/frontend-design/MODULE.md → modules/frontend-design.md} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/python/MODULE.md → modules/python.md} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/security/MODULE.md → modules/security.md} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/testing/MODULE.md → modules/testing.md} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { ROUTES, dispatchableWorkflows } from "./contracts.mjs";
|
|
2
|
+
const ACTIVE = new Set(["READY","IN_PROGRESS","REVIEW_REQUIRED","REPAIR_REQUIRED","PASS"]);
|
|
3
|
+
const TERMINAL = new Set(["PASS","CANCELLED"]);
|
|
4
|
+
const REVIEW_RESULT = { PASS:"PASS", REPAIR:"REPAIR_REQUIRED", REPLAN:"REPLAN_REQUIRED", BLOCKED:"BLOCKED" };
|
|
5
|
+
const idNum = value => Number(String(value??"").match(/(\d+)(?!.*\d)/)?.[1]??0);
|
|
6
|
+
const byId=(a,b)=>idNum(a)-idNum(b)||String(a).localeCompare(String(b));
|
|
7
|
+
const repoEq=(a,b)=>Boolean(a&&b&&a.status==="READY"&&b.status==="READY"&&a.algorithm===b.algorithm&&a.head_commit===b.head_commit&&a.worktree_digest===b.worktree_digest);
|
|
8
|
+
const currentSpecId=(state)=>String(state?.planning?.active_spec??"").match(/SPEC-[0-9]+/)?.[0]??null;
|
|
9
|
+
const sourceCurrent=(ticket,state,a)=>{
|
|
10
|
+
const t=a.tickets?.[ticket]?.meta;if(!t)return false;
|
|
11
|
+
const sid=String(t.spec??"");const s=a.specs?.[sid]?.meta;if(!s)return false;
|
|
12
|
+
return Number(t.product_revision??0)===Number(state.product.revision??0)
|
|
13
|
+
&& Number(t.engineering_revision??0)===Number(state.planning.revision??0)
|
|
14
|
+
&& Number(t.spec_revision??0)===Number(s.revision??0)
|
|
15
|
+
&& Number(s.product_revision??0)===Number(state.product.revision??0)
|
|
16
|
+
&& Number(s.engineering_revision??0)===Number(state.planning.revision??0);
|
|
17
|
+
};
|
|
18
|
+
const currentTicketIds=(state,a)=>Object.keys(a.tickets??{}).filter(id=>sourceCurrent(id,state,a)).sort(byId);
|
|
19
|
+
const dependenciesPass=(ticket,state,a)=>((a.tickets?.[ticket]?.meta?.dependencies??[]).every(id=>state.tickets?.[id]==="PASS"));
|
|
20
|
+
const evidenceFor=(ticket,a)=>Object.values(a.evidence??{}).filter(x=>x?.ticket===ticket&&x?.schema==="yaaw.evidence/v3");
|
|
21
|
+
const reviewFor=(ticket,a)=>Object.values(a.reviews??{}).filter(x=>x?.meta?.ticket===ticket&&x?.meta?.schema==="yaaw.review/v2").sort((x,y)=>Number(x.meta.round??0)-Number(y.meta.round??0));
|
|
22
|
+
const latestStart=(ticket,a)=>evidenceFor(ticket,a).filter(x=>x.kind==="implementation_start"&&x.result==="STARTED").sort((x,y)=>idNum(x.id)-idNum(y.id)).at(-1)??null;
|
|
23
|
+
const latestVerification=(ticket,a)=>evidenceFor(ticket,a).filter(x=>x.kind==="implementation_verification").sort((x,y)=>idNum(x.id)-idNum(y.id)).at(-1)??null;
|
|
24
|
+
const latestReview=(ticket,a)=>reviewFor(ticket,a).at(-1)??null;
|
|
25
|
+
const verificationCurrent=(v,ticket,a,repo)=>Boolean(v&&v.result==="PASS"&&Number(v.ticket_revision??0)===Number(a.tickets?.[ticket]?.meta?.revision??0)&&Number(v.spec_revision??0)===Number(a.specs?.[a.tickets?.[ticket]?.meta?.spec]?.meta?.revision??0)&&repoEq(v.repository,repo));
|
|
26
|
+
const reviewCurrent=(r,ticket,a,repo,v)=>Boolean(r&&REVIEW_RESULT[r.meta?.result]&&Number(r.meta.ticket_revision??0)===Number(a.tickets?.[ticket]?.meta?.revision??0)&&Number(r.meta.spec_revision??0)===Number(a.specs?.[a.tickets?.[ticket]?.meta?.spec]?.meta?.revision??0)&&repoEq(r.meta.repository,repo)&&Array.isArray(r.meta.evidence)&&(!v||r.meta.evidence.includes(v.id)));
|
|
27
|
+
|
|
28
|
+
export function deriveState(a){
|
|
29
|
+
const p=a.product?.meta??{},e=a.engineering?.meta??{};
|
|
30
|
+
const product={artifact:a.product?.path??null,status:String(p.status??"missing"),revision:Number(p.revision??0)};
|
|
31
|
+
const planning={artifact:a.engineering?.path??null,status:String(e.status??"missing"),revision:Number(e.revision??0),current_frontier:e.current_frontier??null,readiness:e.readiness??"pending",scope_status:e.scope_status??"UNKNOWN",active_spec:null};
|
|
32
|
+
if(e.product_revision!==undefined&&Number(e.product_revision)!==product.revision)planning.readiness="pending";
|
|
33
|
+
const accepted=Object.entries(a.specs??{}).filter(([,x])=>x.meta?.status==="ACCEPTED"&&Number(x.meta.product_revision??0)===product.revision&&Number(x.meta.engineering_revision??0)===planning.revision).sort(([x],[y])=>byId(x,y));
|
|
34
|
+
if(accepted.length===1)planning.active_spec=accepted[0][1].path;
|
|
35
|
+
const tickets=Object.fromEntries(Object.entries(a.tickets??{}).map(([id,x])=>[id,String(x.meta?.status??"DRAFT")]));
|
|
36
|
+
const current=Object.keys(tickets).filter(id=>sourceCurrent(id,{product,planning,tickets},a));
|
|
37
|
+
const allTerminal=current.length>0&¤t.every(id=>TERMINAL.has(tickets[id]));
|
|
38
|
+
let phase="implementation";
|
|
39
|
+
if(product.status!=="ready")phase="product";
|
|
40
|
+
else if(planning.status!=="ready"||planning.readiness!=="PASS")phase="planning";
|
|
41
|
+
else if(allTerminal&&planning.scope_status==="COMPLETE")phase="complete";
|
|
42
|
+
const precedence=["REPLAN_REQUIRED","REPAIR_REQUIRED","REVIEW_REQUIRED","IN_PROGRESS","READY","DRAFT","BLOCKED"];
|
|
43
|
+
let active_ticket=null;for(const status of precedence){active_ticket=current.find(id=>tickets[id]===status)??null;if(active_ticket)break;}
|
|
44
|
+
return {schema:"yaaw.derived-state/v1",phase,product,planning,active_ticket,tickets,accepted_specs:accepted.map(([id])=>id)};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function transition(kernel,ticket,from,to,id,reason,evidence=[],workflow="orchestration.reconcile-state"){
|
|
48
|
+
const legal=kernel.lifecycle.legal.some(t=>t.from===from&&t.to===to);
|
|
49
|
+
if(!legal)return {id:"ILLEGAL_TRANSITION",kind:"BLOCKED",subject:ticket,from,to,reason:`illegal derived transition ${from} -> ${to}`,workflow:null,evidence:[]};
|
|
50
|
+
return {id,kind:"TICKET_STATUS",subject:ticket,from,to,reason,workflow,evidence};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function selectReconciliation(kernel,state,a,repo){
|
|
54
|
+
if((state.accepted_specs??[]).length>1)return {id:"MULTIPLE_CURRENT_SPECS",kind:"BLOCKED",subject:null,from:null,to:null,reason:"more than one current ACCEPTED specification exists",workflow:null,evidence:state.accepted_specs};
|
|
55
|
+
const ids=Object.keys(state.tickets??{}).sort(byId);
|
|
56
|
+
for(const ticket of ids){
|
|
57
|
+
const status=state.tickets[ticket];
|
|
58
|
+
if((ACTIVE.has(status)||status==="REPLAN_REQUIRED")&&!sourceCurrent(ticket,state,a)){
|
|
59
|
+
if(status==="REPLAN_REQUIRED")continue;
|
|
60
|
+
return transition(kernel,ticket,status,"REPLAN_REQUIRED","CONTRACT_SOURCE_STALE","ticket source revisions are stale",[],"planning.replan");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for(const ticket of ids){
|
|
64
|
+
const status=state.tickets[ticket];if(!sourceCurrent(ticket,state,a))continue;
|
|
65
|
+
const start=latestStart(ticket,a),verification=latestVerification(ticket,a),review=latestReview(ticket,a);
|
|
66
|
+
if(status==="READY"&&start){
|
|
67
|
+
const t=a.tickets[ticket].meta;
|
|
68
|
+
if(Number(start.ticket_revision??0)===Number(t.revision??0)&&Number(start.spec_revision??0)===Number(a.specs?.[t.spec]?.meta?.revision??0))return transition(kernel,ticket,"READY","IN_PROGRESS","IMPLEMENTATION_STARTED","implementation_start evidence exists",[start.id]);
|
|
69
|
+
}
|
|
70
|
+
if(status==="IN_PROGRESS"&&verificationCurrent(verification,ticket,a,repo))return transition(kernel,ticket,"IN_PROGRESS","REVIEW_REQUIRED","IMPLEMENTATION_VERIFIED","current PASS verification exists",[verification.id]);
|
|
71
|
+
if(status==="REPAIR_REQUIRED"&&verificationCurrent(verification,ticket,a,repo)){
|
|
72
|
+
const prior=review?.meta?.evidence??[];if(!prior.includes(verification.id))return transition(kernel,ticket,"REPAIR_REQUIRED","REVIEW_REQUIRED","IMPLEMENTATION_VERIFIED","fresh PASS verification exists after repair",[verification.id]);
|
|
73
|
+
}
|
|
74
|
+
if(status==="REVIEW_REQUIRED"&&reviewCurrent(review,ticket,a,repo,verification)){
|
|
75
|
+
const to=REVIEW_RESULT[review.meta.result];return transition(kernel,ticket,"REVIEW_REQUIRED",to,"REVIEW_RESULT_UNAPPLIED",`review result ${review.meta.result} authorizes ${to}`,[review.path,verification?.id].filter(Boolean));
|
|
76
|
+
}
|
|
77
|
+
if(status==="PASS"){
|
|
78
|
+
if(!verificationCurrent(verification,ticket,a,repo))return transition(kernel,ticket,"PASS","REVIEW_REQUIRED","ACCEPTANCE_STALE","accepted ticket lacks current PASS verification",verification?[verification.id]:[]);
|
|
79
|
+
if(!reviewCurrent(review,ticket,a,repo,verification))return transition(kernel,ticket,"PASS","REVIEW_REQUIRED","ACCEPTANCE_STALE","accepted ticket lacks current review for repository/evidence basis",review?[review.path]:[]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function planningReady(state){return state.product.status==="ready"&&state.planning.status==="ready"&&state.planning.readiness==="PASS"}
|
|
86
|
+
function requestedTicket(intent,state){const t=String(intent?.target_artifact??"").match(/TASK-[0-9]+/)?.[0];return t&&state.tickets?.[t]?t:null}
|
|
87
|
+
export function intentComplete(intent,state,a){
|
|
88
|
+
if(!intent)return false;const o=intent.desired_outcome,target=requestedTicket(intent,state),base=intent.created_from??{};
|
|
89
|
+
if(o==="CONTINUE")return false;
|
|
90
|
+
if(o==="CONTINUE_PRODUCT")return state.product.status==="ready";
|
|
91
|
+
if(o==="REVISE_PRODUCT")return state.product.status==="ready"&&Number(state.product.revision)>Number(base.product_revision??0);
|
|
92
|
+
if(o==="REFINE_PRODUCT")return Boolean(a.product?.digest&&base.product_digest&&a.product.digest!==base.product_digest);
|
|
93
|
+
if(o==="CONTINUE_PLANNING")return planningReady(state);
|
|
94
|
+
if(o==="PLANNING_REVIEW")return state.planning.readiness!==base.planning_readiness||a.engineering?.digest!==base.engineering_digest;
|
|
95
|
+
if(o==="CREATE_SPEC")return Boolean(currentSpecId(state));
|
|
96
|
+
if(o==="CREATE_TICKETS")return currentTicketIds(state,a).length>0;
|
|
97
|
+
if(o==="IMPLEMENT"||o==="REPAIR")return Boolean(target&&state.tickets[target]==="REVIEW_REQUIRED");
|
|
98
|
+
if(o==="REVIEW")return Boolean(target&&state.tickets[target]!=="REVIEW_REQUIRED");
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function baseRoute(state,a){
|
|
103
|
+
if(state.product.status!=="ready")return {workflow:ROUTES.product,ticket:null};
|
|
104
|
+
const replan=Object.keys(state.tickets).sort(byId).find(id=>state.tickets[id]==="REPLAN_REQUIRED");if(replan)return{workflow:ROUTES.replan,ticket:replan};
|
|
105
|
+
if(state.planning.status!=="ready"||state.planning.readiness!=="PASS")return{workflow:ROUTES.planning,ticket:null};
|
|
106
|
+
if(!currentSpecId(state))return{workflow:ROUTES.spec,ticket:null};
|
|
107
|
+
const ids=currentTicketIds(state,a);
|
|
108
|
+
const repair=ids.find(id=>state.tickets[id]==="REPAIR_REQUIRED");if(repair)return{workflow:ROUTES.repair,ticket:repair};
|
|
109
|
+
const review=ids.find(id=>state.tickets[id]==="REVIEW_REQUIRED");if(review)return{workflow:ROUTES.review,ticket:review};
|
|
110
|
+
const progress=ids.find(id=>state.tickets[id]==="IN_PROGRESS");if(progress)return{workflow:ROUTES.verify,ticket:progress};
|
|
111
|
+
const ready=ids.find(id=>state.tickets[id]==="READY"&&dependenciesPass(id,state,a));if(ready)return{workflow:ROUTES.implement,ticket:ready};
|
|
112
|
+
const draft=ids.find(id=>state.tickets[id]==="DRAFT"&&dependenciesPass(id,state,a));if(draft)return{workflow:ROUTES.tickets,ticket:draft};
|
|
113
|
+
if(ids.length===0)return{workflow:ROUTES.tickets,ticket:null};
|
|
114
|
+
if(ids.every(id=>TERMINAL.has(state.tickets[id]))){if(state.planning.scope_status==="COMPLETE")return{terminal:"COMPLETE"};return{workflow:ROUTES.planning,ticket:null};}
|
|
115
|
+
const blocked=ids.find(id=>state.tickets[id]==="BLOCKED");if(blocked)return{blocked:`ticket ${blocked} is BLOCKED`,ticket:blocked};
|
|
116
|
+
return{blocked:"no legal next workflow from current durable artifacts",ticket:null};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function legalRequested(kernel,workflow,ticket,state,a){
|
|
120
|
+
if(!dispatchableWorkflows(kernel).has(workflow))return false;
|
|
121
|
+
if(workflow==="prd.route"||workflow==="prd.revise"||workflow==="prd.refine")return true;
|
|
122
|
+
if(workflow==="planning.route"||workflow==="planning.readiness-review")return state.product.status==="ready";
|
|
123
|
+
if(workflow==="planning.create-spec")return planningReady(state)&&!currentSpecId(state);
|
|
124
|
+
if(workflow==="planning.create-tickets")return planningReady(state)&&Boolean(currentSpecId(state));
|
|
125
|
+
if(workflow==="implementation.implement-ticket")return Boolean(ticket&&state.tickets[ticket]==="READY"&&sourceCurrent(ticket,state,a)&&dependenciesPass(ticket,state,a));
|
|
126
|
+
if(workflow==="implementation.repair-ticket")return Boolean(ticket&&state.tickets[ticket]==="REPAIR_REQUIRED"&&sourceCurrent(ticket,state,a));
|
|
127
|
+
if(workflow==="review.review-ticket")return Boolean(ticket&&state.tickets[ticket]==="REVIEW_REQUIRED"&&sourceCurrent(ticket,state,a));
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function planNext(kernel,state,a,repo,intent){
|
|
132
|
+
const reconciliation=selectReconciliation(kernel,state,a,repo);if(reconciliation)return{type:"RECONCILE_REQUIRED",reconciliation};
|
|
133
|
+
if(intentComplete(intent,state,a))return{type:"INTENT_COMPLETE",completion_kind:intent.completion_kind};
|
|
134
|
+
if(state.phase==="complete"&&!["prd.revise","prd.refine"].includes(intent?.requested_workflow))return{type:"TERMINAL",terminal:"COMPLETE"};
|
|
135
|
+
if(intent?.desired_outcome==="REVISE_PRODUCT"&&Number(state.product.revision)>Number(intent.created_from?.product_revision??0)&&state.product.status!=="ready")return{type:"ROUTE",workflow:ROUTES.product,ticket:null};
|
|
136
|
+
if(intent&&intent.requested_workflow&&intent.requested_workflow!=="orchestration.route"){
|
|
137
|
+
let ticket=requestedTicket(intent,state);
|
|
138
|
+
if(!ticket&&intent.desired_outcome==="IMPLEMENT")ticket=Object.keys(state.tickets).sort(byId).find(id=>state.tickets[id]==="READY"&&dependenciesPass(id,state,a))??null;
|
|
139
|
+
if(!ticket&&intent.desired_outcome==="REPAIR")ticket=Object.keys(state.tickets).sort(byId).find(id=>state.tickets[id]==="REPAIR_REQUIRED")??null;
|
|
140
|
+
if(!ticket&&intent.desired_outcome==="REVIEW")ticket=Object.keys(state.tickets).sort(byId).find(id=>state.tickets[id]==="REVIEW_REQUIRED")??null;
|
|
141
|
+
if(legalRequested(kernel,intent.requested_workflow,ticket,state,a))return{type:"ROUTE",workflow:intent.requested_workflow,ticket};
|
|
142
|
+
return{type:"BLOCKED",reason:`PRECONDITION_UNSATISFIED:${intent.requested_workflow}`,ticket};
|
|
143
|
+
}
|
|
144
|
+
return{type:"ROUTE",...baseRoute(state,a)};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function chooseIntentTarget(skill,state,a){
|
|
148
|
+
if(!skill)return null;const ids=currentTicketIds(state,a);
|
|
149
|
+
if(skill.desired_outcome==="IMPLEMENT")return ids.find(id=>state.tickets[id]==="READY"&&dependenciesPass(id,state,a))??null;
|
|
150
|
+
if(skill.desired_outcome==="REPAIR")return ids.find(id=>state.tickets[id]==="REPAIR_REQUIRED")??null;
|
|
151
|
+
if(skill.desired_outcome==="REVIEW")return ids.find(id=>state.tickets[id]==="REVIEW_REQUIRED")??null;
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { access, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join, relative, resolve } from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { validateContracts, validateDispatchFiles } from "./contracts.mjs";
|
|
7
|
+
import { parseFrontmatter } from "./frontmatter.mjs";
|
|
8
|
+
import { deriveState, planNext, chooseIntentTarget } from "./routing.mjs";
|
|
9
|
+
|
|
10
|
+
const hash=v=>"sha256:"+createHash("sha256").update(v).digest("hex");
|
|
11
|
+
const stable=value=>Array.isArray(value)?value.map(stable):(value&&typeof value==="object"?Object.fromEntries(Object.keys(value).sort().map(k=>[k,stable(value[k])])):value);
|
|
12
|
+
const same=(a,b)=>JSON.stringify(stable(a))===JSON.stringify(stable(b));
|
|
13
|
+
const rel=(root,path)=>relative(root,path).replaceAll("\\","/");
|
|
14
|
+
async function exists(path){try{await access(path);return true}catch{return false}}
|
|
15
|
+
async function json(path,fallback=null){try{return JSON.parse(await readFile(path,"utf8"))}catch{return fallback}}
|
|
16
|
+
async function meta(root,path){try{const raw=await readFile(path,"utf8");return{path:rel(root,path),meta:parseFrontmatter(raw),digest:hash(Buffer.from(raw,"utf8"))}}catch{return null}}
|
|
17
|
+
async function list(dir,ext){try{return(await readdir(dir)).filter(x=>x.endsWith(ext)).sort()}catch{return[]}}
|
|
18
|
+
function execJson(file,workspace){const r=spawnSync(process.execPath,[file,"--workspace",workspace],{encoding:"utf8",windowsHide:true});let value=null;try{value=JSON.parse(r.stdout)}catch{}return value??{status:"UNKNOWN",error:r.stderr||`exit ${r.status}`}}
|
|
19
|
+
function argsOf(argv){const out={workspace:process.cwd(),invoke:null,inspect:false,reconcile:false,check:false};for(let i=0;i<argv.length;i+=1){const x=argv[i];if(x==="--workspace"&&argv[i+1]){out.workspace=argv[++i]}else if(x==="--invoke-skill"&&argv[i+1]){out.invoke=argv[++i]}else if(x==="--inspect-only")out.inspect=true;else if(x==="--reconcile-one")out.reconcile=true;else if(x==="--check-handoff")out.check=true;else throw new Error(`unknown argument: ${x}`)}return out}
|
|
20
|
+
|
|
21
|
+
async function inspectArtifacts(root){
|
|
22
|
+
const p=join(root,".yaaw-core","project"),product=await meta(root,join(p,"product.md")),engineering=await meta(root,join(p,"engineering.md")),specs={},tickets={},reviews={},evidence={},research={},rules={};
|
|
23
|
+
for(const name of await list(join(p,"specs"),".md")){const x=await meta(root,join(p,"specs",name));if(x?.meta?.id)specs[x.meta.id]=x}
|
|
24
|
+
for(const name of await list(join(p,"tickets"),".md")){const x=await meta(root,join(p,"tickets",name));if(x?.meta?.id)tickets[x.meta.id]=x}
|
|
25
|
+
for(const name of await list(join(p,"reviews"),".md")){const x=await meta(root,join(p,"reviews",name));if(x?.meta?.ticket)reviews[name]=x}
|
|
26
|
+
for(const name of await list(join(p,"evidence"),".json")){const x=await json(join(p,"evidence",name));if(x?.id){x.path=rel(root,join(p,"evidence",name));evidence[x.id]=x}}
|
|
27
|
+
for(const name of await list(join(p,"research"),".md")){const x=await meta(root,join(p,"research",name));if(x)research[name]=x}
|
|
28
|
+
for(const name of await list(join(p,"rules"),".md")){const x=await meta(root,join(p,"rules",name));if(x)rules[name]=x}
|
|
29
|
+
return{product,engineering,specs,tickets,reviews,evidence,research,rules};
|
|
30
|
+
}
|
|
31
|
+
function frameworkBasis(i){return{yaaw_version:i.package_version??"unknown",system_schema:Number(i.system_schema??0),installation_schema:Number(i.installation_schema??0),project_schema:Number(i.project_schema??0),manifest_digest:i.manifest_digest??"unknown",integrity_status:i.status??"UNKNOWN"}}
|
|
32
|
+
function baseline(state,a){return{product_revision:state.product.revision,product_digest:a.product?.digest??null,engineering_revision:state.planning.revision,engineering_digest:a.engineering?.digest??null,planning_readiness:state.planning.readiness,active_spec:state.planning.active_spec,ticket_statuses:state.tickets}}
|
|
33
|
+
async function seedIntent(root,kernel,skillId,state,a){const s=kernel.skills[skillId];if(!s)throw new Error(`unknown skill ${skillId}`);const intent={schema:"yaaw.intent/v3",source_skill:skillId,desired_outcome:s.desired_outcome,requested_workflow:s.requested_workflow,target_artifact:chooseIntentTarget(s,state,a),completion_kind:s.completion_kind,created_from:baseline(state,a)};await mkdir(join(root,".yaaw-core","runtime"),{recursive:true});await writeFile(join(root,".yaaw-core","runtime","intent.json"),JSON.stringify(intent,null,2)+"\n");return intent}
|
|
34
|
+
function selectedSpec(state,a,ticket){const sid=ticket?a.tickets?.[ticket]?.meta?.spec:String(state.planning.active_spec??"").match(/SPEC-[0-9]+/)?.[0];return sid?a.specs?.[sid]??null:null}
|
|
35
|
+
function refsFor(reads,state,a,ticket){const refs=[];const push=x=>{if(x&&!refs.includes(x))refs.push(x)};for(const kind of reads){if(kind==="product")push(a.product?.path);else if(kind==="engineering")push(a.engineering?.path);else if(kind==="spec")push(selectedSpec(state,a,ticket)?.path);else if(kind==="ticket"){if(ticket)push(a.tickets?.[ticket]?.path);else Object.values(a.tickets??{}).forEach(x=>push(x.path))}else if(kind==="engineering_research")Object.values(a.research??{}).forEach(x=>push(x.path));else if(kind==="project_rule")Object.values(a.rules??{}).forEach(x=>push(x.path));else if(kind==="evidence")Object.values(a.evidence??{}).filter(x=>!ticket||x.ticket===ticket).forEach(x=>push(x.path));else if(kind==="review")Object.values(a.reviews??{}).filter(x=>!ticket||x.meta?.ticket===ticket).forEach(x=>push(x.path))}return refs}
|
|
36
|
+
function revisions(state,a,ticket){const spec=selectedSpec(state,a,ticket);return{product:Number(state.product.revision??0),engineering:Number(state.planning.revision??0),spec:Number(spec?.meta?.revision??0),ticket:Number(ticket?a.tickets?.[ticket]?.meta?.revision??0:0)}}
|
|
37
|
+
function basis(state,a,ticket){const spec=selectedSpec(state,a,ticket);return{product_digest:a.product?.digest??null,engineering_digest:a.engineering?.digest??null,spec_digest:spec?.digest??null,ticket_digest:ticket?a.tickets?.[ticket]?.digest??null:null,ticket_status:ticket?state.tickets?.[ticket]??null:null}}
|
|
38
|
+
function modulesFor(kernel,role,policy,a,ticket){const names=[...(policy.required_modules??[])];if(policy.ticket_modules&&ticket)for(const x of a.tickets?.[ticket]?.meta?.expertise??[])names.push(x);return[...new Set(names)].filter(name=>kernel.modules[name]?.usable_by?.includes(role)).map(name=>kernel.modules[name].path)}
|
|
39
|
+
function handoff(kernel,framework,state,a,repo,workflow,ticket,intent){const wf=kernel.workflows[workflow],policy=kernel.handoffs[workflow],role=kernel.roles[wf?.role];if(!wf||!policy||!role)throw new Error(`no handoff contract for ${workflow}`);for(const kind of ["reads","writes"])for(const artifact of policy[kind]??[])if(!role[kind].includes(artifact))throw new Error(`workflow ${workflow} ${kind} unauthorized artifact ${artifact}`);return{schema:"yaaw.handoff/v4",framework:frameworkBasis(framework),role:wf.role,workflow,operation:wf.operation,instruction:{document:role.document,operation:wf.operation},desired_intent:intent?.desired_outcome??null,active_artifact:policy.active_artifact??null,ticket:ticket??null,references:refsFor(policy.reads,state,a,ticket),reads:policy.reads,writes:policy.writes,forbidden_writes:Object.keys(kernel.artifacts).filter(x=>!role.writes.includes(x)),revisions:revisions(state,a,ticket),basis:basis(state,a,ticket),expertise:modulesFor(kernel,wf.role,policy,a,ticket),host_expertise:[],expected_output:policy.expected_output,result_vocabulary:policy.result_vocabulary,repository_requirement:wf.repository_requirement,repository:repo}}
|
|
40
|
+
function repoAllowed(requirement,repo){if(requirement==="NONE")return true;if(requirement==="INSPECT")return repo?.status==="READY"||repo?.status==="UNVERSIONED";return repo?.status==="READY"}
|
|
41
|
+
function patchStatus(text,status){const lines=String(text).split(/\r?\n/);if(lines[0]?.trim()!=="---")throw new Error("ticket missing frontmatter");const end=lines.slice(1).findIndex(x=>x.trim()==="---");if(end<0)throw new Error("ticket missing closing frontmatter");const idx=lines.slice(1,end+1).findIndex(x=>/^status:\s*/.test(x));if(idx<0)throw new Error("ticket missing status");lines[idx+1]=`status: ${status}`;return lines.join("\n")}
|
|
42
|
+
async function observed(root,framework,repo,state,a,reconciliation){const value={schema:"yaaw.observed-state/v4",framework:{...frameworkBasis(framework),modified:framework.modified??[],missing:framework.missing??[],local_overrides:framework.local_overrides??[],repair_required:Boolean(framework.repair_required)},repository:repo,derived:state,reconstructable:true,artifacts:{product:a.product,engineering:a.engineering,specs:a.specs,tickets:a.tickets,reviews:a.reviews,evidence:a.evidence,research:a.research,rules:a.rules},inconsistencies:[],candidate_actions:[],reconciliation};await mkdir(join(root,".yaaw-core","runtime"),{recursive:true});await writeFile(join(root,".yaaw-core","runtime","observed-state.json"),JSON.stringify(value,null,2)+"\n");return value}
|
|
43
|
+
|
|
44
|
+
async function main(){
|
|
45
|
+
const opt=argsOf(process.argv.slice(2)),root=resolve(opt.workspace),system=join(root,".yaaw-core","system"),runtime=join(root,".yaaw-core","runtime"),kernel=JSON.parse(await readFile(join(system,"kernel.yaml"),"utf8"));
|
|
46
|
+
const integrity=execJson(join(system,"engine","integrity.mjs"),root);if(integrity.status!=="HEALTHY"){console.log(JSON.stringify({type:"FRAMEWORK_STOP",reason:`FRAMEWORK_${integrity.status}`,framework:integrity}));return}
|
|
47
|
+
const contractErrors=validateContracts(kernel);
|
|
48
|
+
if(contractErrors.length){
|
|
49
|
+
const intent=await json(join(runtime,"intent.json")),sourceSkill=opt.invoke??intent?.source_skill??null,requested=kernel.skills[sourceSkill]?.requested_workflow??intent?.requested_workflow??null;
|
|
50
|
+
const subject=contractErrors[0].split(": ")[0],workflow=kernel.workflows[subject]?subject:requested??subject;
|
|
51
|
+
throw Object.assign(new Error(contractErrors.join("; ")),{diagnostic:{classification:"FRAMEWORK_DEFECT_OR_DAMAGED_INSTALLATION",workflow,requested_workflow:requested,source_skill:sourceSkill,routing_source:sourceSkill?"PUBLIC_SKILL_INTENT":"DETERMINISTIC_ROUTER",owning_role:kernel.workflows[workflow]?.role??null,framework_version:integrity.package_version,contract_type:"DISPATCH_CONTRACT",recommendation:"Update or repair YAAW-SE through the supported installer; preserve project memory."}});
|
|
52
|
+
}
|
|
53
|
+
const repo=execJson(join(system,"engine","repository-identity.mjs"),root),a=await inspectArtifacts(root),state=deriveState(a);
|
|
54
|
+
let intent=await json(join(runtime,"intent.json"));if(opt.invoke)intent=await seedIntent(root,kernel,opt.invoke,state,a);
|
|
55
|
+
const planned=planNext(kernel,state,a,repo,intent),reconciliation=planned.type==="RECONCILE_REQUIRED"?planned.reconciliation:null;await observed(root,integrity,repo,state,a,reconciliation);
|
|
56
|
+
if(opt.inspect){console.log(JSON.stringify({type:"INSPECTED",state,reconciliation}));return}
|
|
57
|
+
if(opt.reconcile){if(!reconciliation){console.log(JSON.stringify({type:"NO_RECONCILIATION"}));return}if(reconciliation.kind==="BLOCKED"){console.log(JSON.stringify({type:"BLOCKED",reason:reconciliation.reason}));return}const ticket=a.tickets?.[reconciliation.subject];if(!ticket)throw new Error(`reconciliation ticket missing: ${reconciliation.subject}`);const ticketPath=join(root,ticket.path),raw=await readFile(ticketPath,"utf8");await writeFile(ticketPath,patchStatus(raw,reconciliation.to),"utf8");for(const file of ["observed-state.json","handoff.json"])try{await writeFile(join(runtime,file),"")}catch{}console.log(JSON.stringify({type:"RECONCILED",reconciliation}));return}
|
|
58
|
+
if(opt.check){const old=await json(join(runtime,"handoff.json"));if(!old){console.log(JSON.stringify({type:"HANDOFF_STALE",reason:"missing handoff"}));return}const candidate=handoff(kernel,integrity,state,a,repo,old.workflow,old.ticket,intent);const fileErrors=await validateDispatchFiles(system,kernel,old.workflow,candidate.expertise);if(fileErrors.length)throw new Error(fileErrors.join("; "));console.log(JSON.stringify(same(old,candidate)?{type:"HANDOFF_FRESH"}:{type:"HANDOFF_STALE",reason:"durable basis changed"}));return}
|
|
59
|
+
if(planned.type!=="ROUTE"){if(planned.type!=="RECONCILE_REQUIRED")try{await writeFile(join(runtime,"handoff.json"),"")}catch{}console.log(JSON.stringify(planned));return}
|
|
60
|
+
if(planned.terminal){console.log(JSON.stringify({type:"TERMINAL",terminal:planned.terminal}));return}if(planned.blocked){console.log(JSON.stringify({type:"BLOCKED",reason:planned.blocked,ticket:planned.ticket??null}));return}
|
|
61
|
+
const wf=kernel.workflows[planned.workflow];if(!wf)throw new Error(`unknown workflow ${planned.workflow}`);if(wf.role==="orchestrator"){console.log(JSON.stringify({type:"ROOT_ACTION",workflow:planned.workflow,ticket:planned.ticket??null}));return}if(!repoAllowed(wf.repository_requirement,repo)){console.log(JSON.stringify({type:"BLOCKED",reason:"PRECONDITION_UNSATISFIED:REPOSITORY_IDENTITY_UNAVAILABLE",workflow:planned.workflow}));return}
|
|
62
|
+
const h=handoff(kernel,integrity,state,a,repo,planned.workflow,planned.ticket??null,intent);
|
|
63
|
+
const fileErrors=await validateDispatchFiles(system,kernel,planned.workflow,h.expertise);if(fileErrors.length)throw Object.assign(new Error(fileErrors.join("; ")),{diagnostic:{classification:"FRAMEWORK_DEFECT_OR_DAMAGED_INSTALLATION",workflow:planned.workflow,source_skill:intent?.source_skill??null,owning_role:h.role,framework_version:integrity.package_version,contract_type:"INSTRUCTION_OR_MODULE_FILE",recommendation:"Update or repair YAAW-SE through the supported installer; preserve project memory."}});
|
|
64
|
+
await mkdir(runtime,{recursive:true});await writeFile(join(runtime,"handoff.json"),JSON.stringify(h,null,2)+"\n");console.log(JSON.stringify({type:"DISPATCH_READY",workflow:planned.workflow,role:h.role,operation:h.operation,ticket:h.ticket,handoff:rel(root,join(runtime,"handoff.json"))}));
|
|
65
|
+
}
|
|
66
|
+
main().catch(error=>{process.stdout.write(JSON.stringify({type:"FRAMEWORK_STOP",reason:"FRAMEWORK_CONTRACT_INCONSISTENCY",error:String(error?.message??error),...(error?.diagnostic?{diagnostic:error.diagnostic}:{})})+"\n");process.exitCode=2});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "yaaw.kernel/v1",
|
|
3
|
+
"principle": "Persist semantic facts once; derive coordination state.",
|
|
4
|
+
"paths": {
|
|
5
|
+
"workspace_root": ".",
|
|
6
|
+
"system_root": ".yaaw-core/system",
|
|
7
|
+
"project_root": ".yaaw-core/project",
|
|
8
|
+
"runtime_root": ".yaaw-core/runtime",
|
|
9
|
+
"install_root": ".yaaw-core/install",
|
|
10
|
+
"product": ".yaaw-core/project/product.md",
|
|
11
|
+
"engineering": ".yaaw-core/project/engineering.md",
|
|
12
|
+
"research": ".yaaw-core/project/research",
|
|
13
|
+
"specs": ".yaaw-core/project/specs",
|
|
14
|
+
"tickets": ".yaaw-core/project/tickets",
|
|
15
|
+
"reviews": ".yaaw-core/project/reviews",
|
|
16
|
+
"evidence": ".yaaw-core/project/evidence",
|
|
17
|
+
"project_rules": ".yaaw-core/project/rules"
|
|
18
|
+
},
|
|
19
|
+
"artifacts": {
|
|
20
|
+
"product": {"path": ".yaaw-core/project/product.md", "durability": "PROJECT_DURABLE", "owner": "prd", "mutable": true},
|
|
21
|
+
"engineering": {"path": ".yaaw-core/project/engineering.md", "durability": "PROJECT_DURABLE", "owner": "planner", "mutable": true},
|
|
22
|
+
"engineering_research": {"path_pattern": ".yaaw-core/project/research/RSH-*.md", "durability": "PROJECT_DURABLE", "owner": "planner", "mutable": true},
|
|
23
|
+
"spec": {"path_pattern": ".yaaw-core/project/specs/SPEC-*.md", "durability": "PROJECT_DURABLE", "owner": "planner", "mutable": true},
|
|
24
|
+
"ticket": {"path_pattern": ".yaaw-core/project/tickets/TASK-*.md", "durability": "PROJECT_DURABLE", "owner": "planner", "mutable": true},
|
|
25
|
+
"ticket_status": {"embedded_in": "ticket", "field": "status", "durability": "PROJECT_DURABLE", "owner": "lifecycle", "mutable": true},
|
|
26
|
+
"review": {"path_pattern": ".yaaw-core/project/reviews/TASK-*-R*.md", "durability": "PROJECT_DURABLE", "owner": "reviewer", "mutable": false},
|
|
27
|
+
"evidence": {"path_pattern": ".yaaw-core/project/evidence/*.json", "durability": "PROJECT_DURABLE", "owner": "implementer", "mutable": false},
|
|
28
|
+
"project_rule": {"path_pattern": ".yaaw-core/project/rules/*.md", "durability": "PROJECT_DURABLE", "owner": "planner", "mutable": true},
|
|
29
|
+
"observed_state": {"path": ".yaaw-core/runtime/observed-state.json", "durability": "RUNTIME_REPLACEABLE", "owner": "orchestrator", "mutable": true},
|
|
30
|
+
"handoff": {"path": ".yaaw-core/runtime/handoff.json", "durability": "RUNTIME_REPLACEABLE", "owner": "orchestrator", "mutable": true},
|
|
31
|
+
"intent": {"path": ".yaaw-core/runtime/intent.json", "durability": "RUNTIME_REPLACEABLE", "owner": "orchestrator", "mutable": true},
|
|
32
|
+
"dispatch_failures": {"path": ".yaaw-core/runtime/dispatch-failures.json", "durability": "RUNTIME_REPLACEABLE", "owner": "orchestrator", "mutable": true},
|
|
33
|
+
"installation_manifest": {"path": ".yaaw-core/install/manifest.json", "durability": "INSTALLER_MANAGED", "owner": "installer", "mutable": true},
|
|
34
|
+
"repository": {"virtual": true, "durability": "OBSERVED", "owner": "none", "mutable": false},
|
|
35
|
+
"application_files": {"virtual": true, "durability": "APPLICATION", "owner": "implementer", "mutable": true}
|
|
36
|
+
},
|
|
37
|
+
"roles": {
|
|
38
|
+
"prd": {"document": ".yaaw-core/system/roles/prd.md", "reads": ["product"], "writes": ["product"]},
|
|
39
|
+
"planner": {"document": ".yaaw-core/system/roles/planner.md", "reads": ["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review"], "writes": ["engineering","engineering_research","spec","ticket","project_rule"]},
|
|
40
|
+
"implementer": {"document": ".yaaw-core/system/roles/implementer.md", "reads": ["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review","application_files"], "writes": ["application_files","evidence"]},
|
|
41
|
+
"reviewer": {"document": ".yaaw-core/system/roles/reviewer.md", "reads": ["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review","application_files"], "writes": ["review"]},
|
|
42
|
+
"orchestrator": {"document": ".yaaw-core/system/roles/orchestrator.md", "reads": ["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review","observed_state","handoff","intent","installation_manifest","dispatch_failures"], "writes": ["ticket_status","observed_state","handoff","intent","dispatch_failures"]}
|
|
43
|
+
},
|
|
44
|
+
"workflows": {
|
|
45
|
+
"prd.route": {"role":"prd","operation":"route","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
46
|
+
"prd.create": {"role":"prd","operation":"create","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
47
|
+
"prd.question-round": {"role":"prd","operation":"question-round","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
48
|
+
"prd.record-decisions": {"role":"prd","operation":"record-decisions","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
49
|
+
"prd.revise": {"role":"prd","operation":"revise","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
50
|
+
"prd.refine": {"role":"prd","operation":"refine","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
51
|
+
"prd.readiness": {"role":"prd","operation":"readiness","repository_requirement":"NONE","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
52
|
+
"planning.route": {"role":"planner","operation":"route","repository_requirement":"INSPECT","external_research":"metadata-only","execution_context":"ISOLATED_PREFERRED"},
|
|
53
|
+
"planning.discover": {"role":"planner","operation":"discover","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
54
|
+
"planning.write-understanding": {"role":"planner","operation":"write-understanding","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
55
|
+
"planning.decision-frontier": {"role":"planner","operation":"decision-frontier","repository_requirement":"INSPECT","external_research":"admission-only","execution_context":"ISOLATED_PREFERRED"},
|
|
56
|
+
"planning.research": {"role":"planner","operation":"research","repository_requirement":"INSPECT","external_research":"candidate-scoped","execution_context":"ISOLATED_PREFERRED"},
|
|
57
|
+
"planning.question-round": {"role":"planner","operation":"question-round","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
58
|
+
"planning.record-decisions": {"role":"planner","operation":"record-decisions","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
59
|
+
"planning.readiness-review": {"role":"planner","operation":"readiness-review","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
60
|
+
"planning.create-spec": {"role":"planner","operation":"create-spec","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
61
|
+
"planning.create-tickets": {"role":"planner","operation":"create-tickets","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
62
|
+
"planning.replan": {"role":"planner","operation":"replan","repository_requirement":"INSPECT","external_research":"admission-only","execution_context":"ISOLATED_PREFERRED"},
|
|
63
|
+
"implementation.select-ticket": {"role":"implementer","operation":"select-ticket","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
64
|
+
"implementation.implement-ticket": {"role":"implementer","operation":"implement-ticket","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
65
|
+
"implementation.verify-ticket": {"role":"implementer","operation":"verify-ticket","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
66
|
+
"implementation.repair-ticket": {"role":"implementer","operation":"repair-ticket","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
67
|
+
"review.inspect-change": {"role":"reviewer","operation":"inspect-change","repository_requirement":"IDENTITY","external_research":"restricted","execution_context":"ISOLATED_PREFERRED"},
|
|
68
|
+
"review.review-ticket": {"role":"reviewer","operation":"review-ticket","repository_requirement":"IDENTITY","external_research":"restricted","execution_context":"ISOLATED_PREFERRED"},
|
|
69
|
+
"review.classify-findings": {"role":"reviewer","operation":"classify-findings","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
70
|
+
"review.record-review": {"role":"reviewer","operation":"record-review","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ISOLATED_PREFERRED"},
|
|
71
|
+
"orchestration.route": {"role":"orchestrator","operation":"route","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ROOT_ONLY"},
|
|
72
|
+
"orchestration.inspect-state": {"role":"orchestrator","operation":"inspect-state","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ROOT_ONLY"},
|
|
73
|
+
"orchestration.reconcile-state": {"role":"orchestrator","operation":"reconcile-state","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ROOT_ONLY"},
|
|
74
|
+
"orchestration.determine-next-action": {"role":"orchestrator","operation":"determine-next-action","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ROOT_ONLY"},
|
|
75
|
+
"orchestration.dispatch": {"role":"orchestrator","operation":"dispatch","repository_requirement":"INSPECT","external_research":"forbidden","execution_context":"ROOT_ONLY"},
|
|
76
|
+
"orchestration.recover-interruption": {"role":"orchestrator","operation":"recover-interruption","repository_requirement":"IDENTITY","external_research":"forbidden","execution_context":"ROOT_ONLY"}
|
|
77
|
+
},
|
|
78
|
+
"handoffs": {
|
|
79
|
+
"prd.revise": {"active_artifact":"product","reads":["product"],"writes":["product"],"required_modules":[],"ticket_modules":false,"expected_output":"Human-approved revised product meaning, incremented semantic revision and provenance; READY or unresolved product questions. Downstream staleness is derived by Orchestrator.","result_vocabulary":["READY","HUMAN_INPUT_REQUIRED","BLOCKED"]},
|
|
80
|
+
"prd.refine": {"active_artifact":"product","reads":["product"],"writes":["product"],"required_modules":[],"ticket_modules":false,"expected_output":"Clarified product text preserving accepted meaning and semantic revision, or a typed product question/stop.","result_vocabulary":["READY","HUMAN_INPUT_REQUIRED","BLOCKED"]},
|
|
81
|
+
"planning.readiness-review": {"active_artifact":"engineering","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository"],"writes":["engineering"],"required_modules":[],"ticket_modules":false,"expected_output":"Current-frontier readiness result, source revisions, reason and evidence persisted only in engineering.md.","result_vocabulary":["PASS","MISSING_DECISIONS","PRODUCT_GAP","REPLAN","BLOCKED"]},
|
|
82
|
+
"prd.route": {"active_artifact":"product","reads":["product"],"writes":["product"],"required_modules":[],"ticket_modules":false,"expected_output":"Current product intent or a typed stop.","result_vocabulary":["READY","HUMAN_INPUT_REQUIRED","BLOCKED"]},
|
|
83
|
+
"planning.route": {"active_artifact":"engineering","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository"],"writes":["engineering","engineering_research","spec","ticket","project_rule"],"required_modules":[],"ticket_modules":false,"expected_output":"Current engineering frontier readiness or one typed planning result.","result_vocabulary":["READY","HUMAN_INPUT_REQUIRED","REPLAN","BLOCKED"]},
|
|
84
|
+
"planning.create-spec": {"active_artifact":"engineering","reads":["product","engineering","engineering_research","project_rule","repository"],"writes":["spec"],"required_modules":[],"ticket_modules":false,"expected_output":"One accepted specification or a typed prerequisite/stop.","result_vocabulary":["SUCCESS","PRECONDITION_UNSATISFIED","BLOCKED"]},
|
|
85
|
+
"planning.create-tickets": {"active_artifact":"spec","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository"],"writes":["ticket"],"required_modules":["changeability"],"ticket_modules":false,"expected_output":"Dependency-aware tickets or a typed prerequisite/stop.","result_vocabulary":["SUCCESS","PRECONDITION_UNSATISFIED","BLOCKED"]},
|
|
86
|
+
"planning.replan": {"active_artifact":"ticket","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review"],"writes":["engineering","engineering_research","spec","ticket","project_rule"],"required_modules":["changeability"],"ticket_modules":true,"expected_output":"Updated engineering contract and ticket admission state.","result_vocabulary":["READY","HUMAN_INPUT_REQUIRED","BLOCKED"]},
|
|
87
|
+
"implementation.implement-ticket": {"active_artifact":"ticket","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review","application_files"],"writes":["application_files","evidence"],"required_modules":["changeability"],"ticket_modules":true,"expected_output":"Start evidence, bounded implementation, and verification evidence or a typed stop.","result_vocabulary":["VERIFICATION_PASS","VERIFICATION_FAIL","REPLAN_REQUIRED","PRECONDITION_UNSATISFIED","BLOCKED"]},
|
|
88
|
+
"implementation.verify-ticket": {"active_artifact":"ticket","reads":["product","engineering","spec","ticket","project_rule","repository","evidence","application_files"],"writes":["evidence"],"required_modules":["changeability"],"ticket_modules":true,"expected_output":"One immutable implementation_verification record.","result_vocabulary":["VERIFICATION_PASS","VERIFICATION_FAIL","IMPLEMENTATION_INCOMPLETE","REPLAN_REQUIRED","BLOCKED"]},
|
|
89
|
+
"implementation.repair-ticket": {"active_artifact":"ticket","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review","application_files"],"writes":["application_files","evidence"],"required_modules":["changeability"],"ticket_modules":true,"expected_output":"Bounded repair plus fresh verification evidence or a typed stop.","result_vocabulary":["VERIFICATION_PASS","VERIFICATION_FAIL","REPLAN_REQUIRED","BLOCKED"]},
|
|
90
|
+
"review.review-ticket": {"active_artifact":"ticket","reads":["product","engineering","engineering_research","spec","ticket","project_rule","repository","evidence","review","application_files"],"writes":["review"],"required_modules":["testing","changeability"],"ticket_modules":true,"expected_output":"One immutable independent review round.","result_vocabulary":["PASS","REPAIR","REPLAN","BLOCKED"]}
|
|
91
|
+
},
|
|
92
|
+
"skills": {
|
|
93
|
+
"yaaw-orchestrator": {"role":"orchestrator","requested_workflow":"orchestration.route","desired_outcome":"CONTINUE","completion_kind":"CONTINUE_UNTIL_STOP","description":"Continue or recover by reconstructing reality and dispatching the next safe workflow."},
|
|
94
|
+
"yaaw-prd": {"role":"prd","requested_workflow":"prd.route","desired_outcome":"CONTINUE_PRODUCT","completion_kind":"PRODUCT_READY","description":"Create or continue product definition."},
|
|
95
|
+
"yaaw-revise-prd": {"role":"prd","requested_workflow":"prd.revise","desired_outcome":"REVISE_PRODUCT","completion_kind":"PRODUCT_REVISION_ADVANCED","description":"Change accepted product intent and invalidate stale downstream contracts."},
|
|
96
|
+
"yaaw-refine-prd": {"role":"prd","requested_workflow":"prd.refine","desired_outcome":"REFINE_PRODUCT","completion_kind":"PRODUCT_REFINED","description":"Improve product clarity without changing accepted meaning."},
|
|
97
|
+
"yaaw-planner": {"role":"planner","requested_workflow":"planning.route","desired_outcome":"CONTINUE_PLANNING","completion_kind":"PLANNING_READY","description":"Continue repository-backed engineering planning."},
|
|
98
|
+
"yaaw-planning-review": {"role":"planner","requested_workflow":"planning.readiness-review","desired_outcome":"PLANNING_REVIEW","completion_kind":"PLANNING_READINESS_DECIDED","description":"Assess current engineering-frontier readiness."},
|
|
99
|
+
"yaaw-create-spec": {"role":"planner","requested_workflow":"planning.create-spec","desired_outcome":"CREATE_SPEC","completion_kind":"CURRENT_SPEC_ACCEPTED","description":"Create the next specification from a ready frontier."},
|
|
100
|
+
"yaaw-create-ticket": {"role":"planner","requested_workflow":"planning.create-tickets","desired_outcome":"CREATE_TICKETS","completion_kind":"CURRENT_TICKETS_REGISTERED","description":"Create bounded implementation tickets."},
|
|
101
|
+
"yaaw-create-tickets": {"role":"planner","requested_workflow":"planning.create-tickets","desired_outcome":"CREATE_TICKETS","completion_kind":"CURRENT_TICKETS_REGISTERED","description":"Create dependency-aware bounded implementation tickets."},
|
|
102
|
+
"yaaw-implement": {"role":"implementer","requested_workflow":"implementation.implement-ticket","desired_outcome":"IMPLEMENT","completion_kind":"TICKET_REVIEW_REQUIRED","description":"Implement one READY ticket and produce verification evidence."},
|
|
103
|
+
"yaaw-repair": {"role":"implementer","requested_workflow":"implementation.repair-ticket","desired_outcome":"REPAIR","completion_kind":"TICKET_REVIEW_REQUIRED","description":"Repair one REPAIR_REQUIRED ticket."},
|
|
104
|
+
"yaaw-review": {"role":"reviewer","requested_workflow":"review.review-ticket","desired_outcome":"REVIEW","completion_kind":"TICKET_REVIEW_APPLIED","description":"Independently review implementation and classify its result."}
|
|
105
|
+
},
|
|
106
|
+
"modules": {
|
|
107
|
+
"frontend-design": {"path":".yaaw-core/system/modules/frontend-design.md","usable_by":["planner","implementer","reviewer"]},
|
|
108
|
+
"security": {"path":".yaaw-core/system/modules/security.md","usable_by":["planner","implementer","reviewer"]},
|
|
109
|
+
"testing": {"path":".yaaw-core/system/modules/testing.md","usable_by":["planner","implementer","reviewer"]},
|
|
110
|
+
"python": {"path":".yaaw-core/system/modules/python.md","usable_by":["planner","implementer","reviewer"]},
|
|
111
|
+
"changeability": {"path":".yaaw-core/system/modules/changeability.md","usable_by":["planner","implementer","reviewer"]}
|
|
112
|
+
},
|
|
113
|
+
"lifecycle": {
|
|
114
|
+
"ticket_states": ["DRAFT","READY","IN_PROGRESS","REVIEW_REQUIRED","REPAIR_REQUIRED","REPLAN_REQUIRED","BLOCKED","PASS","CANCELLED"],
|
|
115
|
+
"legal": [
|
|
116
|
+
{"from":"DRAFT","to":"READY","owner":"planner","workflow":"planning.create-tickets"},
|
|
117
|
+
{"from":"DRAFT","to":"CANCELLED","owner":"planner","workflow":"planning.replan"},
|
|
118
|
+
{"from":"READY","to":"IN_PROGRESS","owner":"implementer","workflow":"implementation.implement-ticket","writer":"orchestrator"},
|
|
119
|
+
{"from":"READY","to":"REPLAN_REQUIRED","owner":"planner","workflow":"planning.replan"},
|
|
120
|
+
{"from":"IN_PROGRESS","to":"REVIEW_REQUIRED","owner":"implementer","workflow":"implementation.verify-ticket","writer":"orchestrator"},
|
|
121
|
+
{"from":"IN_PROGRESS","to":"REPLAN_REQUIRED","owner":"planner","workflow":"planning.replan"},
|
|
122
|
+
{"from":"IN_PROGRESS","to":"BLOCKED","owner":"implementer","workflow":"implementation.implement-ticket","writer":"orchestrator"},
|
|
123
|
+
{"from":"REVIEW_REQUIRED","to":"PASS","owner":"reviewer","workflow":"review.record-review","writer":"orchestrator"},
|
|
124
|
+
{"from":"REVIEW_REQUIRED","to":"REPAIR_REQUIRED","owner":"reviewer","workflow":"review.record-review","writer":"orchestrator"},
|
|
125
|
+
{"from":"REVIEW_REQUIRED","to":"REPLAN_REQUIRED","owner":"reviewer","workflow":"review.record-review","writer":"orchestrator"},
|
|
126
|
+
{"from":"REVIEW_REQUIRED","to":"BLOCKED","owner":"reviewer","workflow":"review.record-review","writer":"orchestrator"},
|
|
127
|
+
{"from":"REPAIR_REQUIRED","to":"REVIEW_REQUIRED","owner":"implementer","workflow":"implementation.repair-ticket","writer":"orchestrator"},
|
|
128
|
+
{"from":"REPAIR_REQUIRED","to":"REPLAN_REQUIRED","owner":"planner","workflow":"planning.replan"},
|
|
129
|
+
{"from":"REPLAN_REQUIRED","to":"DRAFT","owner":"planner","workflow":"planning.replan"},
|
|
130
|
+
{"from":"REPLAN_REQUIRED","to":"READY","owner":"planner","workflow":"planning.replan"},
|
|
131
|
+
{"from":"PASS","to":"CANCELLED","owner":"planner","workflow":"planning.replan"},
|
|
132
|
+
{"from":"PASS","to":"REVIEW_REQUIRED","owner":"orchestrator","workflow":"orchestration.reconcile-state","causes":["REVIEW_MISSING","REVIEW_REPOSITORY_STALE","VERIFICATION_MISSING","VERIFICATION_REPOSITORY_STALE","LEGACY_IDENTITY_UNVERIFIABLE"],"writer":"orchestrator"},
|
|
133
|
+
{"from":"PASS","to":"REPLAN_REQUIRED","owner":"orchestrator","workflow":"orchestration.reconcile-state","causes":["PRODUCT_SOURCE_STALE","ENGINEERING_SOURCE_STALE","SPEC_SOURCE_STALE","TICKET_SOURCE_STALE","CONTRACT_INVALIDATED"],"writer":"orchestrator"}
|
|
134
|
+
],
|
|
135
|
+
"forbidden": [{"from":"DRAFT","to":"PASS"},{"from":"READY","to":"PASS"},{"from":"REPAIR_REQUIRED","to":"PASS"}],
|
|
136
|
+
"routing": {
|
|
137
|
+
"product_unready_workflow":"prd.route","planning_unready_workflow":"planning.route","missing_spec_workflow":"planning.create-spec","missing_tickets_workflow":"planning.create-tickets","draft_admission_workflow":"planning.create-tickets","next_frontier_workflow":"planning.route","complete_terminal":"COMPLETE",
|
|
138
|
+
"invalidation_routes": {
|
|
139
|
+
"PRODUCT_SOURCE_STALE":{"state":"REPLAN_REQUIRED","workflow":"planning.replan"},"ENGINEERING_SOURCE_STALE":{"state":"REPLAN_REQUIRED","workflow":"planning.replan"},"SPEC_SOURCE_STALE":{"state":"REPLAN_REQUIRED","workflow":"planning.replan"},"TICKET_SOURCE_STALE":{"state":"REPLAN_REQUIRED","workflow":"planning.replan"},"CONTRACT_INVALIDATED":{"state":"REPLAN_REQUIRED","workflow":"planning.replan"},"REVIEW_MISSING":{"state":"REVIEW_REQUIRED","workflow":"review.review-ticket"},"REVIEW_REPOSITORY_STALE":{"state":"REVIEW_REQUIRED","workflow":"review.review-ticket"},"VERIFICATION_MISSING":{"state":"REVIEW_REQUIRED","workflow":"review.review-ticket"},"VERIFICATION_REPOSITORY_STALE":{"state":"REVIEW_REQUIRED","workflow":"review.review-ticket"},"LEGACY_IDENTITY_UNVERIFIABLE":{"state":"REVIEW_REQUIRED","workflow":"review.review-ticket"}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"reconciliation_priority": ["CONTRACT_SOURCE_STALE","IMPLEMENTATION_STARTED","IMPLEMENTATION_VERIFIED","REVIEW_RESULT_UNAPPLIED","ACCEPTANCE_STALE"],
|
|
143
|
+
"one_reconciliation_per_cycle": true
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changeability expertise
|
|
2
|
+
|
|
3
|
+
Use this optional module when a ticket, design, or review has non-trivial maintainability implications. The mandatory policy is summarized in `SYSTEM.md`; this module provides deeper reasoning and examples, not additional authority.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
Optimize the changed surface for future comprehension, modification, verification, and rollback while preserving the current product/spec/ticket contract and repository conventions.
|
|
7
|
+
|
|
8
|
+
## Reasoning sequence
|
|
9
|
+
1. Identify the actual domain behavior being changed.
|
|
10
|
+
2. Identify the minimum authorized code surface needed to implement it safely.
|
|
11
|
+
3. Locate relevant boundaries, state models, decision logic, errors, and tests.
|
|
12
|
+
4. Apply only principles that materially affect that surface.
|
|
13
|
+
5. Prefer the smallest design that removes concrete ambiguity/coupling/risk.
|
|
14
|
+
6. Verify behavior and the relevant structural property.
|
|
15
|
+
7. Leave unrelated cleanup out of scope.
|
|
16
|
+
|
|
17
|
+
## Heuristics
|
|
18
|
+
- **Visible main path:** use guard clauses/decomposition when exceptional cases bury the operation; avoid mechanical style rewrites.
|
|
19
|
+
- **Domain naming:** expose business meaning where known; generic names are fine for genuinely generic mechanics.
|
|
20
|
+
- **External boundaries:** keep provider/transport/ORM schemas and failures at narrow adapters when the accepted architecture benefits.
|
|
21
|
+
- **Invalid states:** prefer explicit variants/constructors/validators when they remove meaningful runtime uncertainty.
|
|
22
|
+
- **Decisions versus actions:** keep important policy independently testable from side effects when practical.
|
|
23
|
+
- **Useful failures:** preserve stable machine identity plus safe human context; never expose secrets.
|
|
24
|
+
- **Focused changes:** a discovered smell is not automatically ticket scope; supporting refactors must be necessary for safe implementation or verification.
|
|
25
|
+
|
|
26
|
+
## Review guidance
|
|
27
|
+
Classify a concrete bounded changeability defect as REPAIR when the accepted contract remains valid. Use REPLAN only when satisfying it changes accepted architecture/spec meaning. Style preference alone is non-blocking.
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
# Implementer
|
|
1
|
+
# Implementer
|
|
2
2
|
|
|
3
3
|
## Authority
|
|
4
|
-
Own application changes and implementation evidence for one bounded admitted ticket at a time.
|
|
4
|
+
Own application changes and implementation evidence for one bounded admitted ticket at a time. Never self-approve or silently change product/engineering contracts.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
Use `SYSTEM.md` for shared invariants. Execute only the operation named by the deterministic handoff.
|
|
7
|
+
|
|
8
|
+
## Operation: select-ticket (`implementation.select-ticket`)
|
|
9
|
+
Require repository status READY. Reject DRAFT, BLOCKED, REPLAN_REQUIRED, REPAIR_REQUIRED, REVIEW_REQUIRED, PASS, CANCELLED, stale-source, or dependency-unsatisfied tickets for normal implementation. Choose the specifically requested eligible READY ticket, otherwise the next dependency-satisfied READY ticket. Revalidate product/engineering/spec/ticket revisions immediately before admission.
|
|
10
|
+
|
|
11
|
+
## Operation: implement-ticket (`implementation.implement-ticket`)
|
|
12
|
+
Require exact current handoff, ticket status READY, current source revisions/dependencies, and repository identity READY. **Before the first application mutation**, write immutable `yaaw.evidence/v3` `implementation_start` evidence with result STARTED, current ticket/spec revisions, workflow ID, and exact pre-edit repository identity. Only then implement inside allowed scope, applying changeability guidance and selected modules. Material contract gaps stop as REPLAN_REQUIRED/BLOCKED rather than being invented. Run verify-ticket and persist verification evidence. Do not edit ticket lifecycle status; Orchestrator derives/adopts READY->IN_PROGRESS from start evidence and IN_PROGRESS->REVIEW_REQUIRED from current PASS verification.
|
|
13
|
+
|
|
14
|
+
## Operation: verify-ticket (`implementation.verify-ticket`)
|
|
15
|
+
Run every ticket-required check plus justified targeted regressions. Verify materially relevant structural/changeability properties. After verification completes, capture canonical repository identity and write a new immutable `.yaaw-core/project/evidence/EVIDENCE-TASK-NNN-VK.json` using `yaaw.evidence/v3`, kind `implementation_verification`, with exactly PASS, FAIL, or BLOCKED. Preserve failed records; fixes create later records. If verification proves implementation materially incomplete, return `IMPLEMENTATION_INCOMPLETE` rather than silently broadening this operation.
|
|
16
|
+
|
|
17
|
+
## Operation: repair-ticket (`implementation.repair-ticket`)
|
|
18
|
+
Require ticket status REPAIR_REQUIRED and the latest current review result REPAIR. Load the unchanged contract, bounded findings, prior evidence, selected modules, and relevant code. Repair only those findings. Contract changes route to REPLAN_REQUIRED. Rerun verification and write fresh evidence distinct from the evidence referenced by the REPAIR review. Orchestrator adopts REPAIR_REQUIRED->REVIEW_REQUIRED only from fresh current PASS verification.
|
|
15
19
|
|
|
16
20
|
## Boundary
|
|
17
|
-
|
|
21
|
+
A lost worker response is not permission to restart implementation. Missing material decisions return through Orchestrator to Planner/PRD. Package-managed `.yaaw-core/system/**` is never writable semantic output.
|
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
# Orchestrator
|
|
1
|
+
# Orchestrator
|
|
2
2
|
|
|
3
3
|
## Authority
|
|
4
|
-
Own continuity, evidence-backed
|
|
4
|
+
Own continuity, evidence-backed observation, deterministic lifecycle adoption, invalidation coordination, recovery, public-intent continuation, and next-workflow dispatch. Orchestrator is a traffic controller, not a super-agent; it never authors product, engineering, implementation, research, or acceptance meaning.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
1. Resolve the workspace root through `.yaaw-core/system/core/execution-context.md`.
|
|
8
|
-
2. For a public skill, invoke `orchestration-runtime.mjs --invoke-skill <skill>`; otherwise prepare with `--workspace <root>`.
|
|
9
|
-
3. Consume exactly one typed result. `RECONCILE_REQUIRED` applies exactly one reconciliation, then observation repeats.
|
|
10
|
-
4. Dispatch exactly one semantic handoff only after framework health, reconciliation, source-current validation, repository policy, and intent prerequisites pass.
|
|
11
|
-
5. After worker success, failure, interruption, or lost response, throw away worker text as authority and observe durable reality again.
|
|
12
|
-
6. Continue until intent completion, human input, an unrecoverable typed blocker/framework stop, or project `COMPLETE`. Recoverable proof gaps must be routed to the owning verification/review workflow rather than surfaced as terminal blockers.
|
|
6
|
+
Use `SYSTEM.md` and `kernel.yaml` as the compact system contract.
|
|
13
7
|
|
|
14
|
-
##
|
|
15
|
-
|
|
8
|
+
## Operation: route (`orchestration.route`)
|
|
9
|
+
For normal continuation run `node .yaaw-core/system/engine/runtime.mjs --workspace <WORKSPACE_ROOT>`. For a public entrypoint append `--invoke-skill <skill-id>`. Repeat one deterministic boundary at a time: FRAMEWORK_STOP -> stop; RECONCILE_REQUIRED -> apply exactly one `--reconcile-one` then observe again; ROOT_ACTION -> run only the returned interruption-recovery operation; DISPATCH_READY -> execute exactly the persisted fresh handoff once; after any worker result/disappearance -> discard worker prose as authority and reobserve; INTENT_COMPLETE/TERMINAL/BLOCKED/human input -> stop.
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
## Operation: inspect-state (`orchestration.inspect-state`)
|
|
12
|
+
Run runtime with `--inspect-only`. It reconstructs product/planning/current spec/ticket lifecycle from durable artifacts, evidence/reviews, and repository identity and writes replaceable `runtime/observed-state.json`. Do not serialize a second state model or mutate semantic artifacts.
|
|
18
13
|
|
|
19
|
-
##
|
|
20
|
-
|
|
14
|
+
## Operation: reconcile-state (`orchestration.reconcile-state`)
|
|
15
|
+
Run runtime with `--reconcile-one`. Apply exactly one deterministic evidence-backed ticket lifecycle update permitted by `kernel.yaml`, then return to route. The only durable coordination mutation is the `status` scalar inside the affected ticket frontmatter. Do not maintain a global state/transition ledger. Planner-owned semantic contract edits remain Planner work; Reviewer outcomes remain Reviewer authority.
|
|
16
|
+
|
|
17
|
+
## Operation: determine-next-action (`orchestration.determine-next-action`)
|
|
18
|
+
Normal runtime preparation owns routing and handoff construction. Consume its typed result; do not duplicate route selection, repository identity, module selection, or handoff serialization in model reasoning.
|
|
19
|
+
|
|
20
|
+
## Operation: dispatch (`orchestration.dispatch`)
|
|
21
|
+
Immediately before execution run runtime with `--check-handoff` and require HANDOFF_FRESH. Execute the selected role and exact operation from the handoff using the host adapter's required effective execution profile. Prefer an isolated authority worker when available; never silently substitute an incompatible profile. If a child was created and failed, reobserve before any retry. The worker loads only its role document/operation, exact handoff references, selected modules, and minimal relevant application context. A worker never routes or spawns another YAAW authority. Treat worker text only as an execution signal; reobserve durable reality afterward.
|
|
22
|
+
|
|
23
|
+
## Operation: recover-interruption (`orchestration.recover-interruption`)
|
|
24
|
+
Use only for a proven interrupted execution boundary, never as the generic fallback for DRAFT admission or shortcut precondition failure. Discard stale runtime caches, identify the last trustworthy durable boundary from ticket status/evidence/reviews/repository identity, and route forward without duplicating completed work. IN_PROGRESS with current PASS verification goes to review; valid start evidence without PASS verification goes to verify; missing proof returns an exact blocker. If no interruption exists, return immediately to normal route.
|
|
25
|
+
|
|
26
|
+
## Runtime invariant
|
|
27
|
+
Delete `.yaaw-core/runtime/` and invoke YAAW again: the safe next semantic action must be reconstructable. If it is not, durable truth leaked into a cache and the framework contract is violated.
|
|
28
|
+
|
|
29
|
+
## Framework boundary
|
|
30
|
+
Never modify `.yaaw-core/system/**` during semantic work. Framework integrity failures stop and require installer repair/update.
|