okstra 0.189.0 → 0.189.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -244,6 +244,12 @@ export const COMMAND_REGISTRY = [
244
244
  category: "introspection",
245
245
  summary: ["Assemble a task's run-to-run phase recap or append a recap log entry"],
246
246
  },
247
+ {
248
+ name: "group-context",
249
+ python: { target: { module: "okstra_ctl.group_context" } },
250
+ category: "introspection",
251
+ summary: ["Create a task-group context skeleton beside the group's briefs"],
252
+ },
247
253
  {
248
254
  name: "user-response",
249
255
  python: { target: { module: "okstra_ctl.user_response" } },
@@ -1 +1 @@
1
- {"version":3,"file":"cli-registry.mjs","sourceRoot":"","sources":["../src/cli-registry.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-registry.mjs","sourceRoot":"","sources":["../src/cli-registry.mts"],"names":[],"mappings":"AAOA,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,kCAAkC;QAC1C,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,kCAAkC;QAC1C,MAAM,EAAE,oBAAoB;QAC5B,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,oCAAoC;QAC5C,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,gCAAgC;QACxC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,qDAAqD,CAAC;KACjE;IACD;QACE,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,iCAAiC;QACzC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE;YACP,sEAAsE;SACvE;KACF;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,wCAAwC;QAChD,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,2DAA2D,CAAC;KACvE;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,oCAAoC;QAC5C,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,qDAAqD,CAAC;KACjE;IACD;QACE,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,iCAAiC;QACzC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,sDAAsD,CAAC;KAClE;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,wCAAwC,CAAC;KACpD;IACD;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE;QACpD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE;QACxD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,2BAA2B,EAAE,EAAE;QAC3D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,oDAAoD,CAAC;KAChE;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,6BAA6B,EAAE,EAAE;QAC7D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,oDAAoD,CAAC;KAChE;IACD;QACE,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE,EAAE;QACvD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,gDAAgD,CAAC;KAC5D;IACD;QACE,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE;QACtD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,kDAAkD,CAAC;KAC9D;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAAE;QACtG,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,iDAAiD,CAAC;KAC7D;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;QACxF,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,wDAAwD,CAAC;KACpE;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE;YACP,uDAAuD;YACvD,gDAAgD;SACjD;KACF;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,EAAE;QAC1D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,+DAA+D,CAAC;KAC3E;IACD;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE;QACpD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,gEAAgE,CAAC;KAC5E;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE;QAC5D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,gDAAgD,CAAC;KAC5D;IACD;QACE,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,gCAAgC;QACxC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE;YACP,oEAAoE;SACrE;KACF;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,EAAE;QAC1D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,8CAA8C,CAAC;KAC1D;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,EAAE;QAC1D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,oDAAoD,CAAC;KAChE;IACD;QACE,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,EAAE;QACzD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,4DAA4D,CAAC;KACxE;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,EAAE;QAC1D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,+DAA+D,CAAC;KAC3E;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,EAAE;QACzD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,mDAAmD,CAAC;KAC/D;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,6BAA6B,EAAE,EAAE;QAC7D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,gEAAgE,CAAC;KAC5E;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,yDAAyD,CAAC;KACrE;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE;QAC5D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,4DAA4D,CAAC;KACxE;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE;QACxD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,2DAA2D,CAAC;KACvE;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,EAAE;QACzD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,2DAA2D,CAAC;KACvE;IACD;QACE,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE,EAAE;QACvD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,6DAA6D,CAAC;KACzE;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE;QAC5D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,4DAA4D,CAAC;KACxE;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,EAAE;QACzD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE;QACtD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,mDAAmD,CAAC;KAC/D;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE;QACtD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,wDAAwD,CAAC;KACpE;IACD;QACE,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE;QAClD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,sEAAsE,CAAC;KAClF;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,EAAE;QAC1D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,gEAAgE,CAAC;KAC5E;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,EAAE;QAC1D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,wFAAwF,CAAC;KACpG;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE;QACxD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,4DAA4D,CAAC;KACxE;IACD;QACE,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,EAAE;QACnD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,oEAAoE,CAAC;KAChF;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE;QACtD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,sDAAsD,CAAC;KAClE;IACD;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;QACpF,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,mCAAmC,CAAC;KAC/C;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,gCAAgC,EAAE,EAAE;QAChE,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,4CAA4C,CAAC;KACxD;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,gCAAgC,EAAE,EAAE;QAChE,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,4DAA4D,CAAC;KACxE;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,8BAA8B,EAAE,EAAE;QAC9D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,qDAAqD,CAAC;KACjE;IACD;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,sCAAsC;QAC9C,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,mDAAmD;YACnD,0CAA0C;SAC3C;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,EAAE;QACzD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,0DAA0D;YAC1D,yCAAyC;SAC1C;KACF;IACD;QACE,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,4BAA4B;QACpC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,sCAAsC,CAAC;KAClD;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,MAAM,EAAE,CAAC,eAAe,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;QAClI,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,8CAA8C;YAC9C,4CAA4C;SAC7C;KACF;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAAE;QACtG,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,sDAAsD,CAAC;KAClE;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,EAAE;QACzD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,+CAA+C,CAAC;KAC3D;IACD;QACE,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAAE;QAC3F,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,2DAA2D,CAAC;KACvE;IACD;QACE,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,+BAA+B;QACvC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,sDAAsD;YACtD,4CAA4C;SAC7C;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE,EAAE;QACvD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,oDAAoD;YACpD,gDAAgD;YAChD,mCAAmC;SACpC;KACF;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,8DAA8D,CAAC;KAC1E;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE;QAC5D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,mDAAmD;YACnD,mDAAmD;YACnD,4BAA4B;SAC7B;KACF;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,2BAA2B,EAAE,EAAE;QAC3D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,8DAA8D,CAAC;KAC1E;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,4CAA4C,CAAC;KACxD;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE;QAC5D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,2DAA2D,CAAC;KACvE;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;QACxF,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,oDAAoD;YACpD,qDAAqD;YACrD,6CAA6C;SAC9C;KACF;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,yDAAyD,CAAC;KACrE;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,EAAE;QAC/D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,0DAA0D,CAAC;KACtE;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,2BAA2B,EAAE,EAAE;QAC3D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,mDAAmD,CAAC;KAC/D;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,qBAAqB,EAAE,EAAE;QACrD,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,8CAA8C,CAAC;KAC1D;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,8BAA8B,EAAE,EAAE;QAC9D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,oEAAoE,CAAC;KAChF;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,8BAA8B,EAAE,EAAE;QAC9D,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,CAAC,qEAAqE,CAAC;KACjF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,8BAA8B;QACtC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,oDAAoD;YACpD,wBAAwB;SACzB;KACF;IACD;QACE,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,0BAA0B;QAClC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,yDAAyD;SAC1D;KACF;IACD;QACE,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,sBAAsB;QAC9B,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE;YACP,oDAAoD;YACpD,sCAAsC;SACvC;KACF;CACqC,CAAC;AAEzC,iDAAiD;AACjD,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GACxB,gBAAiD;KAC/C,MAAM,CAAC,CAAC,CAAC,EAAgC,EAAE,CAAC,QAAQ,IAAI,CAAC,CAAC;KAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAEjC,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,UAA6B;IACtD,8CAA8C;IAC9C,qDAAqD;IACrD,iCAAiC;IACjC,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACtE,OAAO,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,YAAY,GAAY,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,mCAAmC,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,EAAE,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAC7B,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1B,CAAC,CAAC,IAAI;IACN,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;CACrB,CAAC,CACH,CAAC;AAEF,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;CAgBhB,CAAC;AAEF,MAAM,cAAc,GAAG;yCACkB,CAAC;AAE1C,MAAM,MAAM,GAAG;;;;CAId,CAAC;AAEF,SAAS,SAAS,CAAC,OAA0B;IAC3C,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IACpE,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5E,OAAO,CAAC,IAAI,EAAE,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,QAAuC;IACzD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC;SAC3D,GAAG,CAAC,SAAS,CAAC;SACd,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAChB,QAAQ;IACR,qBAAqB;IACrB,UAAU,CAAC,OAAO,CAAC;IACnB,2FAA2F;IAC3F,UAAU,CAAC,eAAe,CAAC;IAC3B,uBAAuB;IACvB,cAAc;IACd,MAAM,CAAC"}
@@ -367,8 +367,17 @@ The history generally includes the following.
367
367
  - related tasks
368
368
  - workflow snapshot
369
369
  - `fixCycleId` *(only when attached to a fix cycle; field omitted otherwise)*
370
+
371
+ An entry is written once, when the run is prepared (`render.render_timeline`, called only from `prepare_task_bundle`). Its `status`, `workflowSnapshot`, and `reportRecordPath` are therefore the values at preparation time: `status` is `prepared` or `in-progress`, the snapshot is the workflow as it stood before the run, and the report path is the run's *reserved* record path. The run's current facts live in its own `run-manifest-<task-type>-<seq>.json`, which `validators/validate-run.py` updates when the run ends (`status`, `validation`, `workflowSnapshot`); task-level current facts (`currentStatus`, `latestRunStatus`, `workflow.*`, `latestReportRecordPath`) live in `task-manifest.json`. Read-side projections (`okstra model-io history-input` / `recap-input`, `okstra recap assemble`) overlay each entry with its run-manifest through `okstra_ctl.timeline_runs.current_run_facts`, and a run whose `validation.status` is still `not-run` projects no report path — the report sequence is allocated from files on disk, so a prepared-but-never-run entry's reservation is reused by the next run and would otherwise point at that later run's report.
372
+
370
373
  Reruns of the same task type reuse the same resolved run directory family. Non-stage runs use `runs/<task-type>/`, while `implementation` and single-stage `final-verification` runs use `runs/<task-type>/stage-<N>/`. Sequence-specific artifacts live beneath that resolved run directory, and each execution accumulates as a separate history entry because `run-manifest-<task-type>-<seq>.json` and related artifact paths are separated by per-category sequence suffixes (`<task-type>-<seq>`). The cross-category identifier is the manifest's `runDateTimeSegment` ISO timestamp field.
371
374
 
375
+ ## Task-group context contract
376
+
377
+ `.okstra/briefs/<task-group>/group-context.md` is the one document a task-group shares: why the group exists, how its result is measured (with the denominator named), group-wide constraints, and ticket relations. It is optional — a group without it prepares as before. The skeleton comes from `okstra group-context init` (`templates/reports/group-context.template.md`; frontmatter `type: group-context`, `task-group`, `created`, `generator`) and the user fills the four sections `Why This Group Exists`, `Definition of Better`, `Group-Wide Constraints`, `Ticket Relations` (the last two accept `_(none)_`). `validators/validate-brief.py` dispatches on the frontmatter `type`, so the group's directory validation covers briefs and the context together (`okstra_ctl.group_context.validate_group_context`).
378
+
379
+ Preparation validates the file before any side effect and refuses one that still carries a `<...>` placeholder line (`run._validate_group_context_preflight`), then copies it to `instruction-set/task-group-context.md` and the analysis packet carries it as `## Task-Group Context` between `## Source Files` and `## Task-Specific Brief Extract`, behind a fixed preface that separates the group's measure and constraints from the brief's scope. The wizard's brief suggestions skip the file.
380
+
372
381
  ## Lead operating contract
373
382
 
374
383
  After `okstra` prepares a run, the host-native Okstra lead follows this default sequence when reading the current task.
package/docs/cli.md CHANGED
@@ -201,6 +201,8 @@ Examples:
201
201
  - `.project-docs/linear/feature/8858/okstra-task-brief.md`
202
202
  - `.project-docs/tasks/8852/BUG_REPORT.md`
203
203
 
204
+ When the task-group directory beside the brief holds `group-context.md` (`.okstra/briefs/<task-group>/group-context.md`, skeleton from `okstra group-context init`), preparation validates it, copies it to `instruction-set/task-group-context.md`, and the analysis packet carries it as `## Task-Group Context` ahead of `## Task-Specific Brief Extract`. A file that still carries a template placeholder line fails preparation; delete it if the group needs no context.
205
+
204
206
  ### `--yes`
205
207
 
206
208
  Skips interactive prompts and confirmation.
@@ -792,6 +794,7 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
792
794
  | `okstra convergence finalize --work-state <path> --output <path>` | Materialize the terminal schema v1.3 convergence state |
793
795
  | `okstra convergence validate --state <path> --kind <working\|final>` | Validate replayable working state or a terminal final state |
794
796
  | `okstra convergence example --kind <groups\|round-results\|critic-results\|coverage-batch>` | Print one deterministic valid input example as JSON. Each kind feeds one command: `groups` → `seed --groups`, `round-results` → `apply-round --results`, `coverage-batch` → `apply-critic-gaps --results`. `critic-results` feeds nothing — it is the critic worker's own result document, and feeding it to `apply-critic-gaps` is rejected by design; that reducer takes the coverage batch the lead assembles from those candidates plus each analyser's vote, which is what `--kind coverage-batch` prints |
797
+ | `okstra group-context init --project-root <root> --task-group <group>` | Write the task-group context skeleton `.okstra/briefs/<task-group>/group-context.md` from `templates/reports/group-context.template.md` and print the sections to fill. Exits 2 when the file already exists. The filled document is validated by `validators/validate-brief.py` (frontmatter `type: group-context`), copied by preparation into `instruction-set/task-group-context.md`, and carried in the analysis packet's `## Task-Group Context` section ahead of the brief extract; preparation refuses a file that still carries a `<...>` placeholder line, and a task-group without the file prepares as before |
795
798
  | `okstra plan-items extract (--narrative <report-narrative.md>\|--data <historical-data.json>) --output <items.json>` | Deterministically extract the complete implementation-planning `P-*` queue. Contract v3 reads the report-writer narrative before publication; `--data` is the historical v2 reader. |
796
799
  | `okstra plan-items validate (--narrative <report-narrative.md>\|--data <historical-data.json>) --items <items.json>` | Require the persisted `P-*` queue to match a fresh deterministic extraction exactly. |
797
800
  | `okstra plan-items derivations --data <data.json> --response <user-response sidecar> [--clarification C-NNN]` | List the plan statements an answered clarification may have falsified. Extracts the symbols, paths, and ids the answer names (backticked spans plus `R-001` / `DEV-10174`-style ids) and reports every string in the plan body that mentions one, as a JSON pointer plus excerpt. Advisory: it says where a decision's subject is mentioned, never which mentions are now wrong — the supersession rule (`prompts/profiles/_common-contract.md`) requires the author to enumerate before editing, and this supplies the enumeration |
@@ -249,6 +249,8 @@ briefs saved (N):
249
249
  next: /okstra-run
250
250
  ```
251
251
 
252
+ Before the hand-off block, once per task-group (Step 7a): if `<PROJECT_ROOT>/.okstra/briefs/<task-group>/group-context.md` is absent, ask whether to create the skeleton (`okstra group-context init --project-root <PROJECT_ROOT> --task-group <task-group>`; recommended for a new group) or skip. Never fill it from the tickets. When created, add `group context skeleton: <abs>/<task-group>/group-context.md (fill before /okstra-run)` to the block — preparation refuses the group's tasks while a `<...>` placeholder line remains.
253
+
252
254
  ## Forbidden patterns
253
255
 
254
256
  - Summarizing or tidying Source Material before inserting it.
@@ -262,8 +262,10 @@ Important modules:
262
262
  | `consumers.py` | Append-only `consumers.jsonl` writer + reader — records which `implementation` runs consumed which `implementation-planning` stage |
263
263
  | `implementation_outcome.py` | Artifact-derived reconstruction of the implementation phase outcome — reads `runs/implementation/carry/stage-<N>.json` + `consumers.jsonl` + the approved Stage Map to derive `phaseOutcome.implementation`, and when every stage has pass-grade carry evidence it raises `workflow.nextRecommendedPhase.status` to `ready` (keeping the `contract-violated` audit information). It never picks the phase — `phase` is left as the last stage's report routing settled it, and the status is raised only while `phase` is non-empty |
264
264
  | `paths.py` | Path/sequence computation for task/run artifacts (including recap directory/log paths) |
265
- | `recap.py` | deterministic backend for the okstra-inspect `recap` facet — `assemble` builds the cross-run phase transitions from the timeline, `record` append-only writes a summary/Q&A to `<task-root>/recap/recap-log.jsonl` (other task artifacts unchanged) |
265
+ | `recap.py` | deterministic backend for the okstra-inspect `recap` facet — `assemble` builds the cross-run phase transitions from the timeline overlaid with each run-manifest's current facts (`timeline_runs.py`), `record` append-only writes a summary/Q&A to `<task-root>/recap/recap-log.jsonl` (other task artifacts unchanged) |
266
+ | `timeline_runs.py` | read-side overlay of a `history/timeline.json` entry with its run-manifest's current facts (`current_run_facts`) — the entry is a prepare-time snapshot (`status`, `workflowSnapshot`, reserved `reportRecordPath`) and `validate-run` writes the end state to the run-manifest only; a run whose `validation.status` is `not-run` projects no report path. Shared by `recap.py` and the `history-input` / overview projections in `model_io/renderers.py` |
266
267
  | `render.py` | task manifest, run manifest, timeline, task index, discovery, team-state, prompt/template render |
268
+ | `group_context.py` | task-group context document (`.okstra/briefs/<task-group>/group-context.md`): the skeleton writer behind `okstra group-context init` (template `templates/reports/group-context.template.md`), `validate_group_context` (four required sections, no template placeholder left, directory slug matches the frontmatter `task-group`) that `validators/validate-brief.py` dispatches to on frontmatter `type: group-context`, and the path helpers `run.py` uses to validate the file at preflight and copy it to `instruction-set/task-group-context.md` for the analysis packet's `## Task-Group Context` section |
267
269
  | `workflow.py` | Phase sequence (`PHASE_SEQUENCE`), per-phase allowed outputs, forbidden actions. It does not decide the next phase — that is `next_phase.py` |
268
270
  | `next_phase.py` | `workflow.nextRecommendedPhase` SSOT — the pointer's shape (`make` / `is_pointer` over `{phase, status, rationale}`, `status` ∈ `ready`/`pending`/`blocked`/`terminal`), the promotion of a legacy string pointer (`promote`), the projection of one report's routing field into a pointer (`project`), and the `ready`-only read the shell and wizard autofill share (`autofill_task_type`). There is no static phase table and no sequence walk: the next phase comes from what the report authored, and nothing else may compute one |
269
271
  | `workers.py`, `models.py` | Worker roster; `models.py` is the model catalog SSOT (`ModelSpec` per alias + `ROLE_DEFAULTS`) — add-a-model single reference point from which picker options, codex pricing, and role defaults all derive |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.189.0",
3
+ "version": "0.189.1",
4
4
  "description": "Host-aware multi-provider cross-verification orchestrator runtime and agent skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.189.0",
3
- "builtAt": "2026-09-04T09:04:34.381Z",
2
+ "package": "0.189.1",
3
+ "builtAt": "2026-09-04T19:05:25.979Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -43,6 +43,7 @@ profile document.
43
43
  - A legacy brief with no `reporter-confirmations` field is not reinterpreted as `pending`; it keeps the compatibility path and proceeds without this reporter-confirmation gate.
44
44
  `[CONFIRMED <YYYY-MM-DD> → RC-N]` markers on `Open Questions` rows are the per-row signal that the reporter has answered; their answers live verbatim under `## Reporter Confirmations` in the brief.
45
45
  - `Source Material` is reporter-verbatim. Do NOT paraphrase, summarize, reorder, or restructure it. Quote it directly when needed.
46
+ - `## Task-Group Context` (present in the analysis packet only when the task-group has `.okstra/briefs/<task-group>/group-context.md`, copied to `instruction-set/task-group-context.md`) is background shared by every task in the group — why the group exists, how the result is measured, group-wide constraints, ticket relations. It is not this task's requirement ledger: the brief decides this run's scope, the group context decides the measure and what no task may break. Reason from the group's measure (its stated denominator) rather than from a quantity only this ticket exposes, and where the brief and the group context conflict, raise a `Clarification Items` row instead of resolving the conflict silently in either direction.
46
47
  - `Related Task Graph` is the structured task-topology handoff. If the section is present and not `_(none)_`, read it before classification, diagnosis, candidate discovery, fan-out, or next-step routing. Preserve the edge direction exactly as written: `From` → `To` is load-bearing for `depends-on`, `blocks`, parent/child, follow-up, and split relations.
47
48
  - Valid relations are `parent-of`, `child-of`, `depends-on`, `blocks`, `blocked-by`, `follow-up-of`, `split-from`, `duplicates`, and `related-to`. `duplicates` / `related-to` are undirected; every other relation is directed.
48
49
  - Treat `Source` as the edge provenance. Do not invent graph edges from filename similarity, topic overlap, or worker preference. If a needed edge is missing or contradictory, raise a `Clarification Items` row instead of silently reordering tasks.
@@ -99,6 +99,7 @@ def build_analysis_packet(
99
99
  clarification_response_path: Path | None,
100
100
  directive: str,
101
101
  instruction_set_relative_path: str,
102
+ group_context_path: Path | None = None,
102
103
  fix_history_text: str = "",
103
104
  stage_ledger_json: str = "",
104
105
  stage_ledger_notice: str = "",
@@ -112,8 +113,13 @@ def build_analysis_packet(
112
113
  from disk state this file does not own. Each arrives already narrowed, and
113
114
  an empty string means the caller found nothing to carry — the matching
114
115
  block is then omitted rather than rendered saying "none".
116
+
117
+ `group_context_path` is the task-group context prepare copied into the
118
+ instruction set (`task-group-context.md`); `None` means the group has no
119
+ such document and the packet carries no `## Task-Group Context` section.
115
120
  """
116
121
  brief_text = task_brief_path.read_text(encoding="utf-8")
122
+ group_context_text = _read_optional(group_context_path) if group_context_path else ""
117
123
  profile_text = analysis_profile_path.read_text(encoding="utf-8")
118
124
  reference_text = _read_optional(reference_expectations_path)
119
125
  clarification_text = (
@@ -127,8 +133,12 @@ def build_analysis_packet(
127
133
  task_type,
128
134
  instruction_set_relative_path,
129
135
  bool(clarification_response_path),
136
+ bool(group_context_text),
130
137
  )
131
138
  )
139
+ # 그룹 맥락은 브리프 발췌보다 앞에 둔다: 짧고 "왜" 를 담으며, 46KB 에서 잘리는
140
+ # 읽기(agy view_file)에서도 도착해야 하는 절이다.
141
+ parts.extend(_group_context_block(group_context_text))
132
142
  parts.extend(_brief_block(brief_text))
133
143
  parts.extend(_profile_block(task_type, profile_text))
134
144
  parts.extend(_reference_block(reference_text))
@@ -243,6 +253,7 @@ def _intro_block(
243
253
  task_type: str,
244
254
  instruction_set: str,
245
255
  has_clarification: bool,
256
+ has_group_context: bool = False,
246
257
  ) -> list[str]:
247
258
  lines = [
248
259
  f"# OKSTRA Analysis Packet - {task_key}",
@@ -268,9 +279,36 @@ def _intro_block(
268
279
  lines.append(
269
280
  f"- Clarification response: `{instruction_set}/clarification-response.md`"
270
281
  )
282
+ if has_group_context:
283
+ lines.append(
284
+ f"- Task-group context: `{instruction_set}/task-group-context.md`"
285
+ )
271
286
  return lines
272
287
 
273
288
 
289
+ GROUP_CONTEXT_PREFACE = (
290
+ "Background shared by every task in this task-group, copied from the group's "
291
+ "`group-context.md`. It is not this task's requirement ledger: the "
292
+ "`## Task-Specific Brief Extract` below decides what this run must deliver, "
293
+ "while this section decides how the result is measured and what no task in the "
294
+ "group may break. Where the two conflict, raise a `Clarification Items` row; "
295
+ "never resolve the conflict silently in either direction."
296
+ )
297
+
298
+
299
+ def _group_context_block(group_context_text: str) -> list[str]:
300
+ if not group_context_text.strip():
301
+ return []
302
+ return [
303
+ "",
304
+ "## Task-Group Context",
305
+ "",
306
+ GROUP_CONTEXT_PREFACE,
307
+ "",
308
+ _strip_frontmatter(group_context_text).strip(),
309
+ ]
310
+
311
+
274
312
  def _brief_block(brief_text: str) -> list[str]:
275
313
  return [
276
314
  "",
@@ -0,0 +1,223 @@
1
+ """task-group 맥락 문서 — 그룹의 모든 task 가 공유하는 배경을 워커 입력에 싣는다.
2
+
3
+ `.okstra/briefs/<task-group>/group-context.md` 한 파일이 그룹이 존재하는 이유,
4
+ 성과 척도, 그룹 전체 금지선, 티켓 간 관계를 담는다. 브리프는 티켓 하나의 범위를
5
+ 말하므로 그룹 단위의 "왜" 는 어느 브리프에도 없다(2026-09-04 실측, fontsninja
6
+ `cache` 그룹: 브리프 15개 중 가용성 사고를 말한 것이 0개였고 option-selection 이
7
+ 분모를 페이지당 요청 수로 바꿔 판단했다).
8
+
9
+ 세 소비자가 이 모듈 하나를 쓴다.
10
+
11
+ - `okstra group-context init` — 템플릿에서 뼈대를 쓴다(있으면 거절).
12
+ - `validators/validate-brief.py` — 프론트매터 `type: group-context` 를 만나면
13
+ `validate_group_context` 로 검사한다.
14
+ - prepare(`run.py`) — 파일이 있으면 같은 검사를 통과해야 진행하고, 통과하면
15
+ `instruction-set/task-group-context.md` 로 복사해 analysis packet 에 싣는다.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ import datetime as dt
21
+ import re
22
+ import sys
23
+ from pathlib import Path
24
+
25
+ from .brief_frontmatter import read_brief_frontmatter
26
+ from .ids import slugify_task_segment
27
+ from .paths import find_asset_root
28
+
29
+ GROUP_CONTEXT_FILENAME = "group-context.md"
30
+ GROUP_CONTEXT_TYPE = "group-context"
31
+ GROUP_CONTEXT_GENERATOR = "okstra-brief-gen"
32
+ INSTRUCTION_SET_FILENAME = "task-group-context.md"
33
+ REQUIRED_FRONTMATTER_KEYS = ("type", "task-group", "created", "generator")
34
+ SECTIONS = (
35
+ "Why This Group Exists",
36
+ "Definition of Better",
37
+ "Group-Wide Constraints",
38
+ "Ticket Relations",
39
+ )
40
+ # 나머지 두 절은 `_(none)_` 이 허용된다 — 금지선이나 관계가 없는 그룹도 있다.
41
+ MUST_BE_FILLED = SECTIONS[:2]
42
+ TEMPLATE_RELATIVE = ("templates", "reports", "group-context.template.md")
43
+
44
+ _HTML_COMMENT_RE = re.compile(r"<!--.*?-->", re.DOTALL)
45
+ _NONE_MARKERS = {"_(none)_", ""}
46
+
47
+
48
+ def briefs_root(project_root: Path) -> Path:
49
+ return Path(project_root) / ".okstra" / "briefs"
50
+
51
+
52
+ def group_context_file(project_root: Path, task_group: str) -> Path:
53
+ """그룹 맥락 문서의 정본 경로. 디렉터리는 브리프와 같은 slug 를 쓴다."""
54
+ return briefs_root(project_root) / slugify_task_segment(task_group) / GROUP_CONTEXT_FILENAME
55
+
56
+
57
+ def is_group_context_file(path: Path) -> bool:
58
+ return path.name == GROUP_CONTEXT_FILENAME
59
+
60
+
61
+ def validate_group_context(path: Path, root: Path) -> list[str]:
62
+ """결함 목록. 비어 있으면 통과. 결함마다 사람이 고칠 자리를 이름한다."""
63
+ text = _HTML_COMMENT_RE.sub("", path.read_text(encoding="utf-8"))
64
+ errors: list[str] = []
65
+ frontmatter = read_brief_frontmatter(path)
66
+ if not frontmatter:
67
+ return ["frontmatter: missing or malformed (a `---` block must open line 1)"]
68
+ missing = [key for key in REQUIRED_FRONTMATTER_KEYS if key not in frontmatter]
69
+ if missing:
70
+ errors.append(f"frontmatter missing keys: {missing}")
71
+ if frontmatter.get("type") != GROUP_CONTEXT_TYPE:
72
+ errors.append(
73
+ f"frontmatter type must be {GROUP_CONTEXT_TYPE!r}, got {frontmatter.get('type')!r}"
74
+ )
75
+ if frontmatter.get("generator") != GROUP_CONTEXT_GENERATOR:
76
+ errors.append(
77
+ f"frontmatter generator must be {GROUP_CONTEXT_GENERATOR!r}, "
78
+ f"got {frontmatter.get('generator')!r}"
79
+ )
80
+ errors.extend(_path_errors(path, root, frontmatter.get("task-group", "")))
81
+ errors.extend(_section_errors(text))
82
+ return errors
83
+
84
+
85
+ def _path_errors(path: Path, root: Path, task_group: str) -> list[str]:
86
+ errors: list[str] = []
87
+ if path.name != GROUP_CONTEXT_FILENAME:
88
+ errors.append(f"file must be named {GROUP_CONTEXT_FILENAME!r}, got {path.name!r}")
89
+ try:
90
+ relative = path.resolve().relative_to(Path(root).resolve())
91
+ except ValueError:
92
+ return errors + [f"file is not under the briefs root {root}"]
93
+ if len(relative.parts) != 2:
94
+ errors.append(
95
+ "file must sit directly under its task-group directory "
96
+ f"(`<briefs>/<task-group>/{GROUP_CONTEXT_FILENAME}`), got {relative}"
97
+ )
98
+ return errors
99
+ expected = slugify_task_segment(task_group)
100
+ if task_group and relative.parts[0] != expected:
101
+ errors.append(
102
+ f"task-group directory segment {relative.parts[0]!r} does not match the "
103
+ f"slugified frontmatter task-group {expected!r}"
104
+ )
105
+ return errors
106
+
107
+
108
+ def _section_errors(text: str) -> list[str]:
109
+ bodies = _section_bodies(text)
110
+ errors: list[str] = []
111
+ for heading in SECTIONS:
112
+ if heading not in bodies:
113
+ errors.append(f"missing section `## {heading}`")
114
+ continue
115
+ lines = [line.strip() for line in bodies[heading].splitlines() if line.strip()]
116
+ placeholders = [line for line in lines if _is_template_placeholder(line)]
117
+ if placeholders:
118
+ errors.append(
119
+ f"section `## {heading}` still carries a template placeholder "
120
+ f"({placeholders[0][:40]}...); fill it or delete the file"
121
+ )
122
+ continue
123
+ if heading in MUST_BE_FILLED and all(line in _NONE_MARKERS for line in lines):
124
+ errors.append(f"section `## {heading}` must be filled; `_(none)_` is not accepted here")
125
+ return errors
126
+
127
+
128
+ def _section_bodies(text: str) -> dict[str, str]:
129
+ """`## ` 제목 → 본문. `## ` 만 절을 닫는다(validate-brief `section_body` 와 같은 규칙)."""
130
+ bodies: dict[str, str] = {}
131
+ current: str | None = None
132
+ buffer: list[str] = []
133
+ for line in text.splitlines():
134
+ if line.startswith("## "):
135
+ if current is not None:
136
+ bodies[current] = "\n".join(buffer)
137
+ current = line[3:].strip()
138
+ buffer = []
139
+ elif current is not None:
140
+ buffer.append(line)
141
+ if current is not None:
142
+ bodies[current] = "\n".join(buffer)
143
+ return bodies
144
+
145
+
146
+ def _is_template_placeholder(line: str) -> bool:
147
+ bare = line.lstrip("-").strip()
148
+ return bare.startswith("<") and bare.endswith(">")
149
+
150
+
151
+ def render_skeleton(task_group: str, created: str) -> str:
152
+ root = find_asset_root(TEMPLATE_RELATIVE)
153
+ if root is None:
154
+ raise FileNotFoundError(
155
+ "group-context template not found in any okstra asset root: "
156
+ + "/".join(TEMPLATE_RELATIVE)
157
+ )
158
+ template = root.joinpath(*TEMPLATE_RELATIVE).read_text(encoding="utf-8")
159
+ slug = slugify_task_segment(task_group)
160
+ return template.replace("<task-group>", slug).replace("<YYYY-MM-DD>", created)
161
+
162
+
163
+ def init_group_context(project_root: Path, task_group: str, *, today: dt.date) -> Path:
164
+ """뼈대를 쓴다. 이미 있으면 `FileExistsError` — 채운 문서를 덮어쓰지 않는다."""
165
+ target = group_context_file(project_root, task_group)
166
+ if target.exists():
167
+ raise FileExistsError(str(target))
168
+ target.parent.mkdir(parents=True, exist_ok=True)
169
+ target.write_text(render_skeleton(task_group, today.isoformat()), encoding="utf-8")
170
+ return target
171
+
172
+
173
+ def _init_command(args: argparse.Namespace) -> int:
174
+ project_root = Path(args.project_root).resolve()
175
+ try:
176
+ target = init_group_context(project_root, args.task_group, today=dt.date.today())
177
+ except FileExistsError as exc:
178
+ print(
179
+ f"group-context: already exists: {exc}\n"
180
+ "Edit that file instead; delete it first if you want a fresh skeleton.",
181
+ file=sys.stderr,
182
+ )
183
+ return 2
184
+ print(f"group context skeleton: {target}")
185
+ print("Fill these sections (one `<...>` placeholder line each):")
186
+ for heading in SECTIONS:
187
+ note = "required" if heading in MUST_BE_FILLED else "`_(none)_` allowed"
188
+ print(f" - ## {heading} ({note})")
189
+ print(
190
+ "Validate with: python3 ~/.okstra/lib/validators/validate-brief.py "
191
+ f"{target} --briefs-root {briefs_root(project_root)}"
192
+ )
193
+ print(
194
+ "Every run of task-group "
195
+ f"`{slugify_task_segment(args.task_group)}` refuses to prepare while a placeholder "
196
+ "line remains; delete the file if the group needs no context."
197
+ )
198
+ return 0
199
+
200
+
201
+ def build_parser() -> argparse.ArgumentParser:
202
+ parser = argparse.ArgumentParser(
203
+ prog="okstra group-context",
204
+ description=(
205
+ "Create the task-group context skeleton beside the group's briefs "
206
+ "(`.okstra/briefs/<task-group>/group-context.md`)."
207
+ ),
208
+ )
209
+ sub = parser.add_subparsers(dest="command", required=True)
210
+ init = sub.add_parser("init", help="write the skeleton from the template; refuses an existing file")
211
+ init.add_argument("--project-root", required=True, help="project root that holds `.okstra/`")
212
+ init.add_argument("--task-group", required=True, help="task-group name; slugified for the directory")
213
+ init.set_defaults(func=_init_command)
214
+ return parser
215
+
216
+
217
+ def main(argv: list[str] | None = None) -> int:
218
+ args = build_parser().parse_args(argv)
219
+ return args.func(args)
220
+
221
+
222
+ if __name__ == "__main__":
223
+ sys.exit(main())
@@ -20,6 +20,7 @@ from ..fixed_text import line as _line, scalar as _value
20
20
  from ..json_boundary import JsonBoundaryError, load_owned_object
21
21
  from ..paths import okstra_home
22
22
  from ..recap import assemble_recap
23
+ from ..timeline_runs import current_run_facts
23
24
  from ..worker_artifacts import worker_provider_id
24
25
  from .lines import (
25
26
  _assignment_line,
@@ -51,7 +52,7 @@ from .references import (
51
52
  )
52
53
 
53
54
 
54
- def _latest_timeline_run(manifest_path: Path) -> Mapping[str, Any]:
55
+ def _latest_timeline_run(project_root: Path, manifest_path: Path) -> Mapping[str, Any]:
55
56
  timeline_path = manifest_path.parent / "history" / "timeline.json"
56
57
  if not timeline_path.is_file():
57
58
  return {}
@@ -59,10 +60,11 @@ def _latest_timeline_run(manifest_path: Path) -> Mapping[str, Any]:
59
60
  runs = timeline.get("runs")
60
61
  if not isinstance(runs, list):
61
62
  return {}
62
- return next(
63
+ latest = next(
63
64
  (run for run in reversed(runs) if isinstance(run, Mapping)),
64
- {},
65
+ None,
65
66
  )
67
+ return current_run_facts(project_root, latest) if latest is not None else {}
66
68
 
67
69
 
68
70
  def _overview_rows(
@@ -79,15 +81,18 @@ def _overview_rows(
79
81
  project_root, manifest_path, expected_task_key=task_key, artifact="task catalog"
80
82
  )
81
83
  manifest = load_owned_object(manifest_path, artifact="task manifest")
82
- latest_run = _latest_timeline_run(manifest_path)
84
+ latest_run = _latest_timeline_run(project_root, manifest_path)
83
85
  _, group, _ = parse_task_key(task_key)
84
86
  workflow = _mapping(manifest, "workflow")
85
87
  next_phase = _mapping(workflow, "nextRecommendedPhase")
88
+ # task 단위 현재 사실은 task-manifest 가 권위다(validate-run 이 run 종료
89
+ # 시 거기에 쓴다). timeline 의 마지막 run 은 task-manifest 에 그 필드가
90
+ # 없을 때의 폴백이고, 그 값도 run-manifest 로 덮어쓴 현재 사실이다.
86
91
  row = {
87
92
  "taskKey": task_key,
88
93
  "taskGroup": manifest.get("taskGroup") or task.get("taskGroup") or group,
89
94
  "taskType": manifest.get("taskType") or latest_run.get("taskType"),
90
- "latestRunStatus": latest_run.get("status") or manifest.get("latestRunStatus"),
95
+ "latestRunStatus": manifest.get("latestRunStatus") or latest_run.get("status"),
91
96
  "updatedAt": manifest.get("updatedAt") or task.get("updatedAt") or latest_run.get("runTimestamp"),
92
97
  "latestRunManifestPath": pointer.get("latestRunManifestPath"),
93
98
  "workCategory": manifest.get("workCategory"),
@@ -98,7 +103,7 @@ def _overview_rows(
98
103
  "nextPhaseStatus": next_phase.get("status"),
99
104
  "nextPhaseRationale": next_phase.get("rationale"),
100
105
  "awaitingApproval": workflow.get("awaitingApproval"),
101
- "latestReportRecordPath": latest_run.get("reportRecordPath") or manifest.get("latestReportRecordPath"),
106
+ "latestReportRecordPath": manifest.get("latestReportRecordPath") or latest_run.get("reportRecordPath"),
102
107
  "latestResumeCommandPath": latest_run.get("resumeCommandPath") or manifest.get("latestResumeCommandPath"),
103
108
  "workStatus": manifest.get("workStatus"),
104
109
  "lastRun": latest_run.get("runTimestamp"),
@@ -336,7 +341,7 @@ def render_history_input(
336
341
  )
337
342
  manifest, runs = _selected_task_data(project_root, task_ref)
338
343
  blocks: list[str] = []
339
- for index, run in enumerate(runs, 1):
344
+ for index, run in enumerate((current_run_facts(project_root, run) for run in runs), 1):
340
345
  blocks.append(
341
346
  f"\n## Run {index}\n\n"
342
347
  + _line("Run timestamp", run.get("runTimestamp"))
@@ -22,6 +22,7 @@ from okstra_project import read_task_key
22
22
  from okstra_ctl.run_context import dir_flock
23
23
  from okstra_ctl.final_report_paths import timeline_report_record_rel
24
24
  from okstra_ctl.task_target import resolve_task_root, project_rel
25
+ from okstra_ctl.timeline_runs import current_run_facts
25
26
 
26
27
  NOTE_KINDS = ("verification-evidence", "decision-draft", "analysis-note")
27
28
 
@@ -97,7 +98,12 @@ def rerun_readiness(project_root: Path, runs: list[dict]) -> dict | None:
97
98
 
98
99
 
99
100
  def assemble_recap(task_root: Path, project_root: Path) -> dict:
100
- runs = _load_timeline(task_root)
101
+ # timeline 항목의 status / workflowSnapshot / reportRecordPath 는 준비 시점
102
+ # 값이다. 각 run 의 종료 상태는 그 run 의 run-manifest 에서 덮어쓴다.
103
+ runs = [
104
+ current_run_facts(project_root, run) if isinstance(run, dict) else run
105
+ for run in _load_timeline(task_root)
106
+ ]
101
107
  transitions = []
102
108
  prev_phase = ""
103
109
  latest_states: dict = {}
@@ -38,6 +38,7 @@ from okstra_project import project_json_path, upsert_project_json
38
38
  from okstra_project.slug import slugify
39
39
  from . import fix_cycles
40
40
  from .analysis_packet import build_analysis_packet
41
+ from . import group_context
41
42
  from .stage_ledger import (
42
43
  build_stage_ledger,
43
44
  render_stage_ledger,
@@ -1363,6 +1364,23 @@ def _validate_task_brief_preflight(
1363
1364
  )
1364
1365
 
1365
1366
 
1367
+ def _validate_group_context_preflight(project_root: Path, task_group: str) -> None:
1368
+ """그룹 맥락 문서가 있으면 검증한다. 없으면 선택적 입력이라 아무 일도 없다.
1369
+
1370
+ 채우지 않은 뼈대가 워커에 닿으면 자리표시자를 배경으로 읽으므로, 있는데 결함이면
1371
+ prepare 를 멈추고 채우거나 지우라고 말한다."""
1372
+ path = group_context.group_context_file(project_root, task_group)
1373
+ if not path.is_file():
1374
+ return
1375
+ errors = group_context.validate_group_context(path, group_context.briefs_root(project_root))
1376
+ if errors:
1377
+ raise PrepareError(
1378
+ f"task-group context failed validation ({path}): "
1379
+ + "; ".join(errors)
1380
+ + " — fill the file, or delete it if the group needs no context"
1381
+ )
1382
+
1383
+
1366
1384
  def _validate_prepare_inputs(project_root: Path, inp: PrepareInputs) -> list:
1367
1385
  """Validate pure prepare inputs and return a final-verification stage map."""
1368
1386
  if not project_root.is_dir():
@@ -3599,6 +3617,14 @@ def _write_instruction_set_sources(
3599
3617
  )
3600
3618
  (instruction_set / "analysis-material.md").write_text(review_material, encoding="utf-8")
3601
3619
  shutil.copyfile(inp.brief_path, instruction_set / "task-brief.md")
3620
+ # 그룹 맥락은 preflight 를 통과한 파일만 여기 온다(`_validate_group_context_preflight`).
3621
+ group_context_source = group_context.group_context_file(
3622
+ Path(inp.project_root), inp.task_group
3623
+ )
3624
+ group_context_path: Path | None = None
3625
+ if group_context_source.is_file():
3626
+ group_context_path = instruction_set / group_context.INSTRUCTION_SET_FILENAME
3627
+ shutil.copyfile(group_context_source, group_context_path)
3602
3628
  # A rule that lives only in the conversation is one compaction away from
3603
3629
  # gone, with no signal that it went. On disk it survives, and the session
3604
3630
  # conformance check can ask afterwards whether it was read. The token is
@@ -3664,6 +3690,7 @@ def _write_instruction_set_sources(
3664
3690
  task_key=ctx["TASK_KEY"],
3665
3691
  task_type=ctx["TASK_TYPE"],
3666
3692
  task_brief_path=instruction_set / "task-brief.md",
3693
+ group_context_path=group_context_path,
3667
3694
  analysis_profile_path=instruction_set / "analysis-profile.md",
3668
3695
  reference_expectations_path=instruction_set / "reference-expectations.md",
3669
3696
  clarification_response_path=(
@@ -4547,6 +4574,7 @@ def prepare_task_bundle(inp: PrepareInputs) -> PrepareOutputs:
4547
4574
  inp.brief_path,
4548
4575
  assets.brief_validator,
4549
4576
  )
4577
+ _validate_group_context_preflight(project_root, inp.task_group)
4550
4578
  selected_direction = _resolve_planning_direction(inp)
4551
4579
  if inp.task_type == "implementation":
4552
4580
  ctx_stage_map = _prepare_implementation_approved_plan(inp)
@@ -0,0 +1,71 @@
1
+ """timeline.json 의 run 항목을 그 run 의 현재 사실로 읽는 read-side 투영.
2
+
3
+ timeline 항목은 prepare 가 한 번 쓴다 — `render.render_timeline` 의 호출자는
4
+ `run._finalize_status_and_render_manifests` 뿐이다. run 이 끝날 때 상태를 쓰는
5
+ 곳은 `validators/validate-run.py` 이고, 그 코드는 run-manifest(`status`,
6
+ `validation`, `workflowSnapshot`)와 task-manifest 만 고친다. 그래서 timeline
7
+ 항목의 `status` 는 언제나 준비 시점 값(`prepared` / `in-progress`)이고
8
+ `workflowSnapshot` 은 준비 시점 스냅샷이다(2026-09-04 실측, dev-10626: 항목
9
+ 6개 전부 `prepared`, 같은 run 의 run-manifest 4개는 `completed`). 같은 run 의
10
+ 현재 사실은 그 run 의 run-manifest 가 가지므로, 읽는 쪽은 그것을 권위로 삼는다.
11
+
12
+ `reportRecordPath` 도 예약이다. 항목이 적는 값은 이번 run 의 기대 리포트 경로인데
13
+ 리포트 seq 는 파일 존재로 배정되므로, 준비만 되고 돌지 않은 run 의 seq 를 다음
14
+ run 이 이어받는다(같은 실측: error-analysis run 001·002 가 같은
15
+ `final-report-error-analysis-001.data.json` 을 적었고 파일은 002 가 썼다).
16
+ validate-run 이 그 run 의 리포트를 검증했을 때(`validation.status` 가 `not-run`
17
+ 이 아닐 때)만 그 경로가 그 run 의 리포트다.
18
+
19
+ task 단위 현재 사실(`currentStatus`, `latestRunStatus`, `workflow.*`,
20
+ `latestReportRecordPath`)은 task-manifest 가 권위다. 이 모듈은 run 단위만 다룬다.
21
+ """
22
+ from __future__ import annotations
23
+
24
+ from pathlib import Path
25
+ from typing import Any, Mapping
26
+
27
+ from .json_boundary import JsonBoundaryError, load_owned_object
28
+ from .paths import resolve_under_root
29
+
30
+ VALIDATION_NOT_RUN = "not-run"
31
+
32
+
33
+ def current_run_facts(project_root: Path, run: Mapping[str, Any]) -> dict[str, Any]:
34
+ """timeline 항목에 그 run 의 run-manifest 가 기록한 현재 사실을 덮어쓴 사본.
35
+
36
+ - `status`, `workflowSnapshot`: run-manifest 값. 키가 없으면 항목 값 그대로.
37
+ - `reportRecordPath` / `reportPath`: run-manifest 의 `validation.status` 가
38
+ `not-run` 이면 비운다 — 그 run 은 리포트를 낸 적이 없고 경로는 예약이다.
39
+ `validation` 블록이 없는 매니페스트는 판정 근거가 없으므로 그대로 둔다.
40
+
41
+ run-manifest 가 없으면(`runManifestPath` 가 비었거나 파일이 없으면) 항목을
42
+ 그대로 돌려준다. 있는데 읽을 수 없으면 `JsonBoundaryError` 가 그대로 올라간다
43
+ — 투영이 잘못된 파일을 조용히 건너뛰면 그 run 만 준비 시점 값으로 남는다.
44
+ """
45
+ entry = dict(run)
46
+ manifest = _run_manifest(project_root, run)
47
+ if manifest is None:
48
+ return entry
49
+ status = manifest.get("status")
50
+ if isinstance(status, str) and status:
51
+ entry["status"] = status
52
+ snapshot = manifest.get("workflowSnapshot")
53
+ if isinstance(snapshot, Mapping):
54
+ entry["workflowSnapshot"] = dict(snapshot)
55
+ validation = manifest.get("validation")
56
+ if isinstance(validation, Mapping) and validation.get("status") == VALIDATION_NOT_RUN:
57
+ entry["reportRecordPath"] = ""
58
+ entry["reportPath"] = ""
59
+ return entry
60
+
61
+
62
+ def _run_manifest(project_root: Path, run: Mapping[str, Any]) -> Mapping[str, Any] | None:
63
+ relative = run.get("runManifestPath")
64
+ if not isinstance(relative, str) or not relative:
65
+ return None
66
+ path = resolve_under_root(project_root, relative)
67
+ if path is None:
68
+ raise JsonBoundaryError(Path(relative), "run manifest", "outside this project")
69
+ if not path.is_file():
70
+ return None
71
+ return load_owned_object(path, artifact="run manifest")
@@ -70,6 +70,7 @@ from okstra_ctl.role_requirements import (
70
70
  )
71
71
  from okstra_ctl.ids import slugify_task_segment
72
72
  from okstra_ctl.brief_frontmatter import read_brief_frontmatter
73
+ from okstra_ctl.group_context import is_group_context_file
73
74
  from okstra_ctl.analysis_inputs import (
74
75
  ANALYSIS_TASK_TYPES,
75
76
  AnalysisInputError,
@@ -2525,7 +2526,7 @@ def _suggest_group_briefs(state: WizardState, limit: int = 6) -> list[str]:
2525
2526
  used_at_by_relpath = _recently_used_brief_times(state)
2526
2527
  candidates: list[tuple[float, str]] = []
2527
2528
  for path in root.rglob("*.md"):
2528
- if not path.is_file():
2529
+ if not path.is_file() or is_group_context_file(path):
2529
2530
  continue
2530
2531
  tg_suggestion, _ = _brief_suggestions(path)
2531
2532
  if tg_suggestion:
@@ -993,10 +993,38 @@ briefs saved (N):
993
993
  next: /okstra-run (run a separate task-key per brief — use the filename stem as task-id)
994
994
  ```
995
995
 
996
+ ### 7a. Task-group context (once per task-group)
997
+
998
+ Before printing the hand-off block, check whether
999
+ `<PROJECT_ROOT>/.okstra/briefs/<task-group>/group-context.md` exists. That
1000
+ file is the one document every task in the group shares — why the group
1001
+ exists, how its result is measured (with the denominator named), group-wide
1002
+ constraints, ticket relations — and no single brief can recover it
1003
+ (observed: a 15-brief group whose reason, "the origin keeps going down under
1004
+ attack traffic", appeared in none of them, so option selection measured a
1005
+ per-page ratio instead of origin load). If the file is absent, ask once via
1006
+ `AskUserQuestion`:
1007
+
1008
+ - `Create the group context skeleton now (Recommended for a new task-group)`
1009
+ → run `okstra group-context init --project-root <PROJECT_ROOT> --task-group <task-group>`
1010
+ and echo its output verbatim. The skeleton carries one `<...>` placeholder
1011
+ line per section; the user fills it. `/okstra-run` refuses to prepare any
1012
+ task in the group while a placeholder line remains.
1013
+ - `Skip — this group needs no shared context`.
1014
+
1015
+ Never fill the skeleton yourself from the tickets: a ticket summary decides
1016
+ nothing, and the sections ask for what the tickets do not say. If the file
1017
+ exists, leave it untouched and mention its path in the hand-off block.
1018
+
996
1019
  Then stop. Do not invoke `okstra-run` directly — the user chooses when to
997
1020
  proceed, and they may want to edit the brief externally first. In the
998
1021
  multi-brief case the user also decides the order in which tasks are
999
- started.
1022
+ started. When a skeleton was created in 7a, add one line to the hand-off
1023
+ block:
1024
+
1025
+ ```
1026
+ group context skeleton: <abs>/<task-group>/group-context.md (fill before /okstra-run)
1027
+ ```
1000
1028
 
1001
1029
  ## Output Rules
1002
1030
 
@@ -36,6 +36,7 @@ When a user selects a specific task:
36
36
 
37
37
  1. Run `okstra model-io history-input --project-root <projectRoot> --task-ref <task-key>`.
38
38
  2. Use each numbered run block for chronological status, report, run-manifest, and resume paths.
39
+ `Status` is the run's current status from its own run-manifest (the timeline entry itself only records the prepare-time value). `Report` is `-` for a run that never validated a report — a prepared run that was superseded before it ran — so two runs never share one report in this list.
39
40
 
40
41
  ```markdown
41
42
  ## Runs for <task-key>
@@ -22,7 +22,7 @@ Use the CLI output as the source of truth:
22
22
  okstra model-io recap-input --project-root <projectRoot> --task-ref <resolved-target>
23
23
  ```
24
24
 
25
- Read the fixed-text `Run count` and repeated `Transition` blocks. Narrate each block's `From phase → To phase`, `Status`, `Last completed phase`, `Next phase`, and `Report` in the emitted chronological order. If `Run count: 0`, answer only "This task has no recorded runs." and do not claim to have read any file.
25
+ Read the fixed-text `Run count` and repeated `Transition` blocks. Narrate each block's `From phase → To phase`, `Status`, `Last completed phase`, `Next phase`, and `Report` in the emitted chronological order. `Status`, `Last completed phase`, and `Next phase` are each run's end state from its own run-manifest, so a `prepared` transition is a run that was prepared and never ran, and it carries no `Report`. If `Run count: 0`, answer only "This task has no recorded runs." and do not claim to have read any file.
26
26
 
27
27
  `Next phase` is already a fixed scalar projection. Narrate it when non-empty, and otherwise use `Next phase status`: `pending` means that run did not settle the route, `blocked` means it stopped on something outside the run, and `terminal` means the lifecycle ended there.
28
28
 
@@ -0,0 +1,31 @@
1
+ ---
2
+ type: group-context
3
+ task-group: <task-group>
4
+ created: <YYYY-MM-DD>
5
+ generator: okstra-brief-gen
6
+ ---
7
+
8
+ # Task-Group Context: <task-group>
9
+
10
+ > Shared by every task in this task-group. okstra copies it into each run's
11
+ > `instruction-set/task-group-context.md` and carries it in the analysis
12
+ > packet's `## Task-Group Context` section, ahead of the brief extract.
13
+ > Write only what no single ticket can recover — a summary of the tickets
14
+ > decides nothing. Preparation refuses this file while any `<...>`
15
+ > placeholder line remains; delete the file instead if the group needs none.
16
+
17
+ ## Why This Group Exists
18
+
19
+ <The situation that created this group: what keeps happening, to whom, and why it takes a group of tickets rather than one. Not a summary of the tickets.>
20
+
21
+ ## Definition of Better
22
+
23
+ <The measure the whole group is judged by, as a quantity and its direction. Name the denominator explicitly: a per-page ratio and a fleet-wide count are different measures, and a run that has only one of them will reason from it.>
24
+
25
+ ## Group-Wide Constraints
26
+
27
+ <Rules every task in the group must respect, one bullet each, so no brief has to repeat them. Write `_(none)_` when there are none.>
28
+
29
+ ## Ticket Relations
30
+
31
+ <Which tickets are causes, which are observation means, which depend on which. Write `_(none)_` when the briefs' Related Task Graph already says it all.>
@@ -42,6 +42,11 @@ Checks performed per brief file:
42
42
  3-digit id and an `— verify: <how>` observation method, EB/EO are rejected
43
43
  in the codebase-scan variant, and `## External Gates` — the destination for
44
44
  an item with no observation method — is required in every variant.
45
+ 15. A file whose frontmatter `type` is `group-context` is the task-group's
46
+ context document (`<briefs>/<task-group>/group-context.md`), not a brief:
47
+ it is checked by `okstra_ctl.group_context.validate_group_context` (four
48
+ required sections, no template placeholder left, directory slug matches
49
+ the frontmatter `task-group`). Any other `type` is a failure.
45
50
 
46
51
  Exit code 0 on PASS, 1 on FAIL.
47
52
  """
@@ -66,6 +71,7 @@ from okstra_ctl.improvement_lenses import (
66
71
  MAX_PRIORITY_LENSES,
67
72
  MIN_PRIORITY_LENSES,
68
73
  )
74
+ from okstra_ctl.group_context import GROUP_CONTEXT_TYPE, validate_group_context
69
75
  from okstra_ctl.ids import slugify_task_segment
70
76
 
71
77
  REQUIRED_FRONTMATTER_KEYS = {
@@ -677,6 +683,9 @@ def validate_brief(path: Path, briefs_root: Path) -> list[str]:
677
683
  except ValueError as exc:
678
684
  return [f"frontmatter: {exc}"]
679
685
 
686
+ if fm.get("type") == GROUP_CONTEXT_TYPE:
687
+ return validate_group_context(path, briefs_root)
688
+
680
689
  missing = REQUIRED_FRONTMATTER_KEYS - fm.keys()
681
690
  if missing:
682
691
  errors.append(f"frontmatter missing keys: {sorted(missing)}")