okstra 0.130.3 → 0.131.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. package/README.md +0 -1
  2. package/docs/architecture.md +2 -2
  3. package/docs/cli.md +1 -1
  4. package/docs/for-ai/README.md +0 -2
  5. package/docs/for-ai/skills/okstra-run.md +13 -2
  6. package/docs/for-ai/skills/okstra-setup.md +4 -1
  7. package/docs/project-structure-overview.md +5 -4
  8. package/docs/task-process/implementation-planning.md +13 -0
  9. package/docs/task-process/implementation.md +17 -2
  10. package/package.json +1 -1
  11. package/runtime/BUILD.json +2 -2
  12. package/runtime/agents/workers/report-writer-worker.md +7 -0
  13. package/runtime/bin/lib/okstra/usage.sh +4 -4
  14. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  15. package/runtime/prompts/lead/plan-body-verification.md +26 -5
  16. package/runtime/prompts/lead/report-writer.md +6 -2
  17. package/runtime/prompts/profiles/_common-contract.md +2 -1
  18. package/runtime/prompts/profiles/_implementation-deliverable.md +6 -1
  19. package/runtime/prompts/profiles/_implementation-executor.md +2 -2
  20. package/runtime/prompts/profiles/_implementation-verifier.md +33 -10
  21. package/runtime/prompts/profiles/final-verification.md +21 -6
  22. package/runtime/prompts/profiles/implementation-planning.md +21 -4
  23. package/runtime/python/okstra_ctl/codex_dispatch.py +31 -0
  24. package/runtime/python/okstra_ctl/conformance.py +49 -11
  25. package/runtime/python/okstra_ctl/report_finalize.py +52 -1
  26. package/runtime/python/okstra_ctl/report_views.py +32 -5
  27. package/runtime/python/okstra_ctl/run.py +15 -3
  28. package/runtime/python/okstra_ctl/worker_prompt_contract.py +14 -6
  29. package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -1
  30. package/runtime/python/okstra_vendor/__init__.py +0 -44
  31. package/runtime/schemas/final-report-v1.0.schema.json +101 -6
  32. package/runtime/skills/okstra-run/SKILL.md +11 -4
  33. package/runtime/skills/okstra-setup/SKILL.md +3 -2
  34. package/runtime/skills/okstra-setup/references/project-config.md +16 -7
  35. package/runtime/templates/reports/final-report.template.md +18 -12
  36. package/runtime/templates/reports/i18n/en.json +1 -0
  37. package/runtime/templates/reports/i18n/ko.json +1 -0
  38. package/runtime/templates/reports/report.css +18 -0
  39. package/runtime/validators/lib/fixtures.sh +6 -0
  40. package/runtime/validators/validate-run.py +1722 -98
  41. package/src/cli-registry.mjs +0 -7
  42. package/src/commands/lifecycle/doctor.mjs +0 -9
  43. package/src/lib/skill-catalog.mjs +0 -1
  44. package/docs/for-ai/skills/okstra-graphify.md +0 -64
  45. package/runtime/python/okstra_ctl/graphify_cmd.py +0 -225
  46. package/runtime/python/okstra_vendor/graphify/.vendored-version +0 -1
  47. package/runtime/python/okstra_vendor/graphify/__init__.py +0 -28
  48. package/runtime/python/okstra_vendor/graphify/__main__.py +0 -1371
  49. package/runtime/python/okstra_vendor/graphify/analyze.py +0 -540
  50. package/runtime/python/okstra_vendor/graphify/benchmark.py +0 -129
  51. package/runtime/python/okstra_vendor/graphify/build.py +0 -107
  52. package/runtime/python/okstra_vendor/graphify/cache.py +0 -169
  53. package/runtime/python/okstra_vendor/graphify/cluster.py +0 -137
  54. package/runtime/python/okstra_vendor/graphify/detect.py +0 -510
  55. package/runtime/python/okstra_vendor/graphify/export.py +0 -1014
  56. package/runtime/python/okstra_vendor/graphify/extract.py +0 -3277
  57. package/runtime/python/okstra_vendor/graphify/hooks.py +0 -220
  58. package/runtime/python/okstra_vendor/graphify/ingest.py +0 -297
  59. package/runtime/python/okstra_vendor/graphify/manifest.py +0 -4
  60. package/runtime/python/okstra_vendor/graphify/report.py +0 -175
  61. package/runtime/python/okstra_vendor/graphify/security.py +0 -203
  62. package/runtime/python/okstra_vendor/graphify/serve.py +0 -373
  63. package/runtime/python/okstra_vendor/graphify/skill-aider.md +0 -1184
  64. package/runtime/python/okstra_vendor/graphify/skill-claw.md +0 -1184
  65. package/runtime/python/okstra_vendor/graphify/skill-codex.md +0 -1242
  66. package/runtime/python/okstra_vendor/graphify/skill-copilot.md +0 -1268
  67. package/runtime/python/okstra_vendor/graphify/skill-droid.md +0 -1239
  68. package/runtime/python/okstra_vendor/graphify/skill-kiro.md +0 -1183
  69. package/runtime/python/okstra_vendor/graphify/skill-opencode.md +0 -1238
  70. package/runtime/python/okstra_vendor/graphify/skill-trae.md +0 -1208
  71. package/runtime/python/okstra_vendor/graphify/skill-vscode.md +0 -253
  72. package/runtime/python/okstra_vendor/graphify/skill-windows.md +0 -1245
  73. package/runtime/python/okstra_vendor/graphify/skill.md +0 -1319
  74. package/runtime/python/okstra_vendor/graphify/transcribe.py +0 -182
  75. package/runtime/python/okstra_vendor/graphify/validate.py +0 -72
  76. package/runtime/python/okstra_vendor/graphify/watch.py +0 -188
  77. package/runtime/python/okstra_vendor/graphify/wiki.py +0 -214
  78. package/runtime/python/okstra_vendor/networkx/__init__.py +0 -62
  79. package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +0 -134
  80. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +0 -26
  81. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +0 -259
  82. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +0 -71
  83. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +0 -412
  84. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +0 -396
  85. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +0 -150
  86. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +0 -149
  87. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +0 -369
  88. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +0 -44
  89. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +0 -143
  90. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +0 -53
  91. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +0 -265
  92. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +0 -1508
  93. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +0 -255
  94. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +0 -83
  95. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +0 -5
  96. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +0 -122
  97. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +0 -302
  98. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +0 -255
  99. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +0 -160
  100. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +0 -127
  101. package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +0 -164
  102. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +0 -88
  103. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +0 -322
  104. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +0 -290
  105. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +0 -289
  106. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +0 -57
  107. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +0 -360
  108. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +0 -105
  109. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +0 -603
  110. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +0 -316
  111. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +0 -590
  112. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +0 -232
  113. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +0 -526
  114. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +0 -112
  115. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +0 -69
  116. package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +0 -168
  117. package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +0 -205
  118. package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +0 -164
  119. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +0 -20
  120. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +0 -591
  121. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +0 -236
  122. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +0 -282
  123. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +0 -364
  124. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +0 -227
  125. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +0 -96
  126. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +0 -150
  127. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +0 -107
  128. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +0 -357
  129. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +0 -130
  130. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +0 -787
  131. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +0 -88
  132. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +0 -331
  133. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +0 -150
  134. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +0 -200
  135. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +0 -128
  136. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +0 -209
  137. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +0 -141
  138. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +0 -361
  139. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +0 -181
  140. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +0 -95
  141. package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +0 -172
  142. package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +0 -443
  143. package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +0 -818
  144. package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +0 -732
  145. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +0 -4
  146. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +0 -505
  147. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +0 -565
  148. package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +0 -163
  149. package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +0 -28
  150. package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +0 -153
  151. package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +0 -354
  152. package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +0 -171
  153. package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +0 -30
  154. package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +0 -216
  155. package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +0 -79
  156. package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +0 -338
  157. package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +0 -162
  158. package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +0 -220
  159. package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +0 -384
  160. package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +0 -227
  161. package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +0 -452
  162. package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +0 -347
  163. package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +0 -6
  164. package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +0 -115
  165. package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +0 -394
  166. package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +0 -282
  167. package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +0 -71
  168. package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +0 -359
  169. package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +0 -196
  170. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +0 -11
  171. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +0 -811
  172. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +0 -616
  173. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +0 -408
  174. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +0 -1270
  175. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +0 -592
  176. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +0 -220
  177. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +0 -235
  178. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +0 -152
  179. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +0 -88
  180. package/runtime/python/okstra_vendor/networkx/algorithms/core.py +0 -588
  181. package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +0 -142
  182. package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +0 -416
  183. package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +0 -1234
  184. package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +0 -677
  185. package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +0 -1392
  186. package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +0 -1095
  187. package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +0 -272
  188. package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +0 -142
  189. package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +0 -268
  190. package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +0 -167
  191. package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +0 -470
  192. package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +0 -11
  193. package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +0 -370
  194. package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +0 -407
  195. package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +0 -238
  196. package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +0 -241
  197. package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +0 -178
  198. package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +0 -611
  199. package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +0 -356
  200. package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +0 -662
  201. package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +0 -425
  202. package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +0 -300
  203. package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +0 -194
  204. package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +0 -435
  205. package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +0 -483
  206. package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +0 -57
  207. package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +0 -196
  208. package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +0 -107
  209. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +0 -7
  210. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +0 -1306
  211. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +0 -336
  212. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +0 -1262
  213. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +0 -352
  214. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +0 -308
  215. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +0 -264
  216. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +0 -1102
  217. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +0 -192
  218. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +0 -2
  219. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +0 -337
  220. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +0 -498
  221. package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +0 -687
  222. package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +0 -280
  223. package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +0 -1148
  224. package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +0 -27
  225. package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +0 -738
  226. package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +0 -78
  227. package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +0 -59
  228. package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +0 -219
  229. package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +0 -155
  230. package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +0 -4
  231. package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +0 -324
  232. package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +0 -468
  233. package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +0 -633
  234. package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +0 -77
  235. package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +0 -73
  236. package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +0 -464
  237. package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +0 -1463
  238. package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +0 -306
  239. package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +0 -98
  240. package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +0 -167
  241. package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +0 -138
  242. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +0 -5
  243. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +0 -239
  244. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +0 -264
  245. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +0 -716
  246. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +0 -625
  247. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +0 -2542
  248. package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +0 -2107
  249. package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +0 -966
  250. package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +0 -404
  251. package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +0 -30
  252. package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +0 -296
  253. package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +0 -374
  254. package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +0 -564
  255. package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +0 -406
  256. package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +0 -981
  257. package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +0 -142
  258. package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +0 -406
  259. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +0 -5
  260. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +0 -90
  261. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +0 -576
  262. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +0 -529
  263. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +0 -185
  264. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +0 -182
  265. package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +0 -7
  266. package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +0 -1042
  267. package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +0 -413
  268. package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +0 -88
  269. package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +0 -219
  270. package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +0 -1281
  271. package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +0 -106
  272. package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +0 -273
  273. package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +0 -500
  274. package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +0 -76
  275. package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +0 -86
  276. package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +0 -77
  277. package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +0 -278
  278. package/runtime/python/okstra_vendor/networkx/classes/__init__.py +0 -13
  279. package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +0 -435
  280. package/runtime/python/okstra_vendor/networkx/classes/digraph.py +0 -1363
  281. package/runtime/python/okstra_vendor/networkx/classes/filters.py +0 -95
  282. package/runtime/python/okstra_vendor/networkx/classes/function.py +0 -1549
  283. package/runtime/python/okstra_vendor/networkx/classes/graph.py +0 -2082
  284. package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +0 -269
  285. package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +0 -977
  286. package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +0 -1294
  287. package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +0 -1447
  288. package/runtime/python/okstra_vendor/networkx/convert.py +0 -502
  289. package/runtime/python/okstra_vendor/networkx/convert_matrix.py +0 -1314
  290. package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +0 -7
  291. package/runtime/python/okstra_vendor/networkx/drawing/layout.py +0 -2036
  292. package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +0 -470
  293. package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +0 -570
  294. package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +0 -361
  295. package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +0 -2978
  296. package/runtime/python/okstra_vendor/networkx/exception.py +0 -131
  297. package/runtime/python/okstra_vendor/networkx/generators/__init__.py +0 -34
  298. package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
  299. package/runtime/python/okstra_vendor/networkx/generators/atlas.py +0 -227
  300. package/runtime/python/okstra_vendor/networkx/generators/classic.py +0 -1091
  301. package/runtime/python/okstra_vendor/networkx/generators/cographs.py +0 -68
  302. package/runtime/python/okstra_vendor/networkx/generators/community.py +0 -1070
  303. package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +0 -886
  304. package/runtime/python/okstra_vendor/networkx/generators/directed.py +0 -572
  305. package/runtime/python/okstra_vendor/networkx/generators/duplication.py +0 -174
  306. package/runtime/python/okstra_vendor/networkx/generators/ego.py +0 -66
  307. package/runtime/python/okstra_vendor/networkx/generators/expanders.py +0 -499
  308. package/runtime/python/okstra_vendor/networkx/generators/geometric.py +0 -1037
  309. package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +0 -163
  310. package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +0 -443
  311. package/runtime/python/okstra_vendor/networkx/generators/intersection.py +0 -125
  312. package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +0 -70
  313. package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +0 -664
  314. package/runtime/python/okstra_vendor/networkx/generators/lattice.py +0 -405
  315. package/runtime/python/okstra_vendor/networkx/generators/line.py +0 -501
  316. package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +0 -110
  317. package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +0 -259
  318. package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +0 -117
  319. package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +0 -1416
  320. package/runtime/python/okstra_vendor/networkx/generators/small.py +0 -1070
  321. package/runtime/python/okstra_vendor/networkx/generators/social.py +0 -554
  322. package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +0 -120
  323. package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +0 -54
  324. package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +0 -131
  325. package/runtime/python/okstra_vendor/networkx/generators/time_series.py +0 -74
  326. package/runtime/python/okstra_vendor/networkx/generators/trees.py +0 -1070
  327. package/runtime/python/okstra_vendor/networkx/generators/triads.py +0 -94
  328. package/runtime/python/okstra_vendor/networkx/lazy_imports.py +0 -188
  329. package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +0 -13
  330. package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +0 -650
  331. package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +0 -466
  332. package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +0 -77
  333. package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +0 -168
  334. package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +0 -512
  335. package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +0 -166
  336. package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +0 -186
  337. package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +0 -17
  338. package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +0 -330
  339. package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +0 -489
  340. package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +0 -1084
  341. package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +0 -879
  342. package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +0 -427
  343. package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +0 -1053
  344. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +0 -19
  345. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +0 -156
  346. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +0 -190
  347. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +0 -261
  348. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +0 -137
  349. package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +0 -108
  350. package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +0 -393
  351. package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +0 -113
  352. package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +0 -286
  353. package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +0 -379
  354. package/runtime/python/okstra_vendor/networkx/readwrite/text.py +0 -851
  355. package/runtime/python/okstra_vendor/networkx/relabel.py +0 -285
  356. package/runtime/python/okstra_vendor/networkx/utils/__init__.py +0 -8
  357. package/runtime/python/okstra_vendor/networkx/utils/backends.py +0 -2171
  358. package/runtime/python/okstra_vendor/networkx/utils/configs.py +0 -396
  359. package/runtime/python/okstra_vendor/networkx/utils/decorators.py +0 -1233
  360. package/runtime/python/okstra_vendor/networkx/utils/heaps.py +0 -338
  361. package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +0 -297
  362. package/runtime/python/okstra_vendor/networkx/utils/misc.py +0 -703
  363. package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +0 -198
  364. package/runtime/python/okstra_vendor/networkx/utils/rcm.py +0 -159
  365. package/runtime/python/okstra_vendor/networkx/utils/union_find.py +0 -106
  366. package/runtime/skills/okstra-graphify/SKILL.md +0 -169
  367. package/src/commands/graphify.mjs +0 -32
@@ -1788,6 +1788,11 @@ def _persist_run_inputs(
1788
1788
  brief_relative: str,
1789
1789
  ) -> None:
1790
1790
  """이 run 의 입력 스냅샷(run-inputs-*.json)을 run-manifests 디렉터리에 기록."""
1791
+ approved_plan_path = (
1792
+ str(Path(inp.approved_plan_path).resolve())
1793
+ if inp.approved_plan_path
1794
+ else ""
1795
+ )
1791
1796
  run_inputs_path = write_run_inputs(
1792
1797
  project_root=Path(inp.project_root),
1793
1798
  run_manifests_dir=Path(ctx["RUN_MANIFESTS_DIR"]),
@@ -1805,7 +1810,7 @@ def _persist_run_inputs(
1805
1810
  "reportWriterModel": models.rw.display,
1806
1811
  "executor": models.executor_provider,
1807
1812
  "relatedTasks": inp.related_tasks_raw,
1808
- "approvedPlanPath": inp.approved_plan_path,
1813
+ "approvedPlanPath": approved_plan_path,
1809
1814
  "clarificationResponsePath": inp.clarification_response_path,
1810
1815
  "renderOnly": inp.render_only,
1811
1816
  },
@@ -2363,8 +2368,15 @@ def main(argv: list[str]) -> int:
2363
2368
  p.add_argument("--critic", default="")
2364
2369
  p.add_argument("--related-tasks", default="", dest="related_tasks_raw")
2365
2370
  p.add_argument("--approved-plan", default="", dest="approved_plan_path")
2366
- p.add_argument("--qa-waiver", default="", dest="qa_waiver",
2367
- help='Stage conformance 우회: "<stageKey>:<reason>" (사용자 확인형, 매니페스트 entry.waiver 기록)')
2371
+ p.add_argument(
2372
+ "--qa-waiver",
2373
+ default="",
2374
+ dest="qa_waiver",
2375
+ help=(
2376
+ 'User-recorded stage conformance waiver: "<stageKey>:<reason>". '
2377
+ "Normally used only for blocking local io entries; external QA is advisory."
2378
+ ),
2379
+ )
2368
2380
  p.add_argument(
2369
2381
  "--stage", default="auto", dest="stage",
2370
2382
  help=(
@@ -6,7 +6,11 @@ from dataclasses import dataclass
6
6
  from pathlib import Path
7
7
  from typing import Any, Mapping, Sequence
8
8
 
9
- from .worker_prompt_policy import PromptPlan, resolve_prompt_plan_for_manifest
9
+ from .worker_prompt_policy import (
10
+ ERRORS_PATH_HEADERS,
11
+ PromptPlan,
12
+ resolve_prompt_plan_for_manifest,
13
+ )
10
14
 
11
15
 
12
16
  MAX_FINAL_VERIFICATION_DIRECTIVE_LINES = 40
@@ -35,8 +39,7 @@ _NON_BODY_PREFIXES = (
35
39
  "**Audit sidecar path:**",
36
40
  "Assigned worker prompt history path:",
37
41
  "**Worker Preamble Path:**",
38
- "**Errors log path:**",
39
- "**Errors sidecar path:**",
42
+ *ERRORS_PATH_HEADERS,
40
43
  "**Read scope:**",
41
44
  "**Worktree:**",
42
45
  "**Verification scope:**",
@@ -231,8 +234,15 @@ def _validate_prompt_for_plan(
231
234
  ) -> list[str]:
232
235
  errors: list[str] = []
233
236
  _require_non_empty_header(text, _WORKER_ERROR_CONTRACT_HEADER, errors)
237
+ # The compact final-verification contract below returns early, so the plan's
238
+ # own required headers must be checked before that branch or they never are.
239
+ for prefix in plan.required_headers:
240
+ _require_non_empty_header(text, prefix, errors)
234
241
  if manifest.get("taskType") == "final-verification" and plan.audience == "analysis":
235
- return [*errors, *validate_final_verification_initial_prompt(text)]
242
+ # Compact target identity re-checks headers the loop above already
243
+ # required, so drop the repeats and report each violation once.
244
+ compact = validate_final_verification_initial_prompt(text)
245
+ return errors + [error for error in compact if error not in errors]
236
246
  if not plan.allow_coding_preflight:
237
247
  _reject_literal(
238
248
  text,
@@ -240,8 +250,6 @@ def _validate_prompt_for_plan(
240
250
  "Coding preflight pack is forbidden for this prompt audience",
241
251
  errors,
242
252
  )
243
- for prefix in plan.required_headers:
244
- _require_non_empty_header(text, prefix, errors)
245
253
  if plan.audience == "analysis":
246
254
  packet_count = len(_PRIMARY_PACKET_RE.findall(text))
247
255
  if packet_count != 1:
@@ -17,6 +17,14 @@ PromptAudience = Literal[
17
17
  # The prompt emitter, the run validator, and the worker-facing docs all bind to
18
18
  # this literal; restating it anywhere else silently forks the dispatch contract.
19
19
  GRILLING_LOG_HEADER = "**Phase 1.5 Grilling Log:**"
20
+ # Workers extract both paths verbatim and abort with
21
+ # `<SENTINEL_PREFIX>_ERRORS_PATH_MISSING` when either is absent, because
22
+ # synthesizing them from a run-directory pattern is forbidden. A prompt that
23
+ # reaches a worker without them yields an empty run-level errors log.
24
+ ERRORS_PATH_HEADERS = (
25
+ "**Errors log path:**",
26
+ "**Errors sidecar path:**",
27
+ )
20
28
  FINAL_VERIFICATION_HEADERS = (
21
29
  "**Worktree:**",
22
30
  "**Verification scope:**",
@@ -137,12 +145,22 @@ def _plan(
137
145
  equality_group=equality_group,
138
146
  packet_only=packet_only,
139
147
  allow_coding_preflight=allow_coding_preflight,
140
- required_headers=required_headers,
148
+ required_headers=_worker_facing_headers(audience, required_headers),
141
149
  max_body_lines=max_body_lines,
142
150
  max_directive_lines=max_directive_lines,
143
151
  )
144
152
 
145
153
 
154
+ def _worker_facing_headers(
155
+ audience: PromptAudience,
156
+ required_headers: tuple[str, ...],
157
+ ) -> tuple[str, ...]:
158
+ """Prepend the errors-path pair every prompt that reaches a worker carries."""
159
+ if audience == "lead-only":
160
+ return required_headers
161
+ return (*ERRORS_PATH_HEADERS, *required_headers)
162
+
163
+
146
164
  def _executor_worker_id(manifest: Mapping[str, Any]) -> str | None:
147
165
  team_contract = manifest.get("teamContract")
148
166
  if not isinstance(team_contract, Mapping):
@@ -11,12 +11,6 @@ Currently vendored:
11
11
  - markupsafe 3.0.3 (BSD-3-Clause) — jinja2 dependency. C extension
12
12
  (`_speedups.c` / `_speedups.pyi`) is stripped; the pure-python
13
13
  `_native` fallback is used at import time.
14
- - networkx (BSD-3-Clause) — graph model + community detection for okstra-graphify.
15
- Per-package `tests/` suites and the top-level `conftest.py` are stripped;
16
- okstra never runs networkx's own test suite. On re-vendor, drop every
17
- `**/tests/` directory and `conftest.py` again.
18
- - graphify 0.4.23 (MIT) — knowledge-graph pipeline for okstra-graphify. tree-sitter
19
- native bindings are NOT vendored; okstra-graphify only indexes .okstra/ docs.
20
14
 
21
15
  Source provenance and licenses are preserved verbatim under each
22
16
  sub-package. Do not edit vendored files in place — re-vendor from PyPI
@@ -28,21 +22,8 @@ re-routing, those would either fail (no system install) or resolve to
28
22
  unrelated user-installed copies. We register the vendored copies in
29
23
  `sys.modules` under their canonical top-level names so jinja2's internal
30
24
  imports find them deterministically.
31
-
32
- networkx and graphify need a stronger mechanism than jinja2/markupsafe.
33
- Both use *self-referential* absolute imports (networkx's `__init__` does
34
- `from networkx.lazy_imports import ...`; graphify submodules do `import
35
- networkx`). Those fire while the package body is still executing, before a
36
- post-hoc `sys.modules.setdefault` could run — so on a machine that also has
37
- these libraries pip-installed globally, the self-import would resolve to the
38
- global copy and cache it under the canonical name. `_vendor_as_toplevel`
39
- registers the module in `sys.modules` under its canonical name *before*
40
- executing its body, so every self-referential import resolves back into the
41
- vendored tree deterministically. networkx is loaded before graphify because
42
- graphify's cluster/export/serve modules import networkx at module-load time.
43
25
  """
44
26
 
45
- import importlib.util as _importlib_util
46
27
  import sys as _sys
47
28
 
48
29
  # Register markupsafe alias BEFORE importing jinja2 — jinja2's __init__
@@ -54,28 +35,3 @@ _sys.modules.setdefault("markupsafe", _markupsafe)
54
35
 
55
36
  from . import jinja2 as _jinja2 # noqa: E402
56
37
  _sys.modules.setdefault("jinja2", _jinja2)
57
-
58
-
59
- def _vendor_as_toplevel(top_name, vendored_name):
60
- """Load a vendored sub-package under its canonical top-level name.
61
-
62
- Registers the module in ``sys.modules`` before executing its body so
63
- that self-referential absolute imports inside the package resolve to the
64
- vendored copy rather than a globally pip-installed one.
65
- """
66
- if top_name in _sys.modules:
67
- return _sys.modules[top_name]
68
- vendored_spec = _importlib_util.find_spec(vendored_name)
69
- top_spec = _importlib_util.spec_from_file_location(
70
- top_name,
71
- vendored_spec.origin,
72
- submodule_search_locations=list(vendored_spec.submodule_search_locations),
73
- )
74
- module = _importlib_util.module_from_spec(top_spec)
75
- _sys.modules[top_name] = module
76
- top_spec.loader.exec_module(module)
77
- return module
78
-
79
-
80
- _networkx = _vendor_as_toplevel("networkx", __name__ + ".networkx")
81
- _graphify = _vendor_as_toplevel("graphify", __name__ + ".graphify")
@@ -446,6 +446,11 @@
446
446
  "items": { "$ref": "#/$defs/ImplementationRequirementCoverageRow" }
447
447
  },
448
448
  "planBodyVerification": { "$ref": "#/$defs/PlanBodyVerification" },
449
+ "supersessionLedger": {
450
+ "type": "array",
451
+ "description": "One entry per clarification this run answered, recording which plan statements the answer invalidated. Incorporating an answer by adding the new decision while leaving the contradicting sentence in place is what produces two opposite instructions for the same symbol in one plan.",
452
+ "items": { "$ref": "#/$defs/SupersessionEntry" }
453
+ },
449
454
  "crossProjectDependencies": {
450
455
  "type": "array",
451
456
  "items": { "$ref": "#/$defs/CrossProjectDependency" }
@@ -1256,7 +1261,8 @@
1256
1261
  "ticketId": { "$ref": "#/$defs/TicketId" },
1257
1262
  "action": { "enum": ["Create", "Modify", "Delete"] },
1258
1263
  "path": { "type": "string", "minLength": 1 },
1259
- "summary": { "type": "string", "minLength": 1 }
1264
+ "summary": { "type": "string", "minLength": 1, "maxLength": 120 },
1265
+ "details": { "type": "string", "minLength": 1 }
1260
1266
  }
1261
1267
  }
1262
1268
  },
@@ -1841,6 +1847,60 @@
1841
1847
  }
1842
1848
  },
1843
1849
 
1850
+ "SelfFixGroup": {
1851
+ "type": "object",
1852
+ "required": ["round", "causeSummary", "itemIds"],
1853
+ "additionalProperties": false,
1854
+ "properties": {
1855
+ "round": { "type": "integer", "minimum": 1 },
1856
+ "causeSummary": { "type": "string", "minLength": 1 },
1857
+ "itemIds": {
1858
+ "type": "array",
1859
+ "minItems": 1,
1860
+ "uniqueItems": true,
1861
+ "items": { "type": "string", "minLength": 1 }
1862
+ }
1863
+ }
1864
+ },
1865
+
1866
+ "SupersessionEntry": {
1867
+ "type": "object",
1868
+ "required": ["clarificationId", "disposition"],
1869
+ "additionalProperties": false,
1870
+ "properties": {
1871
+ "clarificationId": { "type": "string", "pattern": "^C-\\d+$" },
1872
+ "disposition": { "enum": ["superseded", "no-dependent-statement"] },
1873
+ "revisedSections": {
1874
+ "type": "array",
1875
+ "items": { "type": "string", "minLength": 1 }
1876
+ },
1877
+ "supersededStatement": { "type": "string", "minLength": 1 },
1878
+ "replacedWith": { "type": "string", "minLength": 1 },
1879
+ "rationale": { "type": "string", "minLength": 1 }
1880
+ },
1881
+ "allOf": [
1882
+ {
1883
+ "if": {
1884
+ "properties": { "disposition": { "const": "superseded" } },
1885
+ "required": ["disposition"]
1886
+ },
1887
+ "then": {
1888
+ "required": ["revisedSections", "supersededStatement", "replacedWith"],
1889
+ "properties": { "revisedSections": { "minItems": 1 } }
1890
+ }
1891
+ },
1892
+ {
1893
+ "if": {
1894
+ "properties": {
1895
+ "disposition": { "const": "no-dependent-statement" }
1896
+ },
1897
+ "required": ["disposition"]
1898
+ },
1899
+ "then": { "required": ["rationale"] }
1900
+ }
1901
+ ]
1902
+ },
1903
+
1844
1904
  "PlanBodyVerification": {
1845
1905
  "type": "object",
1846
1906
  "required": ["roundCount", "gateResult", "planItems", "dissentLog"],
@@ -1855,7 +1915,19 @@
1855
1915
  "aborted-non-result"
1856
1916
  ]
1857
1917
  },
1918
+ "gateBlockedBy": {
1919
+ "type": "array",
1920
+ "uniqueItems": true,
1921
+ "items": {
1922
+ "enum": ["majority-disagree", "coverage-gap", "non-result"]
1923
+ }
1924
+ },
1858
1925
  "selfFixRoundsApplied": { "type": "integer", "minimum": 0 },
1926
+ "selfFixGroups": {
1927
+ "type": "array",
1928
+ "description": "How each self-fix round's targets were grouped by common cause before being handed to report-writer. Several blocked items are usually one defect's derivatives; instructing them as a flat list makes each patch leave its siblings' contradictions standing, so the same family reappears next round.",
1929
+ "items": { "$ref": "#/$defs/SelfFixGroup" }
1930
+ },
1859
1931
  "selfFixStopReason": {
1860
1932
  "enum": [
1861
1933
  "not-attempted",
@@ -1893,8 +1965,14 @@
1893
1965
  "verdict": {
1894
1966
  "enum": ["AGREE", "DISAGREE", "SUPPLEMENT", "verification-error"]
1895
1967
  },
1896
- "breakageKind": { "type": "string" },
1897
- "fixability": { "enum": ["planner-fixable", "needs-user-input"] },
1968
+ "breakageKind": {
1969
+ "description": "Set only on DISAGREE. `null` and absent are equivalent, matching the sibling `votes.<worker>.disagreeBasis` contract in prompts/lead/convergence.md.",
1970
+ "type": ["string", "null"]
1971
+ },
1972
+ "fixability": {
1973
+ "description": "Set only on DISAGREE. `null` and absent are equivalent.",
1974
+ "enum": ["planner-fixable", "needs-user-input", null]
1975
+ },
1898
1976
  "note": { "type": "string" }
1899
1977
  }
1900
1978
  }
@@ -2105,9 +2183,9 @@
2105
2183
  "additionalProperties": false,
2106
2184
  "properties": {
2107
2185
  "number": { "type": "integer", "minimum": 1 },
2108
- "tier": { "enum": [1, 2] },
2186
+ "tier": { "enum": [1, 2, 3] },
2109
2187
  "command": { "type": "string", "minLength": 1 },
2110
- "status": { "enum": ["executed", "rejected", "not-configured", "env-unavailable"] },
2188
+ "status": { "enum": ["executed", "rejected", "not-configured", "env-unavailable", "advisory"] },
2111
2189
  "exitCode": { "type": ["integer", "null"] },
2112
2190
  "statusReason": { "type": ["string", "null"] },
2113
2191
  "outputTail": { "type": "string" }
@@ -2118,7 +2196,24 @@
2118
2196
  { "if": { "properties": { "status": { "const": "rejected" } } },
2119
2197
  "then": { "required": ["statusReason"] } },
2120
2198
  { "if": { "properties": { "status": { "const": "env-unavailable" } } },
2121
- "then": { "required": ["statusReason"] } }
2199
+ "then": { "required": ["statusReason"] } },
2200
+ {
2201
+ "if": {
2202
+ "properties": { "status": { "const": "advisory" } },
2203
+ "required": ["status"]
2204
+ },
2205
+ "then": {
2206
+ "required": ["statusReason"],
2207
+ "properties": {
2208
+ "tier": { "const": 3 },
2209
+ "statusReason": {
2210
+ "type": "string",
2211
+ "minLength": 1,
2212
+ "pattern": ".*\\S.*"
2213
+ }
2214
+ }
2215
+ }
2216
+ }
2122
2217
  ]
2123
2218
  },
2124
2219
 
@@ -201,11 +201,18 @@ The python function underneath is mutex-protected (`~/.okstra/.locks/<task-key>.
201
201
 
202
202
  You can delete the literal state-file path after this point — its job is done. Invoke `rm` with the literal path (e.g. `rm /var/folders/.../okstra-wizard.AbCd.json`), not a shell variable.
203
203
 
204
- ### Step 5.1 (implementation only): conformance waiver offer
204
+ ### Step 5.1 (implementation only): blocking local conformance waiver offer
205
205
 
206
- `render-bundle` accepts an optional `--qa-waiver "<stageKey>:<reason>"` flag (implementation only). It records a **user-acknowledged** waiver into the task-level conformance manifest entry (`entry.waiver`), letting the run proceed when a stage's Tier 3 conformance script genuinely cannot run (e.g. the replica DB is unreachable). The waiver records the user's reason **verbatim**.
206
+ `render-bundle` accepts an optional `--qa-waiver "<stageKey>:<reason>"` flag (implementation only). It records a **user-acknowledged** waiver into the task-level conformance manifest entry (`entry.waiver`), letting the run proceed when an `io`-only Tier 3 conformance script genuinely cannot run. The waiver records the user's reason **verbatim**.
207
207
 
208
- This is **never** a lead/worker self-exemption — only the user may waive. Offer it **only** when conformance BLOCKING is expected (the chosen stage declares a conformance entry whose script you cannot run in this environment). Surface it as a 3-option recommendation picker (per the run-prompt recommendation rule):
208
+ Inspect the selected manifest entry's `requires`. If it contains `db`, `http`,
209
+ or `external`, it is external-advisory: Do not offer a waiver and continue so
210
+ the verifier can attempt automatic startup/execution. A non-PASS outcome will
211
+ become a user-owned follow-up. If `requires=[]`, fail closed as declaration or
212
+ contract trouble: Do not offer a waiver for `requires=[]`. Offer the existing
213
+ waiver picker only when `requires=[io]` and that local command genuinely cannot run.
214
+
215
+ This is **never** a lead/worker self-exemption — only the user may waive. After classification confirms `requires=[io]`, surface it as a 3-option recommendation picker (per the run-prompt recommendation rule):
209
216
 
210
217
  1. (recommended) Run the conformance script — no waiver.
211
218
  2. Waive this stage — ask the user for the exact `<stageKey>` and reason, then pass `--qa-waiver "<stageKey>:<reason>"` to `render-bundle` (reason = the user's words, unedited).
@@ -249,7 +256,7 @@ When `task-type == implementation` and Step 5 render-args' `chain-stages` CSV ha
249
256
 
250
257
  Queue = the topologically-sorted stage list from splitting `chain-stages` on `,` (the order Task 5 emitted by topologically sorting the dependency closure). For each stage `N` in the queue, in order:
251
258
 
252
- 1. Call Step 5's `render-bundle` with the same arguments but `--stage N` (the base commit is auto-computed by prepare from the predecessor's done `head_commit`, so do not pass it by hand). Step 5's conformance waiver offer·concurrent-run detection·git-reconcile gates apply identically to each stage's `render-bundle`.
259
+ 1. Call Step 5's `render-bundle` with the same arguments but `--stage N` (the base commit is auto-computed by prepare from the predecessor's done `head_commit`, so do not pass it by hand). Step 5's blocking local conformance waiver offer·concurrent-run detection·git-reconcile gates apply identically to each stage's `render-bundle`.
253
260
  2. As in Step 6, become Claude lead and run that stage's Phase 1–7 inline. Phase 6's lead post-stage persistence appends that stage's `status:"done"` row to `runs/<plan-task-key>/consumers.jsonl` (per the implementation profile directive).
254
261
  3. After confirming that `done` row was written, move to the next stage. Clean up context at each stage boundary (leftover panes·finished teammates from the previous batch).
255
262
  4. One-line report at each stage start/finish: `stage N/<total> start` / `stage N done → next K`.
@@ -107,8 +107,9 @@ matching section:
107
107
  - **A. worktree sync dirs** (`worktreeSyncDirs`) — extra directories symlinked
108
108
  into task worktrees.
109
109
  - **B. project QA commands** (`qaCommands`, recommended) + **B.1 `qaEnv`** —
110
- check-only lint/format/typecheck/test baseline and the Tier 3 conformance
111
- environment the `implementation` verifiers use.
110
+ check-only lint/format/typecheck/test baselines and the Tier 3 environment.
111
+ Local `io` conformance is blocking; DB/HTTP/external QA is advisory and
112
+ remains user-owned when automatic execution cannot PASS.
112
113
  - **C. `.claude/settings.local.json` symlink** — automatic; read only to
113
114
  diagnose a symlink/backup warning.
114
115
  - **D. PR body template** (release-handoff) — opt-in pre-registration; also
@@ -86,6 +86,15 @@ prove the diff satisfies upstream requirements. Declare the environment those
86
86
  scripts are allowed to touch under `qaEnv`. Every field is optional; declare
87
87
  only what your conformance scripts use.
88
88
 
89
+ `qaEnv` lets Okstra attempt Tier 3 automatically; it does not transfer
90
+ ownership of a real DB/API check to the run. Entries requiring `db`, `http`,
91
+ or `external` are advisory: a missing environment or non-PASS result is
92
+ reported with an exact rerun method but does not block the run. `io`-only
93
+ conformance stays blocking. Remote IO should also declare `external`; this is
94
+ an authoring guideline, not an automatically detected contract. Gate outcomes
95
+ are enforced by `scripts/okstra_ctl/conformance.py::decide_conformance_gate`
96
+ and `validators/validate-run.py::_validate_conformance`.
97
+
89
98
  ```json
90
99
  "qaEnv": {
91
100
  "replicaDbDsn": "<replica/test DB DSN — never shared/staging/prod>",
@@ -104,13 +113,13 @@ only what your conformance scripts use.
104
113
  before running conformance scripts.
105
114
  - `surfacePatterns` — per-project **override** of the diff-surface cross-check
106
115
  map (`capability → glob list`). The validator maps each changed file to a
107
- capability surface (`db` / `http` / `io`) and fails the run when the diff
108
- touches a surface no stage `requires`. The built-in patterns (e.g. `*router*`
109
- for `http`, `*storage*` for `io`) are broad and match many front-end files,
110
- so front-end-heavy repos should override with narrower globs to avoid false
111
- BLOCKING verdicts. An over-broad pattern over-blocks; an over-narrow one
112
- lets an undeclared surface through — tune to the repo's real db/http/io file
113
- naming.
116
+ capability surface (`db` / `http` / `io`) and fails the declaration contract
117
+ when the diff touches a surface no stage `requires`. The built-in patterns
118
+ (e.g. `*router*` for `http`, `*storage*` for `io`) are broad and match many
119
+ front-end files, so front-end-heavy repos should override with narrower globs
120
+ to avoid false BLOCKING verdicts. An over-broad pattern over-blocks; an
121
+ over-narrow one lets an undeclared surface through — tune to the repo's real
122
+ db/http/io file naming.
114
123
 
115
124
  ## C. Project-local Claude settings symlink (automatic — diagnostics only)
116
125
 
@@ -204,10 +204,10 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
204
204
 
205
205
  - File Structure:
206
206
 
207
- | ID | Ticket ID | Action | Path (and line-range) | Change summary |
208
- |----|-----------|--------|------------------------|----------------|
207
+ | {{ t("columns.recordMeta") }} | Path (and line-range) | Change summary |
208
+ |------|------------------------|----------------|
209
209
  {% for fs in opt.fileStructure -%}
210
- | {{ fs.id | mdcell }} | `{{ fs.ticketId | mdcell }}` | {{ fs.action | mdcell }} | `{{ fs.path | mdcell }}` | {{ fs.summary | mdcell }} |
210
+ | **{{ fs.id | mdcell }}**<br>Ticket: `{{ fs.ticketId | mdcell }}`<br>Action: {{ fs.action | mdcell }} | `{{ fs.path | mdcell }}` | {{ fs.summary | mdcell }}{% if fs.details %}<br><small>{{ fs.details | mdcell }}</small>{% endif %} |
211
211
  {% endfor %}
212
212
 
213
213
  - {{ t("implementationPlanning.optionInterfacesLabel") }}: {{ opt.interfaces }}
@@ -358,8 +358,11 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
358
358
 
359
359
  - **Round count**: `{{ implementationPlanning.planBodyVerification.roundCount }}`
360
360
  - **Gate result**: `{{ implementationPlanning.planBodyVerification.gateResult }}`
361
-
361
+ {% if implementationPlanning.planBodyVerification.gateBlockedBy %}- **Blocked by**: {% for cause in implementationPlanning.planBodyVerification.gateBlockedBy %}`{{ cause }}`{% if not loop.last %}, {% endif %}{% endfor %}
362
+ {% endif %}
362
363
  > {{ t("implementationPlanning.planBodyGateLegend") }}
364
+ >
365
+ > {{ t("implementationPlanning.planBodyBlockedByLegend") }}
363
366
 
364
367
  #### Verdict details
365
368
 
@@ -703,7 +706,7 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
703
706
  | # | Tier | Command (verbatim) | Status | Exit code | Output tail |
704
707
  |---|------|---------------------|--------|-----------|-------------|
705
708
  {% for row in finalVerification.readonlyCommandLog -%}
706
- | {{ row.number | mdcell }} | {{ row.tier | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.status | mdcell }}` | {{ (row.exitCode if row.exitCode is not none else '—') | mdcell }} | {{ (row.statusReason if row.status in ['rejected', 'env-unavailable'] else row.outputTail) | mdcell }} |
709
+ | {{ row.number | mdcell }} | {{ row.tier | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.status | mdcell }}` | {{ (row.exitCode if row.exitCode is not none else '—') | mdcell }} | {{ (row.statusReason if row.status in ['rejected', 'env-unavailable', 'advisory'] else row.outputTail) | mdcell }} |
707
710
  {% endfor %}
708
711
 
709
712
  ### 5.8.6 Conditional Acceptance Conditions
@@ -736,24 +739,27 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
736
739
 
737
740
  ### 5.8.9 Could-Not-Verify Roll-up
738
741
 
739
- Single scan of every agreed check that this run did NOT confirm — requirement gaps, commands not run (rejected / not-configured / env-unavailable), and blocked manual tests — aggregated from the sections above.
742
+ Single scan of every agreed check that this run did NOT confirm — requirement gaps, commands not run (rejected / not-configured / env-unavailable), advisory commands, and blocked manual tests — aggregated from the sections above.
740
743
 
741
- {% set nv = namespace(any=false) -%}
742
744
  {% for row in finalVerification.validationEvidence if row.status == 'gap' -%}
743
- {% set nv.any = true -%}
744
745
  - `{{ row.id | mdcell }}` requirement gap — {{ row.requirement | mdcell }}
745
746
  {% endfor -%}
746
- {% for row in finalVerification.readonlyCommandLog if row.status in ['rejected', 'not-configured', 'env-unavailable'] -%}
747
- {% set nv.any = true -%}
747
+ {% for row in finalVerification.readonlyCommandLog if row.status in ['rejected', 'not-configured', 'env-unavailable', 'advisory'] -%}
748
748
  - `{{ row.command | mdcell }}` — {{ row.status | mdcell }}: {{ row.statusReason | mdcell }}
749
749
  {% endfor -%}
750
750
  {% if finalVerification.manualUserTest.applicable -%}
751
751
  {% for row in finalVerification.manualUserTest.results if row.result == 'blocked' -%}
752
- {% set nv.any = true -%}
753
752
  - manual: {{ row.target | mdcell }} — {{ row.performed | mdcell }} (blocked): {{ row.observed | mdcell }}
754
753
  {% endfor -%}
755
754
  {% endif -%}
756
- {% if not nv.any -%}
755
+ {% if not (
756
+ finalVerification.validationEvidence | selectattr('status', 'equalto', 'gap') | list
757
+ or finalVerification.readonlyCommandLog | selectattr('status', 'in', ['rejected', 'not-configured', 'env-unavailable', 'advisory']) | list
758
+ or (
759
+ finalVerification.manualUserTest.applicable
760
+ and finalVerification.manualUserTest.results | selectattr('result', 'equalto', 'blocked') | list
761
+ )
762
+ ) -%}
757
763
  - All agreed checks were executed or covered — nothing left unverified.
758
764
  {%- endif %}
759
765
 
@@ -103,6 +103,7 @@
103
103
  },
104
104
  "implementationPlanning": {
105
105
  "planBodyGateLegend": "Gate values — `passed`: agreed, no dissent · `passed-with-dissent`: a minority dissent remains but the gate passes (a majority dissent would block approval) · `blocked-by-disagreement`: majority dissent blocks approval · `aborted-non-result`: verification itself produced no result.",
106
+ "planBodyBlockedByLegend": "Which input blocked the gate — `majority-disagree`: a worker majority dissent · `coverage-gap`: a Requirement Coverage gap / blocked row, independent of worker votes · `non-result`: verification produced no result. Absent means nothing blocked.",
106
107
  "planBodyVerdictLegend": "Verdict — **AGREE**: executable as written and internally consistent with other items · **SUPPLEMENT**: item is sound but a dependency / edge case / precondition is missing · **DISAGREE**: has a defect (see Breakage kind) · **verification-error**: the worker produced no result.",
107
108
  "planBodyBreakageLegend": "Breakage kind — a: cited file path/symbol mismatches another step or option · b: command is not executable or is ambiguous · c: validation signal is not observable · d: rollback violates commit/dependency order · e: contradicts the trade-off matrix · f: requirement-coverage row does not map to an option/stage/step that actually satisfies the requirement. (`--` = not applicable) Fixability: planner-fixable = correctable from code + plan + brief; needs-user-input = requires an external decision.",
108
109
  "planBodySourceLabel": "source §",
@@ -103,6 +103,7 @@
103
103
  },
104
104
  "implementationPlanning": {
105
105
  "planBodyGateLegend": "게이트 결과 값 뜻 — `passed`: 이견 없이 통과 · `passed-with-dissent`: 소수 워커의 반대가 남았으나 통과(반대가 다수였다면 승인 차단) · `blocked-by-disagreement`: 다수 반대로 승인 차단 · `aborted-non-result`: 검증 자체가 결과를 내지 못함.",
106
+ "planBodyBlockedByLegend": "게이트를 막은 입력 — `majority-disagree`: 워커 다수 반대 · `coverage-gap`: Requirement Coverage 의 gap / blocked 행(워커 반대와는 무관) · `non-result`: 검증 자체가 결과를 내지 못함. 이 항목이 없으면 차단 원인이 없다는 뜻이다.",
106
107
  "planBodyVerdictLegend": "판정(Verdict) — **AGREE**: 적힌 대로 실행 가능하고 다른 항목과 내부적으로 일관됨 · **SUPPLEMENT**: 항목 자체는 타당하나 의존성·엣지케이스·전제조건이 누락됨 · **DISAGREE**: 결함이 있음(결함 유형 참조) · **verification-error**: 워커 검증이 결과를 내지 못함.",
107
108
  "planBodyBreakageLegend": "결함 유형(Breakage kind) — a: 인용한 파일 경로/심볼이 다른 스텝·옵션과 불일치 · b: 명령이 실행 불가하거나 모호함 · c: 검증 신호가 관측 불가 · d: 롤백이 커밋/의존성 순서를 위반 · e: 트레이드오프 매트릭스와 모순 · f: 요구사항 커버리지 행이 요구사항을 실제로 충족하는 옵션/스테이지/스텝에 매핑되지 않음. (`--` = 해당 없음) · 자가수정 가능 여부(Fixability) — planner-fixable: 코드·계획·브리프만으로 수정 가능 · needs-user-input: 외부 결정 필요",
108
109
  "planBodySourceLabel": "출처 §",
@@ -188,6 +188,24 @@ td.td-narrow, th.td-narrow {
188
188
  width: 5%;
189
189
  white-space: nowrap;
190
190
  }
191
+ /* Path columns — assigned by `_path_columns()` in report_views.py. A
192
+ * repo-relative path holds no spaces, so the `overflow-wrap: anywhere`
193
+ * above lets the auto table layout starve the column down to a couple of
194
+ * characters per line. Floor the width and let it wrap at separators. */
195
+ td.td-path, th.td-path {
196
+ min-width: 26ch;
197
+ word-break: break-word;
198
+ }
199
+
200
+ /* Second line of a two-tier cell: the plain-language summary leads, the
201
+ * technical detail follows demoted. */
202
+ td small {
203
+ display: inline-block;
204
+ margin-top: 0.35em;
205
+ font-size: 0.88em;
206
+ color: GrayText;
207
+ }
208
+
191
209
  thead th {
192
210
  position: sticky;
193
211
  top: 3rem;
@@ -133,6 +133,9 @@ prompt_path.write_text(
133
133
  "\n".join(
134
134
  [
135
135
  "**Worker Error Contract Path:** /okstra/templates/worker-error-contract.md",
136
+ f"**Errors log path:** {project_root}/run/logs/errors.jsonl",
137
+ f"**Errors sidecar path:** {project_root}/run/worker-results/"
138
+ f"{target_worker_id}-errors.json",
136
139
  f"Assigned worker prompt history path: {prompt_relative}",
137
140
  f"- Primary analysis packet: `{analysis_packet_path}`",
138
141
  "",
@@ -223,6 +226,9 @@ for worker in team_state.get("workers", []):
223
226
  prompt_path.parent.mkdir(parents=True, exist_ok=True)
224
227
  prompt_lines = [
225
228
  "**Worker Error Contract Path:** /okstra/templates/worker-error-contract.md",
229
+ f"**Errors log path:** {project_root}/run/logs/errors.jsonl",
230
+ f"**Errors sidecar path:** {project_root}/run/worker-results/"
231
+ f"{worker_id}-errors.json",
226
232
  f"Assigned worker prompt history path: {prompt_relative}",
227
233
  ]
228
234
  if worker_id != "report-writer":