@su-record/vibe 4.2.34 → 4.2.36

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 (225) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/dist/cli/common.js +4 -1
  5. package/dist/cli/common.js.map +1 -1
  6. package/dist/cli/heldout.js +10 -4
  7. package/dist/cli/heldout.js.map +1 -1
  8. package/dist/cli/human.js +8 -4
  9. package/dist/cli/human.js.map +1 -1
  10. package/dist/cli/internal.js +37 -24
  11. package/dist/cli/internal.js.map +1 -1
  12. package/dist/cli/ledger.js +67 -0
  13. package/dist/cli/ledger.js.map +1 -0
  14. package/dist/cli/map.js +5 -3
  15. package/dist/cli/map.js.map +1 -1
  16. package/dist/cli/memory.js +104 -74
  17. package/dist/cli/memory.js.map +1 -1
  18. package/dist/cli/risks.js +20 -3
  19. package/dist/cli/risks.js.map +1 -1
  20. package/dist/cli/session.js +4 -2
  21. package/dist/cli/session.js.map +1 -1
  22. package/dist/cli/setup.js +44 -13
  23. package/dist/cli/setup.js.map +1 -1
  24. package/dist/cli/verification.js +1 -1
  25. package/dist/cli/verification.js.map +1 -1
  26. package/dist/cli/work.js +75 -22
  27. package/dist/cli/work.js.map +1 -1
  28. package/dist/cli.js +18 -6
  29. package/dist/cli.js.map +1 -1
  30. package/dist/core/analyze.js +21 -7
  31. package/dist/core/analyze.js.map +1 -1
  32. package/dist/core/artifact-paths.js +14 -3
  33. package/dist/core/artifact-paths.js.map +1 -1
  34. package/dist/core/capabilities.js +69 -15
  35. package/dist/core/capabilities.js.map +1 -1
  36. package/dist/core/check-authorization.js +37 -0
  37. package/dist/core/check-authorization.js.map +1 -0
  38. package/dist/core/check-process.js +12 -4
  39. package/dist/core/check-process.js.map +1 -1
  40. package/dist/core/check-report.js +66 -0
  41. package/dist/core/check-report.js.map +1 -0
  42. package/dist/core/check-selection.js +4 -2
  43. package/dist/core/check-selection.js.map +1 -1
  44. package/dist/core/check.js +66 -130
  45. package/dist/core/check.js.map +1 -1
  46. package/dist/core/checks/changed.js +20 -6
  47. package/dist/core/checks/changed.js.map +1 -1
  48. package/dist/core/checks/eval.js +35 -10
  49. package/dist/core/checks/eval.js.map +1 -1
  50. package/dist/core/checks/file.js +26 -23
  51. package/dist/core/checks/file.js.map +1 -1
  52. package/dist/core/checks/fileRules.js +42 -16
  53. package/dist/core/checks/fileRules.js.map +1 -1
  54. package/dist/core/checks/http.js +35 -34
  55. package/dist/core/checks/http.js.map +1 -1
  56. package/dist/core/checks/packs.js +1 -1
  57. package/dist/core/checks/packs.js.map +1 -1
  58. package/dist/core/checks/review.js +75 -40
  59. package/dist/core/checks/review.js.map +1 -1
  60. package/dist/core/checks/run.js +5 -2
  61. package/dist/core/checks/run.js.map +1 -1
  62. package/dist/core/checks/schema.js +25 -0
  63. package/dist/core/checks/schema.js.map +1 -0
  64. package/dist/core/checks/source.js +11 -6
  65. package/dist/core/checks/source.js.map +1 -1
  66. package/dist/core/config.js +9 -2
  67. package/dist/core/config.js.map +1 -1
  68. package/dist/core/consent.js +24 -16
  69. package/dist/core/consent.js.map +1 -1
  70. package/dist/core/context-notes.js +15 -7
  71. package/dist/core/context-notes.js.map +1 -1
  72. package/dist/core/context.js +24 -12
  73. package/dist/core/context.js.map +1 -1
  74. package/dist/core/conventions.js +22 -9
  75. package/dist/core/conventions.js.map +1 -1
  76. package/dist/core/docs/cfb.js +81 -45
  77. package/dist/core/docs/cfb.js.map +1 -1
  78. package/dist/core/docs/html.js +14 -3
  79. package/dist/core/docs/html.js.map +1 -1
  80. package/dist/core/docs/hwp.js +44 -22
  81. package/dist/core/docs/hwp.js.map +1 -1
  82. package/dist/core/docs/office.js +20 -10
  83. package/dist/core/docs/office.js.map +1 -1
  84. package/dist/core/docs/pdf.js +10 -4
  85. package/dist/core/docs/pdf.js.map +1 -1
  86. package/dist/core/docs/read.js +32 -24
  87. package/dist/core/docs/read.js.map +1 -1
  88. package/dist/core/docs/zip.js +32 -15
  89. package/dist/core/docs/zip.js.map +1 -1
  90. package/dist/core/evidence.js +17 -7
  91. package/dist/core/evidence.js.map +1 -1
  92. package/dist/core/failure-message.js +35 -13
  93. package/dist/core/failure-message.js.map +1 -1
  94. package/dist/core/failure.js +49 -14
  95. package/dist/core/failure.js.map +1 -1
  96. package/dist/core/github.js +3 -1
  97. package/dist/core/github.js.map +1 -1
  98. package/dist/core/handoff.js +20 -7
  99. package/dist/core/handoff.js.map +1 -1
  100. package/dist/core/heldout-run.js +6 -3
  101. package/dist/core/heldout-run.js.map +1 -1
  102. package/dist/core/heldout.js +24 -13
  103. package/dist/core/heldout.js.map +1 -1
  104. package/dist/core/inbox.js +3 -1
  105. package/dist/core/inbox.js.map +1 -1
  106. package/dist/core/inputs.js +76 -0
  107. package/dist/core/inputs.js.map +1 -0
  108. package/dist/core/inspect.js +61 -20
  109. package/dist/core/inspect.js.map +1 -1
  110. package/dist/core/intent.js +50 -12
  111. package/dist/core/intent.js.map +1 -1
  112. package/dist/core/knowledge-find.js +31 -12
  113. package/dist/core/knowledge-find.js.map +1 -1
  114. package/dist/core/knowledge.js +22 -12
  115. package/dist/core/knowledge.js.map +1 -1
  116. package/dist/core/lang.js +5 -2
  117. package/dist/core/lang.js.map +1 -1
  118. package/dist/core/ledger.js +44 -20
  119. package/dist/core/ledger.js.map +1 -1
  120. package/dist/core/locations.js +12 -0
  121. package/dist/core/locations.js.map +1 -0
  122. package/dist/core/map/imports.js +20 -9
  123. package/dist/core/map/imports.js.map +1 -1
  124. package/dist/core/map/index.js +28 -13
  125. package/dist/core/map/index.js.map +1 -1
  126. package/dist/core/map/symbols.js +27 -12
  127. package/dist/core/map/symbols.js.map +1 -1
  128. package/dist/core/output-capture.js +7 -4
  129. package/dist/core/output-capture.js.map +1 -1
  130. package/dist/core/paths.js +2 -1
  131. package/dist/core/paths.js.map +1 -1
  132. package/dist/core/performance.js +43 -17
  133. package/dist/core/performance.js.map +1 -1
  134. package/dist/core/profile.js +6 -3
  135. package/dist/core/profile.js.map +1 -1
  136. package/dist/core/reader.js +32 -16
  137. package/dist/core/reader.js.map +1 -1
  138. package/dist/core/readerSession.js +34 -14
  139. package/dist/core/readerSession.js.map +1 -1
  140. package/dist/core/recent.js +20 -6
  141. package/dist/core/recent.js.map +1 -1
  142. package/dist/core/regress.js +21 -12
  143. package/dist/core/regress.js.map +1 -1
  144. package/dist/core/repair.js +22 -4
  145. package/dist/core/repair.js.map +1 -1
  146. package/dist/core/research-queries.js +85 -0
  147. package/dist/core/research-queries.js.map +1 -0
  148. package/dist/core/research.js +89 -88
  149. package/dist/core/research.js.map +1 -1
  150. package/dist/core/results.js +89 -0
  151. package/dist/core/results.js.map +1 -0
  152. package/dist/core/risk-signals.js +55 -16
  153. package/dist/core/risk-signals.js.map +1 -1
  154. package/dist/core/run-id.js +10 -6
  155. package/dist/core/run-id.js.map +1 -1
  156. package/dist/core/scenarios.js +97 -57
  157. package/dist/core/scenarios.js.map +1 -1
  158. package/dist/core/session.js +3 -2
  159. package/dist/core/session.js.map +1 -1
  160. package/dist/core/size-gate.js +57 -0
  161. package/dist/core/size-gate.js.map +1 -0
  162. package/dist/core/size.js +32 -10
  163. package/dist/core/size.js.map +1 -1
  164. package/dist/core/skills.js +66 -28
  165. package/dist/core/skills.js.map +1 -1
  166. package/dist/core/skillsmp.js +26 -12
  167. package/dist/core/skillsmp.js.map +1 -1
  168. package/dist/core/source-basis.js +21 -9
  169. package/dist/core/source-basis.js.map +1 -1
  170. package/dist/core/status.js +26 -13
  171. package/dist/core/status.js.map +1 -1
  172. package/dist/core/table.js +8 -1
  173. package/dist/core/table.js.map +1 -1
  174. package/dist/core/tokens.js +20 -10
  175. package/dist/core/tokens.js.map +1 -1
  176. package/dist/core/tree.js +26 -16
  177. package/dist/core/tree.js.map +1 -1
  178. package/dist/core/verification-plan.js +26 -10
  179. package/dist/core/verification-plan.js.map +1 -1
  180. package/dist/core/verification.js +14 -7
  181. package/dist/core/verification.js.map +1 -1
  182. package/dist/core/view.js +93 -44
  183. package/dist/core/view.js.map +1 -1
  184. package/dist/install/global.js +37 -18
  185. package/dist/install/global.js.map +1 -1
  186. package/dist/install/hooks.js +17 -8
  187. package/dist/install/hooks.js.map +1 -1
  188. package/dist/install/manifest.js +11 -0
  189. package/dist/install/manifest.js.map +1 -0
  190. package/dist/install/mcpb.js +52 -23
  191. package/dist/install/mcpb.js.map +1 -1
  192. package/dist/install/plugin.js +73 -33
  193. package/dist/install/plugin.js.map +1 -1
  194. package/dist/install/project.js +8 -7
  195. package/dist/install/project.js.map +1 -1
  196. package/dist/install/register.js +83 -48
  197. package/dist/install/register.js.map +1 -1
  198. package/dist/install/tree.js +27 -11
  199. package/dist/install/tree.js.map +1 -1
  200. package/dist/install/update.js +46 -20
  201. package/dist/install/update.js.map +1 -1
  202. package/hooks/code-map.cjs +22 -9
  203. package/hooks/file-size.cjs +83 -0
  204. package/hooks/journal.cjs +28 -18
  205. package/hooks/knowledge-auto.cjs +55 -21
  206. package/hooks/knowledge-journal.cjs +47 -20
  207. package/hooks/knowledge-projects.cjs +50 -21
  208. package/hooks/knowledge-recall.cjs +16 -6
  209. package/hooks/knowledge-upkeep.cjs +22 -5
  210. package/hooks/locations.cjs +35 -0
  211. package/hooks/notify.js +52 -24
  212. package/hooks/obsidian.cjs +17 -7
  213. package/hooks/private-store.cjs +25 -10
  214. package/hooks/retest.cjs +39 -16
  215. package/hooks/session-context.cjs +30 -13
  216. package/hooks/session-files.cjs +44 -21
  217. package/hooks/session-repair.cjs +26 -11
  218. package/hooks/session-state.cjs +78 -38
  219. package/hooks/session.js +19 -8
  220. package/hooks/slice-command.cjs +38 -17
  221. package/hooks/slice-guard.cjs +20 -6
  222. package/hooks/slice-store.cjs +25 -12
  223. package/internal/guides/code.md +17 -0
  224. package/mcpb/server/index.js +40 -12
  225. package/package.json +1 -1
@@ -1,4 +1,11 @@
1
1
  import path from 'node:path';
2
+ /**
3
+ * Tables — the FDE's raw material. CSV / TSV / JSONL / JSON (array of objects) become rows of
4
+ * cells. No Excel: the harness has no zip reader and takes no dependency for it — export a CSV.
5
+ */
6
+ const PLAIN_NUMBER = /^-?\d+(\.\d+)?$/;
7
+ /** A number written with thousands separators: `1,234,567.50`. */
8
+ const GROUPED_NUMBER = /^-?\d{1,3}(,\d{3})+(\.\d+)?$/;
2
9
  export function formatOf(file) {
3
10
  const ext = path.extname(file).toLowerCase();
4
11
  if (ext === '.csv')
@@ -57,7 +64,7 @@ function cellOf(raw) {
57
64
  const text = raw.trim();
58
65
  if (text === '')
59
66
  return null;
60
- if (/^-?\d+(\.\d+)?$/.test(text) || /^-?\d{1,3}(,\d{3})+(\.\d+)?$/.test(text))
67
+ if (PLAIN_NUMBER.test(text) || GROUPED_NUMBER.test(text))
61
68
  return Number(text.replace(/,/g, ''));
62
69
  if (text === 'true' || text === 'false')
63
70
  return text === 'true';
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/core/table.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAc7B,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7C,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACjC,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACjC,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC1D,IAAI,GAAG,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC;IACnC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sFAAsF;AACtF,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACnD,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,MAAM,GAAa,EAAE,CAAC;IAC1B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACpB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACtC,KAAK,IAAI,GAAG,CAAC;gBACb,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;iBAAM,IAAI,EAAE,KAAK,GAAG;gBAAE,MAAM,GAAG,KAAK,CAAC;;gBACjC,KAAK,IAAI,EAAE,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG;YAAE,MAAM,GAAG,IAAI,CAAC;aACzB,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,KAAK,GAAG,EAAE,CAAC;QACb,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACtC,IAAI,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI;gBAAE,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,GAAG,EAAE,CAAC;YACZ,KAAK,GAAG,EAAE,CAAC;QACb,CAAC;;YAAM,KAAK,IAAI,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,KAAK,KAAK,EAAE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,MAAM,CAAC,GAAW;IACzB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IACrH,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,KAAK,MAAM,CAAC;IAChE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,SAAiB,EAAE,MAAqB;IAC3E,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7G,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACvG,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,WAAW,CAAC,OAAkB,EAAE,MAAwB;IAC/D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAU,EAAE,CAAC;IACvB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/E,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9C,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,MAAuB;IAC9D,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7D,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9D,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7G,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IAC3C,OAAO,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/core/table.ts"],"names":[],"mappings":"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"}
@@ -3,14 +3,23 @@ import { vibePath } from './paths.js';
3
3
  import { appendJsonl, nowIso, readJsonl } from './store.js';
4
4
  export const TOKEN_TTL_MS = 10 * 60 * 1000;
5
5
  export const TOKEN_MAX_FAILURES = 3;
6
+ const TOKEN_DIGITS = 6;
7
+ /** The token is shown as `123 456`: this many digits, a space, the rest. */
8
+ const TOKEN_GROUP = 3;
9
+ const TOKENS_FILE = 'inbox.jsonl';
10
+ /** Domain prefix, so a token hash cannot be reused as another kind of hash. */
11
+ const TOKEN_HASH_PREFIX = 'vibe-token:';
12
+ const TARGET_HASH_LENGTH = 16;
13
+ /** Random suffix range of a token id, in base 36. */
14
+ const TOKEN_ID_RANDOM = 4096;
6
15
  export function tokensPath(root) {
7
- return vibePath(root, 'inbox.jsonl');
16
+ return vibePath(root, TOKENS_FILE);
8
17
  }
9
18
  export function hashToken(digits) {
10
- return createHash('sha256').update(`vibe-token:${digits}`).digest('hex');
19
+ return createHash('sha256').update(`${TOKEN_HASH_PREFIX}${digits}`).digest('hex');
11
20
  }
12
21
  export function hashTarget(value) {
13
- return createHash('sha256').update(value).digest('hex').slice(0, 16);
22
+ return createHash('sha256').update(value).digest('hex').slice(0, TARGET_HASH_LENGTH);
14
23
  }
15
24
  export function foldTokens(root) {
16
25
  const views = new Map();
@@ -32,29 +41,30 @@ export function foldTokens(root) {
32
41
  return views;
33
42
  }
34
43
  function formatDigits(digits) {
35
- return `${digits.slice(0, 3)} ${digits.slice(3)}`;
44
+ return `${digits.slice(0, TOKEN_GROUP)} ${digits.slice(TOKEN_GROUP)}`;
36
45
  }
37
46
  export function issueToken(root, kind, target) {
38
- const digits = String(randomInt(0, 1_000_000)).padStart(6, '0');
47
+ const digits = String(randomInt(0, 10 ** TOKEN_DIGITS)).padStart(TOKEN_DIGITS, '0');
39
48
  const issuedAt = nowIso();
40
49
  const expiresAt = new Date(Date.now() + TOKEN_TTL_MS).toISOString();
41
- const id = `t-${Date.now().toString(36)}-${randomInt(0, 4096).toString(36)}`;
50
+ const id = `t-${Date.now().toString(36)}-${randomInt(0, TOKEN_ID_RANDOM).toString(36)}`;
42
51
  const event = { type: 'token', id, kind, target, tokenHash: hashToken(digits), issuedAt, expiresAt };
43
52
  appendJsonl(tokensPath(root), event);
44
53
  return { id, token: formatDigits(digits), expiresAt };
45
54
  }
46
- /** Verify and consume once. Failures are recorded; three failures kill the token. */
55
+ /** Verify and consume once. Failures are recorded; `TOKEN_MAX_FAILURES` failures kill the token. */
47
56
  export function verifyAndConsume(root, kind, target, token, now = new Date()) {
48
57
  const digits = token.replace(/\D/g, '');
49
- if (digits.length !== 6)
58
+ if (digits.length !== TOKEN_DIGITS)
50
59
  return { ok: false, reason: 'a token is six digits' };
51
60
  const wanted = hashToken(digits);
52
- const candidates = [...foldTokens(root).values()].filter((view) => view.kind === kind && view.target === target && view.usedAt === null);
61
+ const unused = (view) => view.kind === kind && view.target === target && view.usedAt === null;
62
+ const candidates = [...foldTokens(root).values()].filter(unused);
53
63
  if (candidates.length === 0)
54
64
  return { ok: false, reason: `no ${kind} token was issued for this target — ask for a new one` };
55
65
  const live = candidates.filter((view) => view.failures < TOKEN_MAX_FAILURES && new Date(view.expiresAt).getTime() > now.getTime());
56
66
  if (live.length === 0)
57
- return { ok: false, reason: 'token expired or revoked after 3 failures — ask for a new one' };
67
+ return { ok: false, reason: `token expired or revoked after ${TOKEN_MAX_FAILURES} failures — ask for a new one` };
58
68
  const match = live.find((view) => view.tokenHash === wanted);
59
69
  if (!match) {
60
70
  for (const view of live)
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"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"}
package/dist/core/tree.js CHANGED
@@ -2,7 +2,17 @@ import { createHash } from 'node:crypto';
2
2
  import { spawnSync } from 'node:child_process';
3
3
  import fs from 'node:fs';
4
4
  import path from 'node:path';
5
- const SKIP_DIRS = new Set(['.git', 'node_modules', '.vibe', 'dist', '.claude', '.codex']);
5
+ import { CLAUDE_DIR, CODEX_DIR } from './locations.js';
6
+ import { VIBE_DIR } from './paths.js';
7
+ const SKIP_DIRS = new Set(['.git', 'node_modules', VIBE_DIR, 'dist', CLAUDE_DIR, CODEX_DIR]);
8
+ /** Hex characters of the tree hash kept as the fingerprint. */
9
+ const TREE_HASH_LENGTH = 16;
10
+ /** Changed files hashed by `changedBlobs` unless the caller asks for more. */
11
+ const DEFAULT_CHANGED_LIMIT = 200;
12
+ const DELETED = 'deleted';
13
+ /** `git status --porcelain` puts a two-letter status and a space before the path. */
14
+ const PORCELAIN_PATH_OFFSET = 3;
15
+ const inVibe = (file) => file.startsWith(`${VIBE_DIR}/`);
6
16
  function git(root, args) {
7
17
  const result = spawnSync('git', args, { cwd: root, encoding: 'utf-8' });
8
18
  return result.status === 0 ? result.stdout : null;
@@ -24,22 +34,26 @@ function walk(dir, rel, into) {
24
34
  }
25
35
  }
26
36
  }
37
+ /** Files git reports as changed or untracked, `.vibe/` excluded; null outside git. */
38
+ function changedFiles(root) {
39
+ const status = git(root, ['status', '--porcelain', '--untracked-files=all']);
40
+ if (status === null)
41
+ return null;
42
+ return status.split('\n').map((line) => line.slice(PORCELAIN_PATH_OFFSET).trim()).filter((file) => file && !inVibe(file));
43
+ }
27
44
  /** Changed or untracked files relative to HEAD with their content ids (`deleted` when gone), `.vibe/` excluded. Empty outside git. */
28
- export function changedBlobs(root, limit = 200) {
29
- const changed = git(root, ['status', '--porcelain', '--untracked-files=all']);
45
+ export function changedBlobs(root, limit = DEFAULT_CHANGED_LIMIT) {
46
+ const changed = changedFiles(root);
30
47
  const out = {};
31
48
  if (changed === null)
32
49
  return out;
33
50
  let n = 0;
34
- for (const line of changed.split('\n')) {
35
- const file = line.slice(3).trim();
36
- if (!file || file.startsWith('.vibe/'))
37
- continue;
51
+ for (const file of changed) {
38
52
  try {
39
53
  out[file] = blobId(fs.readFileSync(path.join(root, file)));
40
54
  }
41
55
  catch {
42
- out[file] = 'deleted';
56
+ out[file] = DELETED;
43
57
  }
44
58
  n += 1;
45
59
  if (n >= limit)
@@ -68,14 +82,10 @@ export function treeHash(root) {
68
82
  for (const line of tracked.split('\n')) {
69
83
  const [meta, file] = line.split('\t');
70
84
  const id = meta?.split(' ')[2];
71
- if (file && id && !file.startsWith('.vibe/'))
85
+ if (file && id && !inVibe(file))
72
86
  blobs.set(file, id);
73
87
  }
74
- const changed = git(root, ['status', '--porcelain', '--untracked-files=all']) ?? '';
75
- for (const line of changed.split('\n')) {
76
- const file = line.slice(3).trim();
77
- if (!file || file.startsWith('.vibe/'))
78
- continue;
88
+ for (const file of changedFiles(root) ?? []) {
79
89
  try {
80
90
  blobs.set(file, blobId(fs.readFileSync(path.join(root, file))));
81
91
  }
@@ -85,13 +95,13 @@ export function treeHash(root) {
85
95
  }
86
96
  for (const [file, id] of [...blobs.entries()].sort())
87
97
  hash.update(`${file}:${id}\n`);
88
- return hash.digest('hex').slice(0, 16);
98
+ return hash.digest('hex').slice(0, TREE_HASH_LENGTH);
89
99
  }
90
100
  const entries = [];
91
101
  walk(root, '', entries);
92
102
  entries.sort();
93
103
  for (const entry of entries)
94
104
  hash.update(entry);
95
- return hash.digest('hex').slice(0, 16);
105
+ return hash.digest('hex').slice(0, TREE_HASH_LENGTH);
96
106
  }
97
107
  //# sourceMappingURL=tree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/core/tree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/core/tree.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,24 @@ import { repairAwaitingInput } from './repair.js';
7
7
  import { requireRiskCoverage } from './risk-signals.js';
8
8
  import { ancestorsOf, isHuman } from './scenarios.js';
9
9
  import { readState } from './state.js';
10
+ /** States in which a plan can be executed; in any other there is no approved task to run. */
11
+ const EXECUTABLE_STATES = ['APPROVED', 'RUNNING', 'DONE', 'STUCK'];
12
+ const QUALITY_GUIDE = 'vibe internal guide verification';
13
+ const QUALITY_NEXT = [
14
+ 'For authored output, inspect affected code, prose or rendered UI against its guide before delivery.',
15
+ 'Record scope, findings and limits in the existing task note or summary.',
16
+ ].join(' ');
17
+ const QUALITY_LIMITS = [
18
+ 'Machine passes and DONE do not establish antislop quality.',
19
+ 'This preview neither performs nor reads an agent assessment; reuse requires unchanged output and criteria.',
20
+ ].join(' ');
21
+ const RETRY_NEXT = 'Inspect the existing failure evidence and identify changed input or a new hypothesis before retrying.';
22
+ const PLAN_LIMITS = [
23
+ 'Read-only snapshot, not DONE, permission or a promise of execution.',
24
+ 'Check revalidates before running; per-action authority and human/handoff waits still apply.',
25
+ 'External state, undeclared ignored inputs, host calls and host token costs are not observed.',
26
+ 'Explicitly rerun checks whose external inputs changed.',
27
+ ].join(' ');
10
28
  /** A read-only view of the existing selector, not a second verdict or execution receipt. */
11
29
  export function verificationPlan(root, options = {}) {
12
30
  const state = readState(root);
@@ -15,10 +33,11 @@ export function verificationPlan(root, options = {}) {
15
33
  const selected = new Set(selectScenarios(universe, previous, options).map(s => s.id));
16
34
  const blockers = [];
17
35
  const waiting = repairAwaitingInput(root, state.repair);
18
- if (!['APPROVED', 'RUNNING', 'DONE', 'STUCK'].includes(state.state))
36
+ if (!EXECUTABLE_STATES.includes(state.state))
19
37
  blockers.push(`task is ${state.state}; no approved execution`);
20
38
  else {
21
- for (const validate of [() => validateApproval(root, state), () => requireConsent(root), () => requireRiskCoverage(root, universe)]) {
39
+ const validations = [() => validateApproval(root, state), () => requireConsent(root), () => requireRiskCoverage(root, universe)];
40
+ for (const validate of validations) {
22
41
  try {
23
42
  validate();
24
43
  }
@@ -33,10 +52,10 @@ export function verificationPlan(root, options = {}) {
33
52
  const result = previous[s.id];
34
53
  const last = result?.last ?? 'never';
35
54
  const decision = blockers.length ? 'blocked' : selected.has(s.id) ? 'selected' : last === 'pass' ? 'reuse' : 'outside-selection';
36
- const reason = decision === 'reuse' ? 'recorded pass is fresh under existing tree, artifact and handoff rules'
55
+ const reason = decision === 'reuse' ? 'recorded pass is fresh: its inputs, artifacts and handoff are unchanged'
37
56
  : decision === 'blocked' ? 'resolve blockers before executing or treating recorded evidence as reusable'
38
57
  : decision === 'outside-selection' ? 'not requested; still required before completion'
39
- : options.all ? 'explicit full run' : options.ids?.includes(s.id) ? 'explicitly requested'
58
+ : options.fresh ? 'explicit full run' : options.ids?.includes(s.id) ? 'explicitly requested'
40
59
  : isHuman(s) ? 'human judgment; no automatic verdict' : `no reusable pass (${last})`;
41
60
  return { id: s.id, type: s.check.type, last, decision, selected: selected.has(s.id), reason,
42
61
  evidence: result?.run ? `${result.run}#${s.id}` : null,
@@ -44,13 +63,10 @@ export function verificationPlan(root, options = {}) {
44
63
  });
45
64
  return { root, recordedState: state.state, blockers, checks,
46
65
  qualityReview: { status: 'not-assessed', assessedBy: null,
47
- guide: 'vibe internal guide verification',
48
- next: 'For authored output, inspect affected code, prose or rendered UI against its guide before delivery. Record scope, findings and limits in the existing task note or summary.',
49
- limits: 'Machine passes and DONE do not establish antislop quality. This preview neither performs nor reads an agent assessment; reuse requires unchanged output and criteria.' },
66
+ guide: QUALITY_GUIDE, next: QUALITY_NEXT, limits: QUALITY_LIMITS },
50
67
  nextAction: blockers.length ? 'resolve-blockers' : checks.some(c => c.decision === 'selected') ? 'run-selected-checks' : 'inspect-completion-requirements',
51
68
  remaining: universe.filter(s => !isHuman(s) && previous[s.id]?.last !== 'pass').map(s => s.id),
52
- retry: state.repair ? { failures: state.failStreak, waiting,
53
- next: 'Inspect the existing failure evidence and identify changed input or a new hypothesis before retrying.' } : null,
54
- limits: 'Read-only snapshot, not DONE, permission or a promise of execution. Check revalidates before running; per-action authority and human/handoff waits still apply. External state, undeclared ignored inputs, host calls and host token costs are not observed. Explicitly rerun checks whose external inputs changed.' };
69
+ retry: state.repair ? { failures: state.failStreak, waiting, next: RETRY_NEXT } : null,
70
+ limits: PLAN_LIMITS };
55
71
  }
56
72
  //# sourceMappingURL=verification-plan.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verification-plan.js","sourceRoot":"","sources":["../../src/core/verification-plan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verification-plan.js","sourceRoot":"","sources":["../../src/core/verification-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAqB,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,6FAA6F;AAC7F,MAAM,iBAAiB,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACnE,MAAM,aAAa,GAAG,kCAAkC,CAAC;AACzD,MAAM,YAAY,GAAG;IACnB,qGAAqG;IACrG,yEAAyE;CAC1E,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACZ,MAAM,cAAc,GAAG;IACrB,4DAA4D;IAC5D,4GAA4G;CAC7G,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACZ,MAAM,UAAU,GAAG,uGAAuG,CAAC;AAC3H,MAAM,WAAW,GAAG;IAClB,qEAAqE;IACrE,6FAA6F;IAC7F,8FAA8F;IAC9F,wDAAwD;CACzD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,4FAA4F;AAC5F,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,UAAwB,EAAE;IACvE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3G,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,KAAK,yBAAyB,CAAC,CAAC;SACxG,CAAC;QACJ,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QACjI,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;YACnC,IAAI,CAAC;gBAAC,QAAQ,EAAE,CAAC;YAAC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC;YAAC,CAAC;QACzH,CAAC;QACD,IAAI,OAAO;YAAE,QAAQ,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC9B,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,OAAO,CAAC;QACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;QACjI,MAAM,MAAM,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,yEAAyE;YAC7G,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,6EAA6E;gBACxG,CAAC,CAAC,QAAQ,KAAK,mBAAmB,CAAC,CAAC,CAAC,iDAAiD;oBACtF,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,sBAAsB;wBAC5F,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,qBAAqB,IAAI,GAAG,CAAC;QACvF,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM;YACzF,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;YACtD,aAAa,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,KAAK,MAAM,CAAC,EAAE,CAAC;IAC/F,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM;QACzD,aAAa,EAAE,EAAE,MAAM,EAAE,cAAuB,EAAE,UAAU,EAAE,IAAI;YAChE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE;QACpE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,iCAAiC;QAC1J,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI;QACtF,MAAM,EAAE,WAAW,EAAE,CAAC;AAC1B,CAAC"}
@@ -1,4 +1,9 @@
1
+ /** Fields a declared risk may carry; any other is rejected. */
2
+ const RISK_FIELDS = new Set(['paths', 'kind', 'impact', 'recovery', 'failureChecks', 'recoveryChecks']);
1
3
  export const RISK_KINDS = ['data', 'access', 'interface', 'deployment', 'integration'];
4
+ function projectRelative(p) {
5
+ return typeof p === 'string' && p !== '' && !p.startsWith('/') && !p.includes('..') && !p.includes('\\') && p !== '.';
6
+ }
2
7
  /** Validate declared obligations; this does not infer domain risks from arbitrary source code. */
3
8
  export function riskReason(value) {
4
9
  if (!value || typeof value !== 'object' || Array.isArray(value))
@@ -12,21 +17,22 @@ export function riskReason(value) {
12
17
  }
13
18
  for (const key of ['failureChecks', 'recoveryChecks']) {
14
19
  const ids = risk[key];
15
- if (!Array.isArray(ids) || !ids.length || ids.some(id => typeof id !== 'string' || !id.trim()))
20
+ if (!Array.isArray(ids) || !ids.length || ids.some(id => typeof id !== 'string' || !id.trim())) {
16
21
  return `risk.${key} must name at least one scenario`;
22
+ }
17
23
  }
18
- if (risk['paths'] !== undefined && (!Array.isArray(risk['paths']) || risk['paths'].some(p => typeof p !== 'string' || !p || p.startsWith('/') || p.includes('..') || p.includes('\\') || p === '.')))
24
+ if (risk['paths'] !== undefined && (!Array.isArray(risk['paths']) || !risk['paths'].every(projectRelative))) {
19
25
  return 'risk.paths must contain project-relative files or directories';
20
- const allowed = new Set(['paths', 'kind', 'impact', 'recovery', 'failureChecks', 'recoveryChecks']);
21
- if (Object.keys(risk).some(key => !allowed.has(key)))
26
+ }
27
+ if (Object.keys(risk).some(key => !RISK_FIELDS.has(key)))
22
28
  return 'unknown risk field';
23
29
  return null;
24
30
  }
25
31
  function assertsContent(check) {
26
32
  if (check.exists === false)
27
33
  return false;
28
- return [check.pattern, check.contains, check.absent, check.traceable, check.schema].some(value => typeof value === 'string' && value.trim().length > 0)
29
- || check.a11y === true || check.sum !== undefined;
34
+ const rules = [check.pattern, check.contains, check.absent, check.traceable, check.schema];
35
+ return rules.some(value => typeof value === 'string' && value.trim().length > 0) || check.a11y === true || check.sum !== undefined;
30
36
  }
31
37
  /** Risk obligations use the existing dependency scheduler and verdict, not a second pipeline. */
32
38
  export function bindRiskChecks(scenarios, rejections) {
@@ -46,8 +52,9 @@ export function bindRiskChecks(scenarios, rejections) {
46
52
  if (id === scenario.id || target.check.type === 'human' || target.check.type === 'review') {
47
53
  rejections.push({ id: scenario.id, reason: `risk check ${id} must be a separate machine check` });
48
54
  }
49
- if (target.irreversible)
55
+ if (target.irreversible) {
50
56
  rejections.push({ id: scenario.id, reason: `risk check ${id} must use a local fixture or dry run, not an irreversible action` });
57
+ }
51
58
  if (target.check.type === 'file' && !assertsContent(target.check)) {
52
59
  rejections.push({ id: scenario.id, reason: `risk check ${id} must assert behavior or content, not only file existence` });
53
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/core/verification.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/core/verification.ts"],"names":[],"mappings":"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"}
package/dist/core/view.js CHANGED
@@ -16,9 +16,21 @@ import { readText } from './store.js';
16
16
  import { sourceValidity } from './source-basis.js';
17
17
  import path from 'node:path';
18
18
  import { recordReadTargets } from './read-guard.js';
19
+ import { RUN_PREFIX } from './run-id.js';
20
+ /** Files shown per scenario in the brief. */
21
+ const FILES_PER_SCENARIO = 8;
22
+ /** More scenarios than this is `full` work, not `small`. */
23
+ const SMALL_SCENARIO_MAX = 8;
24
+ const UNTITLED = '(untitled)';
25
+ const DISCOVER_NEXT = 'discover — the vibe-discover skill: inspect accessible evidence, resolve material unknowns, stop when agreement is sufficient';
26
+ const SCOPE_NEXT = 'approve — the vibe-scope skill: vibe intent analyze, confirm sufficient agreement, one approval message; wait for "yes"';
27
+ const REPORT_TAIL = [
28
+ 'answer the user from this output — what was built, which checks passed — reply in chat, not vibe ask;',
29
+ 'with no skill and no further reads; HANDOFF.md only if the intent asks',
30
+ ].join(' ');
19
31
  function sizeOf(scenarios) {
20
32
  const own = scenarios.filter((s) => !('regression' in s && s.regression));
21
- if (own.length > 8)
33
+ if (own.length > SMALL_SCENARIO_MAX)
22
34
  return 'full';
23
35
  if (own.some((s) => s.irreversible))
24
36
  return 'full';
@@ -46,7 +58,10 @@ function checkTarget(check) {
46
58
  }
47
59
  /** One scenario as the brief shows it: its check, and — while it has not passed — the files it is about. */
48
60
  function scenarioView(root, s, results) {
49
- const view = { id: s.id, then: s.then, type: s.check.type, last: results[s.id]?.last ?? 'never', at: results[s.id]?.at ?? null, check: checkTarget(s.check) };
61
+ const view = {
62
+ id: s.id, then: s.then, type: s.check.type, last: results[s.id]?.last ?? 'never', at: results[s.id]?.at ?? null,
63
+ check: checkTarget(s.check),
64
+ };
50
65
  const failure = results[s.id]?.failure;
51
66
  if (failure)
52
67
  view.failure = failure;
@@ -57,7 +72,8 @@ function scenarioView(root, s, results) {
57
72
  if (s.needs)
58
73
  view.needs = s.needs;
59
74
  if (view.last !== 'pass' && !isHuman(s)) {
60
- const files = [...new Set([...(view.failure?.locations.map((location) => location.file) ?? []), ...filesFor(root, s.check)])].slice(0, 8);
75
+ const located = view.failure?.locations.map((location) => location.file) ?? [];
76
+ const files = [...new Set([...located, ...filesFor(root, s.check)])].slice(0, FILES_PER_SCENARIO);
61
77
  if (files.length)
62
78
  view.files = files;
63
79
  }
@@ -66,15 +82,27 @@ function scenarioView(root, s, results) {
66
82
  function scenarioTargets(scenarios) {
67
83
  return scenarios.map((s) => `${s.id}${s.files?.length ? ` (files: ${s.files.join(', ')})` : ''}`).join(', ');
68
84
  }
85
+ /** What to do once a question is answered, by stage. */
86
+ function resumeAfterAnswer(state, stage, remaining) {
87
+ if (stage === 'discover')
88
+ return 'continue discovery with vibe-discover; use the answer to resolve material unknowns';
89
+ if (stage === 'scope')
90
+ return 'continue scope with vibe-scope; incorporate the answer, confirm sufficient agreement and request approval';
91
+ if (state === 'DONE')
92
+ return 'reply in chat, not vibe ask';
93
+ return remaining.length ? `continue building ${scenarioTargets(remaining)}; then vibe check --all` : 'then vibe check --all';
94
+ }
69
95
  /** Asking is a stop: an unanswered question means wait; an answered one carries its answer and lets the work continue. */
70
96
  function inboxLine(state, stage, items, remaining) {
71
97
  const waiting = items.filter((q) => !q.answer?.trim());
72
98
  const answered = items.filter((q) => q.answer?.trim());
73
- if (waiting.length > 0)
74
- return `${state === 'STUCK' ? 'STUCK — ' : 'wait — '}${waiting.map((q) => q.id).join(', ')} asked${remaining.some((s) => s.failure) ? ` — ${remaining.flatMap((s) => s.failure ? [failureLine(s.failure)] : []).join(' | ')}` : ''}; the user answers; stop and wait — do not answer it yourself`;
75
- const resume = stage === 'discover' ? 'continue discovery with vibe-discover; use the answer to resolve material unknowns'
76
- : stage === 'scope' ? 'continue scope with vibe-scope; incorporate the answer, confirm sufficient agreement and request approval'
77
- : state === 'DONE' ? 'reply in chat, not vibe ask' : remaining.length ? `continue building ${scenarioTargets(remaining)}; then vibe check --all` : 'then vibe check --all';
99
+ if (waiting.length > 0) {
100
+ const failures = remaining.flatMap((s) => s.failure ? [failureLine(s.failure)] : []);
101
+ const because = failures.length ? ` — ${failures.join(' | ')}` : '';
102
+ const prefix = state === 'STUCK' ? 'STUCK — ' : 'wait — ';
103
+ return `${prefix}${waiting.map((q) => q.id).join(', ')} asked${because}; the user answers; stop and wait — do not answer it yourself`;
104
+ }
105
+ const resume = resumeAfterAnswer(state, stage, remaining);
78
106
  if (answered.length > 0)
79
107
  return `answered ${answered.map((q) => `${q.id}: "${q.answer}"`).join(' · ')} — ${resume}; vibe inbox resolve <id> once used`;
80
108
  return null;
@@ -87,13 +115,15 @@ function nextLine(state, stage, pending, inbox, size, run, repair) {
87
115
  if (state === 'STUCK')
88
116
  return repairNext(repair);
89
117
  if (stage === 'discover')
90
- return 'discover — the vibe-discover skill: inspect accessible evidence, resolve material unknowns, stop when agreement is sufficient';
118
+ return DISCOVER_NEXT;
91
119
  if (stage === 'scope')
92
- return 'approve — the vibe-scope skill: vibe intent analyze, confirm sufficient agreement, one approval message; wait for "yes"';
93
- if (state === 'DONE')
94
- return `report — DONE r-${run}: answer the user from this output — what was built, which checks passed — reply in chat, not vibe ask; with no skill and no further reads; HANDOFF.md only if the intent asks`;
95
- if (isHandoffOnly(pending))
120
+ return SCOPE_NEXT;
121
+ if (state === 'DONE') {
122
+ return `report — DONE ${RUN_PREFIX}${run}: ${REPORT_TAIL}`;
123
+ }
124
+ if (isHandoffOnly(pending)) {
96
125
  return `handoff — required work remains unmet: ${scenarioTargets(pending)}; reopen a handed-off scenario explicitly before retrying`;
126
+ }
97
127
  if (remaining.length === 0)
98
128
  return 'check --all — nothing remaining; the verdict comes from vibe check';
99
129
  const failed = pending.filter((s) => s.last === 'fail');
@@ -106,28 +136,15 @@ function nextLine(state, stage, pending, inbox, size, run, repair) {
106
136
  function intentTitle(root) {
107
137
  const text = readText(intentPath(root)) ?? '';
108
138
  const heading = text.split('\n').find((line) => line.startsWith('#'));
109
- return heading ? heading.replace(/^#+\s*/, '').trim() : '(untitled)';
139
+ return heading ? heading.replace(/^#+\s*/, '').trim() : UNTITLED;
110
140
  }
111
- /** Every skill's first call. A DONE invalidated by edits falls back to RUNNING here. */
112
- export function buildStateView(root, cwd = process.cwd()) {
113
- const notices = [];
114
- if (path.resolve(cwd) !== path.resolve(root))
115
- notices.push(`project root is ${root} — above the current directory; records and run checks use that root`);
116
- if (invalidateDoneIfEdited(root))
117
- notices.push('files changed after DONE — state is RUNNING again; run `vibe check`');
118
- const state = readState(root);
119
- const results = readResults(root);
120
- const scenarios = loadScenarios(root);
121
- const regressions = listRegressions(root);
122
- const views = [...scenarios, ...regressions.map((r) => ({ ...r, regression: true }))].map((s) => scenarioView(root, s, results));
123
- const gated = views.filter((v) => v.type !== 'human');
124
- const pending = gated.filter((v) => v.last !== 'pass');
125
- const remaining = pending.map((v) => v.id);
126
- const allPassedOnce = gated.length > 0 && remaining.length === 0;
127
- const inbox = openQuestions(root), repairQuestion = pendingRepairQuestion(root, state.repair);
141
+ /** The questions as the brief lists them; a repair question the inbox does not hold yet joins it. */
142
+ function inboxItems(root, repair) {
143
+ const inbox = openQuestions(root);
144
+ const repairQuestion = pendingRepairQuestion(root, repair);
128
145
  if (repairQuestion && !inbox.some(q => q.id === repairQuestion.id))
129
146
  inbox.push(repairQuestion);
130
- const questions = inbox.map((q) => {
147
+ return inbox.map((q) => {
131
148
  const item = { id: q.id, question: q.question };
132
149
  if (q.answer)
133
150
  item.answer = q.answer;
@@ -141,23 +158,55 @@ export function buildStateView(root, cwd = process.cwd()) {
141
158
  item.needs = q.needs;
142
159
  return item;
143
160
  });
144
- const lastEvent = readLedger(root).at(-1);
145
- const intent = hasIntent(root) ? { title: intentTitle(root), hash: state.intentHash, approvedAt: state.approvedAt } : null;
146
- if (state.intentHash && !recordReadTargets(root, { intentHash: state.intentHash, files: views.flatMap(view => view.files ?? []) }))
147
- notices.push('read-target mirror unavailable; state remains available, intrinsic contract protection still applies');
161
+ }
162
+ const READ_MIRROR_NOTICE = 'read-target mirror unavailable; state remains available, intrinsic contract protection still applies';
163
+ const STUCK_WAITING_NOTICE = 'STUCK — repair limit reached; relay the question and its failure summary';
164
+ const STUCK_DIAGNOSE_NOTICE = 'STUCK — diagnose the failure and change the approach; ordinary repair needs no permission';
165
+ /** What the brief warns about once the state is read: the contract's sources, regression files, mutations, a stuck repair, human items. */
166
+ function recordNotices(root, state, scenarios, views) {
167
+ const notices = [];
168
+ const files = views.flatMap(view => view.files ?? []);
169
+ if (state.intentHash && !recordReadTargets(root, { intentHash: state.intentHash, files }))
170
+ notices.push(READ_MIRROR_NOTICE);
148
171
  const sources = sourceValidity(root);
149
- if (sources && !sources.valid)
150
- notices.push(`source basis changed or missing: ${[...sources.changed, ...sources.missing, ...sources.unreadable].join(', ')} — re-evaluate affected findings and redraft before approval`);
172
+ if (sources && !sources.valid) {
173
+ const named = [...sources.changed, ...sources.missing, ...sources.unreadable].join(', ');
174
+ notices.push(`source basis changed or missing: ${named} — re-evaluate affected findings and redraft before approval`);
175
+ }
151
176
  notices.push(...regressionProblems(root));
152
- for (const s of scenarios)
153
- if (s.irreversible)
154
- notices.push(`${s.id} mutates (${actionOf(s.irreversible)}) — not run by check --all without vibe authorize --action ${actionOf(s.irreversible)}`);
177
+ for (const s of scenarios) {
178
+ if (!s.irreversible)
179
+ continue;
180
+ const action = actionOf(s.irreversible);
181
+ notices.push(`${s.id} mutates (${action}) — not run by check --all without vibe authorize --action ${action}`);
182
+ }
155
183
  if (state.state === 'STUCK')
156
- notices.push(state.repair?.waiting ? 'STUCK — repair limit reached; relay the question and its failure summary' : 'STUCK — diagnose the failure and change the approach; ordinary repair needs no permission');
184
+ notices.push(state.repair?.waiting ? STUCK_WAITING_NOTICE : STUCK_DIAGNOSE_NOTICE);
157
185
  if (scenarios.some(isHuman) && state.state === 'DONE')
158
186
  notices.push('human items are not gates — a confirmation was requested in the inbox');
159
- const stage = stageOf(state, intent !== null, allPassedOnce);
160
- const size = sizeOf([...scenarios, ...regressions.map((r) => ({ ...r, regression: true }))]);
187
+ return notices;
188
+ }
189
+ /** Every skill's first call. A DONE invalidated by edits falls back to RUNNING here. */
190
+ export function buildStateView(root, cwd = process.cwd()) {
191
+ const notices = [];
192
+ if (path.resolve(cwd) !== path.resolve(root))
193
+ notices.push(`project root is ${root} — above the current directory; records and run checks use that root`);
194
+ if (invalidateDoneIfEdited(root))
195
+ notices.push('files changed after DONE — state is RUNNING again; run `vibe check`');
196
+ const state = readState(root);
197
+ const results = readResults(root);
198
+ const scenarios = loadScenarios(root);
199
+ const withRegressions = [...scenarios, ...listRegressions(root).map((r) => ({ ...r, regression: true }))];
200
+ const views = withRegressions.map((s) => scenarioView(root, s, results));
201
+ const gated = views.filter((v) => v.type !== 'human');
202
+ const pending = gated.filter((v) => v.last !== 'pass');
203
+ const remaining = pending.map((v) => v.id);
204
+ const questions = inboxItems(root, state.repair);
205
+ const lastEvent = readLedger(root).at(-1);
206
+ const intent = hasIntent(root) ? { title: intentTitle(root), hash: state.intentHash, approvedAt: state.approvedAt } : null;
207
+ notices.push(...recordNotices(root, state, scenarios, views));
208
+ const stage = stageOf(state, intent !== null, gated.length > 0 && remaining.length === 0);
209
+ const size = sizeOf(withRegressions);
161
210
  return {
162
211
  root,
163
212
  state: state.state,