@dzhechkov/harness-core 0.5.0 → 0.5.2

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 (96) hide show
  1. package/.dz-manifest.json +339 -75
  2. package/README.md +47 -4
  3. package/dist/codex-hooks-assets.d.ts.map +1 -1
  4. package/dist/codex-hooks-assets.js +39 -2
  5. package/dist/codex-hooks-assets.js.map +1 -1
  6. package/dist/codex-hooks-verify.d.ts +23 -2
  7. package/dist/codex-hooks-verify.d.ts.map +1 -1
  8. package/dist/codex-hooks-verify.js +29 -0
  9. package/dist/codex-hooks-verify.js.map +1 -1
  10. package/dist/codex-hooks.d.ts +90 -7
  11. package/dist/codex-hooks.d.ts.map +1 -1
  12. package/dist/codex-hooks.js +171 -21
  13. package/dist/codex-hooks.js.map +1 -1
  14. package/dist/feature-adr-routing.d.ts +22 -0
  15. package/dist/feature-adr-routing.d.ts.map +1 -1
  16. package/dist/feature-adr-routing.js +45 -0
  17. package/dist/feature-adr-routing.js.map +1 -1
  18. package/dist/index.d.ts +11 -4
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +17 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/loop-blobs.generated.d.ts +1 -1
  23. package/dist/loop-blobs.generated.d.ts.map +1 -1
  24. package/dist/loop-blobs.generated.js +12 -3
  25. package/dist/loop-blobs.generated.js.map +1 -1
  26. package/dist/loop-plan.d.ts +70 -0
  27. package/dist/loop-plan.d.ts.map +1 -1
  28. package/dist/loop-plan.js +103 -0
  29. package/dist/loop-plan.js.map +1 -1
  30. package/dist/loop-render.d.ts.map +1 -1
  31. package/dist/loop-render.js +38 -130
  32. package/dist/loop-render.js.map +1 -1
  33. package/dist/loop-run-semantics.d.ts +130 -0
  34. package/dist/loop-run-semantics.d.ts.map +1 -0
  35. package/dist/loop-run-semantics.js +257 -0
  36. package/dist/loop-run-semantics.js.map +1 -0
  37. package/dist/loop-trace.d.ts +106 -5
  38. package/dist/loop-trace.d.ts.map +1 -1
  39. package/dist/loop-trace.js +151 -18
  40. package/dist/loop-trace.js.map +1 -1
  41. package/dist/managed-hooks.d.ts +10 -0
  42. package/dist/managed-hooks.d.ts.map +1 -1
  43. package/dist/managed-hooks.js +17 -5
  44. package/dist/managed-hooks.js.map +1 -1
  45. package/dist/named-lock.d.ts +57 -0
  46. package/dist/named-lock.d.ts.map +1 -0
  47. package/dist/named-lock.js +247 -0
  48. package/dist/named-lock.js.map +1 -0
  49. package/dist/operations.d.ts +81 -5
  50. package/dist/operations.d.ts.map +1 -1
  51. package/dist/operations.js +356 -38
  52. package/dist/operations.js.map +1 -1
  53. package/dist/parity.d.ts +70 -2
  54. package/dist/parity.d.ts.map +1 -1
  55. package/dist/parity.js +133 -2
  56. package/dist/parity.js.map +1 -1
  57. package/dist/qe-bridge.d.ts +291 -0
  58. package/dist/qe-bridge.d.ts.map +1 -0
  59. package/dist/qe-bridge.js +538 -0
  60. package/dist/qe-bridge.js.map +1 -0
  61. package/dist/score.d.ts.map +1 -1
  62. package/dist/score.js +43 -9
  63. package/dist/score.js.map +1 -1
  64. package/dist/trace-corroborate.d.ts +48 -0
  65. package/dist/trace-corroborate.d.ts.map +1 -0
  66. package/dist/trace-corroborate.js +172 -0
  67. package/dist/trace-corroborate.js.map +1 -0
  68. package/dist/workflow-run-dispatch.d.ts +230 -0
  69. package/dist/workflow-run-dispatch.d.ts.map +1 -0
  70. package/dist/workflow-run-dispatch.js +363 -0
  71. package/dist/workflow-run-dispatch.js.map +1 -0
  72. package/dist/workflow-run.d.ts +513 -0
  73. package/dist/workflow-run.d.ts.map +1 -0
  74. package/dist/workflow-run.js +1377 -0
  75. package/dist/workflow-run.js.map +1 -0
  76. package/package.json +2 -2
  77. package/sbom.json +740 -80
  78. package/src/codex-hooks-assets.ts +39 -2
  79. package/src/codex-hooks-verify.ts +55 -2
  80. package/src/codex-hooks.ts +172 -20
  81. package/src/feature-adr-routing.ts +55 -0
  82. package/src/index.ts +46 -1
  83. package/src/loop-blobs.generated.ts +12 -3
  84. package/src/loop-plan.ts +185 -0
  85. package/src/loop-render.ts +38 -128
  86. package/src/loop-run-semantics.ts +278 -0
  87. package/src/loop-trace.ts +207 -16
  88. package/src/managed-hooks.ts +26 -5
  89. package/src/named-lock.ts +277 -0
  90. package/src/operations.ts +441 -40
  91. package/src/parity.ts +177 -2
  92. package/src/qe-bridge.ts +737 -0
  93. package/src/score.ts +50 -9
  94. package/src/trace-corroborate.ts +205 -0
  95. package/src/workflow-run-dispatch.ts +459 -0
  96. package/src/workflow-run.ts +1773 -0
package/dist/score.js CHANGED
@@ -39,8 +39,19 @@ function evidenceLine(text, re) {
39
39
  * heuristic table). A line whose match is preceded by a negation word is skipped. Heuristic — but
40
40
  * the failure mode flips from a silent false pass to a visible miss the shown evidence exposes.
41
41
  */
42
+ // The DEFAULT vocabulary — verbs and determiners that deny the sentence they sit in.
42
43
  const NEGATION_RE = /\b(no|not|never|without|wasn'?t|isn'?t)\b/i;
43
- function evidenceLinePositive(text, re) {
44
+ /**
45
+ * The default vocabulary plus the negative QUANTIFIERS. Opt-in per site, because a quantifier
46
+ * negates a NOUN, not the claim: "None of the mutants survived; discrimination §42 is proven by the
47
+ * red run" is idiomatic POSITIVE evidence that the wide list silently discarded (QE B-F2 —
48
+ * negating-the-mutants is not negating-the-proof). It is passed only where a red test demanded it:
49
+ * "Nothing was MEASURED in this round" scored as proof of measurement, because the word boundary in
50
+ * `\bno\b` does NOT match "Nothing". Hedges like "skipped" stay out of both lists — they routinely
51
+ * appear inside genuine evidence lines.
52
+ */
53
+ const NEGATION_QUANTIFIED_RE = /\b(no|not|never|without|nothing|none|neither|nor|nobody|wasn'?t|isn'?t)\b/i;
54
+ function evidenceLinePositive(text, re, negationRe = NEGATION_RE) {
44
55
  for (const line of text.split('\n')) {
45
56
  if (!re.test(line))
46
57
  continue;
@@ -48,7 +59,7 @@ function evidenceLinePositive(text, re) {
48
59
  // before-the-match check missed it. The trade is deliberate: a genuine line that happens to
49
60
  // contain a negation is SKIPPED (a visible miss the evidence exposes) rather than a negated
50
61
  // line being ACCEPTED (a silent false pass).
51
- if (NEGATION_RE.test(line))
62
+ if (negationRe.test(line))
52
63
  continue;
53
64
  return line.trim().slice(0, 140);
54
65
  }
@@ -77,10 +88,19 @@ export function scoreRun(slug, artifacts) {
77
88
  add('adr-confirmation', 'ADR present, property → named test', 'absent', 'no 03_adr/*.md artifact');
78
89
  }
79
90
  else {
80
- const conf = evidenceLine(adrText, /^##+\s*Confirmation/i);
81
- add('adr-confirmation', 'ADR present, property named test', conf !== null ? 'pass' : 'partial', conf ?? 'ADR exists but has no Confirmation section — the load-bearing property names no test');
91
+ // POSITIVE (QE B-F2 reversed my first call, which exempted this site as "structural"). The
92
+ // heading regex allows a SUFFIX, so `## Confirmation not yet performed` — the realistic
93
+ // placeholder an unfinished ADR carries — scored a full PASS. Heading presence is structural;
94
+ // heading TEXT is not, and this one can deny itself. Default (narrow) vocabulary: a heading is
95
+ // a fragment, and the quantifiers only appear in prose. Pinned both ways by tests.
96
+ const conf = evidenceLinePositive(adrText, /^##+\s*Confirmation/i);
97
+ add('adr-confirmation', 'ADR present, property → named test', conf !== null ? 'pass' : 'partial', conf ?? 'ADR exists but has no (non-negated) Confirmation heading — the load-bearing property names no test');
82
98
  }
83
99
  // 2. Discrimination — proof the test can FAIL (the §42 gate, or an explicit mutation proof).
100
+ // Default (narrow) vocabulary ON PURPOSE (QE B-F2): mutation evidence is written by negating the
101
+ // MUTANTS — "None of the mutants survived", "neither mutant escaped" — which is the proof, not
102
+ // its denial. The quantifiers would discard exactly the strongest lines this discipline exists
103
+ // to find. "No discrimination proof was performed" is still caught by the narrow list.
84
104
  const discr = evidenceLinePositive(allText, /discrimination|§42/i) ??
85
105
  evidenceLinePositive(allText, /mutation[s]?\s.*(prov|kill)|mutant[s]?\s.*(kill|red)|RED on the old|goes? RED|failed as expected/i);
86
106
  add('discrimination', 'the property test is proven able to fail', discr !== null ? 'pass' : 'absent', discr ?? 'no discrimination/§42/mutation-proof evidence in any artifact');
@@ -91,6 +111,13 @@ export function scoreRun(slug, artifacts) {
91
111
  }
92
112
  else {
93
113
  const crossLine = evidenceLinePositive(qeText, /codex|gpt-|cross-model/i);
114
+ // EXEMPT from the negation filter (wave1-scorer-negation, per-site review): this line is a
115
+ // DISPLAY LOCATOR, not a verdict input — the verdict above rests on `crossLine` (already
116
+ // positive-filtered) AND on `grade`, parsed from the whole report. A letter grade is a
117
+ // structural token ("Grade: D"); there is no idiomatic "no Grade: D". Filtering here would only
118
+ // drop the most common real grade line ("**Grade: B** — no blockers remain") from the shown
119
+ // evidence for zero change in verdict. Pinned by a test. Residual, flagged not hidden:
120
+ // `extractQeGrade` itself is negation-blind and stays so — out of FR-B1's scope.
94
121
  const gradeLine = grade !== null ? evidenceLine(qeText, GRADE_RE) : null;
95
122
  add('cross-model-qe', 'independent cross-model review with a grade', crossLine !== null && grade !== null ? 'pass' : 'partial', crossLine !== null
96
123
  ? grade !== null
@@ -100,15 +127,22 @@ export function scoreRun(slug, artifacts) {
100
127
  }
101
128
  // 4. Live verification — the property was observed, not inferred. The health-advisor 1.2.0 QE
102
129
  // report is the cautionary case: "✅ (mechanism)" with no live evidence shipped a dead feature.
103
- const live = evidenceLine(qeText, /MEASURED|verified live|VERIFIED LIVE|reproducer/i);
104
- const liveAnywhere = live ?? evidenceLine(allText, /MEASURED|verified live|VERIFIED LIVE|reproducer/i);
130
+ // POSITIVE (wave1-scorer-negation): "nothing was MEASURED" / "no reproducer was run" is the
131
+ // claim's exact opposite and used to score as proof of it (the crossrt-1 6/7 shape).
132
+ const live = evidenceLinePositive(qeText, /MEASURED|verified live|VERIFIED LIVE|reproducer/i, NEGATION_QUANTIFIED_RE);
133
+ const liveAnywhere = live ?? evidenceLinePositive(allText, /MEASURED|verified live|VERIFIED LIVE|reproducer/i, NEGATION_QUANTIFIED_RE);
105
134
  add('live-verification', 'claims verified by running, not by reasoning', live !== null ? 'pass' : liveAnywhere !== null ? 'partial' : 'absent', live ?? liveAnywhere ?? 'no MEASURED / verified-live / reproducer marker anywhere — every claim is inferred');
106
135
  // 5. README-first — the docs travelled in the same change.
107
- const readme = evidenceLine(qeText + '\n' + manifestText, /README/);
136
+ // POSITIVE (wave1-scorer-negation): THE acid-A5 defect. crossrt-1-agents-md scored here over
137
+ // its own finding "README-first not satisfied — no README was touched": a negation rendered as
138
+ // a checkmark. A README mention is not a README update.
139
+ const readme = evidenceLinePositive(qeText + '\n' + manifestText, /README/, NEGATION_QUANTIFIED_RE);
108
140
  add('readme-first', 'READMEs updated in the same change', readme !== null ? 'pass' : 'absent', readme ?? 'no README mention in the QE report or the change manifest');
109
141
  // 6. The learning loop — Step-0 recall folded in, Step-8 lessons taught.
110
- const recalled = evidenceLine(complexityText + '\n' + allText, /LEARNED_PATTERNS|dz recall|recalled/i);
111
- const taught = evidenceLine(allText, /lesson[s]? taught|dz teach|taught \(/i);
142
+ // POSITIVE both halves (wave1-scorer-negation): "recall was not performed" and "no lessons were
143
+ // taught (dz teach skipped)" both matched the plain regexes and scored the loop as RUN.
144
+ const recalled = evidenceLinePositive(complexityText + '\n' + allText, /LEARNED_PATTERNS|dz recall|recalled/i, NEGATION_QUANTIFIED_RE);
145
+ const taught = evidenceLinePositive(allText, /lesson[s]? taught|dz teach|taught \(/i, NEGATION_QUANTIFIED_RE);
112
146
  add('learning-loop', 'Step-0 recall used; Step-8 lessons taught', recalled !== null && taught !== null ? 'pass' : recalled !== null || taught !== null ? 'partial' : 'absent', recalled !== null && taught !== null
113
147
  ? `${recalled.slice(0, 68)} | ${taught.slice(0, 68)}`
114
148
  : recalled ?? taught ?? 'no recall/teach evidence — the run neither drew on nor fed the learned store');
package/dist/score.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"score.js","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"score.js","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAyBH,SAAS,OAAO,CAAC,SAAuB,EAAE,SAAoC;IAC5E,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;SAC7B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;SACvB,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,4EAA4E;AAC5E,SAAS,YAAY,CAAC,IAAY,EAAE,EAAU;IAC5C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,qFAAqF;AACrF,MAAM,WAAW,GAAG,4CAA4C,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,sBAAsB,GAAG,4EAA4E,CAAC;AAE5G,SAAS,oBAAoB,CAAC,IAAY,EAAE,EAAU,EAAE,aAAqB,WAAW;IACtF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,uFAAuF;QACvF,4FAA4F;QAC5F,4FAA4F;QAC5F,6CAA6C;QAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QACpC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iGAAiG;AACjG,6FAA6F;AAC7F,MAAM,QAAQ,GAAG,oEAAoE,CAAC;AAEtF,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,SAAuB;IAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,iBAAiB,IAAI,CAAC,KAAK,2BAA2B,CAAC,CAAC;IACvG,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,2BAA2B,IAAI,CAAC,KAAK,yBAAyB,CAAC,CAAC;IACjH,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,6BAA6B,CAAC,CAAC;IACtF,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAsB,EAAE,CAAC;IAC1C,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,KAAa,EAAE,OAA0B,EAAE,QAAgB,EAAQ,EAAE;QAC5F,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC;IAEF,4FAA4F;IAC5F,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,GAAG,CAAC,kBAAkB,EAAE,oCAAoC,EAAE,QAAQ,EAAE,yBAAyB,CAAC,CAAC;IACrG,CAAC;SAAM,CAAC;QACN,2FAA2F;QAC3F,0FAA0F;QAC1F,8FAA8F;QAC9F,+FAA+F;QAC/F,mFAAmF;QACnF,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;QACnE,GAAG,CACD,kBAAkB,EAClB,oCAAoC,EACpC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAClC,IAAI,IAAI,oGAAoG,CAC7G,CAAC;IACJ,CAAC;IAED,6FAA6F;IAC7F,oGAAoG;IACpG,kGAAkG;IAClG,kGAAkG;IAClG,0FAA0F;IAC1F,MAAM,KAAK,GACT,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,CAAC;QACpD,oBAAoB,CAAC,OAAO,EAAE,mGAAmG,CAAC,CAAC;IACrI,GAAG,CACD,gBAAgB,EAChB,0CAA0C,EAC1C,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAClC,KAAK,IAAI,+DAA+D,CACzE,CAAC;IAEF,6EAA6E;IAC7E,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,GAAG,CAAC,gBAAgB,EAAE,6CAA6C,EAAE,QAAQ,EAAE,6BAA6B,CAAC,CAAC;IAChH,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;QAC1E,2FAA2F;QAC3F,yFAAyF;QACzF,uFAAuF;QACvF,gGAAgG;QAChG,4FAA4F;QAC5F,uFAAuF;QACvF,iFAAiF;QACjF,MAAM,SAAS,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,GAAG,CACD,gBAAgB,EAChB,6CAA6C,EAC7C,SAAS,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACzD,SAAS,KAAK,IAAI;YAChB,CAAC,CAAC,KAAK,KAAK,IAAI;gBACd,CAAC,CAAC,GAAG,SAAS,GAAG,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBACvG,CAAC,CAAC,GAAG,SAAS,2BAA2B,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;YACzD,CAAC,CAAC,wFAAwF,CAC7F,CAAC;IACJ,CAAC;IAED,8FAA8F;IAC9F,kGAAkG;IAClG,+FAA+F;IAC/F,wFAAwF;IACxF,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,EAAE,kDAAkD,EAAE,sBAAsB,CAAC,CAAC;IACtH,MAAM,YAAY,GAChB,IAAI,IAAI,oBAAoB,CAAC,OAAO,EAAE,kDAAkD,EAAE,sBAAsB,CAAC,CAAC;IACpH,GAAG,CACD,mBAAmB,EACnB,8CAA8C,EAC9C,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EACrE,IAAI,IAAI,YAAY,IAAI,oFAAoF,CAC7G,CAAC;IAEF,2DAA2D;IAC3D,kGAAkG;IAClG,kGAAkG;IAClG,2DAA2D;IAC3D,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,GAAG,IAAI,GAAG,YAAY,EAAE,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IACpG,GAAG,CACD,cAAc,EACd,oCAAoC,EACpC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EACnC,MAAM,IAAI,2DAA2D,CACtE,CAAC;IAEF,yEAAyE;IACzE,mGAAmG;IACnG,2FAA2F;IAC3F,MAAM,QAAQ,GAAG,oBAAoB,CACnC,cAAc,GAAG,IAAI,GAAG,OAAO,EAC/B,sCAAsC,EACtC,sBAAsB,CACvB,CAAC;IACF,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,EAAE,uCAAuC,EAAE,sBAAsB,CAAC,CAAC;IAC9G,GAAG,CACD,eAAe,EACf,2CAA2C,EAC3C,QAAQ,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAC3G,QAAQ,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;QAClC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;QACrD,CAAC,CAAC,QAAQ,IAAI,MAAM,IAAI,8EAA8E,CACzG,CAAC;IAEF,0FAA0F;IAC1F,8FAA8F;IAC9F,6EAA6E;IAC7E,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,wFAAwF;QACxF,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,GAAG,CACD,wBAAwB,EACxB,8CAA8C,EAC9C,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC1E,OAAO,CAAC,MAAM,KAAK,CAAC;YAClB,CAAC,CAAC,oCAAoC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC5D,CAAC,CAAC,WAAW,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IACtE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjF,MAAM,OAAO,GACX,GAAG,MAAM,IAAI,KAAK,8BAA8B;QAChD,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC5D,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE7D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACvE,CAAC;AAED,MAAM,IAAI,GAAsC,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEzF,MAAM,UAAU,eAAe,CAAC,IAAkB;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,sDAAsD,CAAC,CAAC;IACxF,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `trace-corroborate` — the Claude host's OWN records, for the half of a trace they can witness.
3
+ *
4
+ * ADR-002. Pure over already-read strings: no `fs`, so it is testable with fixtures alone.
5
+ *
6
+ * The design is shaped by one MEASURED fact and one refuted design. The fact: the trace and the
7
+ * host's `journal.jsonl` share NO identifier — trace dispatch events carry `invocationId` /
8
+ * `stepId`, the journal carries `agentId` and a `v2:<sha>` key. There is no run nonce to bind them
9
+ * with, and we do not control the host's format, so DIRECTORY CONTAINMENT is the only binding
10
+ * available and every result says so. The refuted design: a bare `agrees` over "agent set +
11
+ * wall-clock order", which a cross-family reviewer defeated with a trace that matched on agents
12
+ * while inventing a join, a gate redo, a typed pause and a file deliverable — every consequential
13
+ * claim fabricated, the verdict green. Hence `agreesWithinScope`, and hence `notWitnessed` being
14
+ * non-empty BY TYPE rather than by discipline.
15
+ */
16
+ /** Non-empty by construction: a tuple type, so no edit can empty it and silently unscope a result. */
17
+ export type NotWitnessed = readonly ['join', 'gate-redo', 'typed-pause', 'file-deliverable'];
18
+ export declare const NOT_WITNESSED: NotWitnessed;
19
+ export type WitnessedClaim = 'agent-multiset' | 'agent-count' | 'wall-clock-order';
20
+ export declare const WITNESSED: readonly WitnessedClaim[];
21
+ /** Deliberately NOT `agrees`. The scope lives in the word, so a stored verdict carries it too. */
22
+ export type CorroborationVerdict = 'agreesWithinScope' | 'disagrees' | 'inconclusive';
23
+ export interface CorroborationResult {
24
+ verdict: CorroborationVerdict;
25
+ /** The ONLY binding available — see the module note. Never omitted. */
26
+ binding: 'by-directory';
27
+ hostDir: string;
28
+ witnessed: readonly WitnessedClaim[];
29
+ notWitnessed: NotWitnessed;
30
+ /** Why, in words, for the human-readable report. */
31
+ detail: string;
32
+ /** Counts, so a caller can render the disagreement rather than re-deriving it. */
33
+ traceAgentCount: number;
34
+ hostAgentCount: number;
35
+ }
36
+ /** One host record set, already read from disk by the caller. */
37
+ export interface HostRecords {
38
+ /** Raw `journal.jsonl` text, or null when the file is absent/unreadable. */
39
+ journal: string | null;
40
+ /** Raw `agent-<id>.jsonl` texts, keyed by agent id. Empty when none were found. */
41
+ agentTranscripts: Record<string, string>;
42
+ }
43
+ /** The trace side, projected by the caller: the agent ids the trace claims took part, in order. */
44
+ export interface TraceAgentProjection {
45
+ agentIds: string[];
46
+ }
47
+ export declare function corroborate(trace: TraceAgentProjection, host: HostRecords, hostDir: string): CorroborationResult;
48
+ //# sourceMappingURL=trace-corroborate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-corroborate.d.ts","sourceRoot":"","sources":["../src/trace-corroborate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,sGAAsG;AACtG,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,kBAAkB,CAAC,CAAC;AAC7F,eAAO,MAAM,aAAa,EAAE,YAAgF,CAAC;AAE7G,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,aAAa,GAAG,kBAAkB,CAAC;AACnF,eAAO,MAAM,SAAS,EAAE,SAAS,cAAc,EAAmE,CAAC;AAEnH,kGAAkG;AAClG,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,WAAW,GAAG,cAAc,CAAC;AAEtF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,uEAAuE;IACvE,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,YAAY,EAAE,YAAY,CAAC;IAC3B,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mFAAmF;IACnF,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,mGAAmG;AACnG,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA+ED,wBAAgB,WAAW,CAAC,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CA0EhH"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * `trace-corroborate` — the Claude host's OWN records, for the half of a trace they can witness.
3
+ *
4
+ * ADR-002. Pure over already-read strings: no `fs`, so it is testable with fixtures alone.
5
+ *
6
+ * The design is shaped by one MEASURED fact and one refuted design. The fact: the trace and the
7
+ * host's `journal.jsonl` share NO identifier — trace dispatch events carry `invocationId` /
8
+ * `stepId`, the journal carries `agentId` and a `v2:<sha>` key. There is no run nonce to bind them
9
+ * with, and we do not control the host's format, so DIRECTORY CONTAINMENT is the only binding
10
+ * available and every result says so. The refuted design: a bare `agrees` over "agent set +
11
+ * wall-clock order", which a cross-family reviewer defeated with a trace that matched on agents
12
+ * while inventing a join, a gate redo, a typed pause and a file deliverable — every consequential
13
+ * claim fabricated, the verdict green. Hence `agreesWithinScope`, and hence `notWitnessed` being
14
+ * non-empty BY TYPE rather than by discipline.
15
+ */
16
+ export const NOT_WITNESSED = ['join', 'gate-redo', 'typed-pause', 'file-deliverable'];
17
+ export const WITNESSED = ['agent-multiset', 'agent-count', 'wall-clock-order'];
18
+ /**
19
+ * Read the agent ids the host journal STARTED, or null when the journal cannot be trusted to be
20
+ * complete. QE round 1 closed three ways this used to lie:
21
+ * H4 — a `started` row whose `agentId` is not a string was silently DROPPED, so a malformed row
22
+ * that may well represent a real extra agent made the sets look equal.
23
+ * M2 — a non-empty journal with zero usable start rows returned `[]`, and an empty trace then
24
+ * "agreed" with it. A journal that records no starts is not evidence that none happened.
25
+ * M3 — `JSON.parse('null')` is valid JSON, and indexing the result threw.
26
+ */
27
+ function journalAgentIds(journal) {
28
+ const ids = [];
29
+ let sawAny = false;
30
+ for (const line of journal.split('\n')) {
31
+ const t = line.trim();
32
+ if (t === '')
33
+ continue;
34
+ sawAny = true;
35
+ let o;
36
+ try {
37
+ o = JSON.parse(t);
38
+ }
39
+ catch {
40
+ // A malformed journal is INCONCLUSIVE, not "the agents we could still parse". A partially
41
+ // readable independent record is not an independent record.
42
+ return null;
43
+ }
44
+ // M3: `null`, a number and a string are all valid JSON and none of them are records.
45
+ if (typeof o !== 'object' || o === null || Array.isArray(o))
46
+ return null;
47
+ const rec = o;
48
+ if (rec['type'] !== 'started')
49
+ continue;
50
+ // H4: a start row we cannot read is a start row we cannot account for.
51
+ if (typeof rec['agentId'] !== 'string' || rec['agentId'] === '')
52
+ return null;
53
+ ids.push(rec['agentId']);
54
+ }
55
+ // M2: a non-empty journal that yielded no starts tells us nothing about how many agents ran.
56
+ if (!sawAny || ids.length === 0)
57
+ return null;
58
+ return ids;
59
+ }
60
+ /**
61
+ * The FIRST readable timestamp in a transcript, or null when the answer cannot be trusted.
62
+ *
63
+ * QE round 1 / M1: this used to skip unparseable lines and keep scanning. But an unparseable line
64
+ * EARLIER in the file may carry an earlier timestamp — so a corrupt prefix does not just cost us a
65
+ * line, it invalidates the whole "first" claim. Returning the next readable stamp presents a
66
+ * possibly-late time as the earliest one, which is exactly how a wrong order reads as right.
67
+ */
68
+ function firstTimestamp(text) {
69
+ for (const line of text.split('\n')) {
70
+ const t = line.trim();
71
+ if (t === '')
72
+ continue;
73
+ let o;
74
+ try {
75
+ o = JSON.parse(t);
76
+ }
77
+ catch {
78
+ return null; // a corrupt line before any stamp ⇒ the earliest is unknowable
79
+ }
80
+ if (typeof o !== 'object' || o === null || Array.isArray(o))
81
+ return null;
82
+ const ts = o['timestamp'];
83
+ if (typeof ts === 'string') {
84
+ const ms = Date.parse(ts);
85
+ if (Number.isFinite(ms))
86
+ return ms;
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+ function multisetEqual(a, b) {
92
+ if (a.length !== b.length)
93
+ return false;
94
+ const count = new Map();
95
+ for (const x of a)
96
+ count.set(x, (count.get(x) ?? 0) + 1);
97
+ for (const x of b) {
98
+ const n = count.get(x);
99
+ if (n === undefined || n === 0)
100
+ return false;
101
+ count.set(x, n - 1);
102
+ }
103
+ return true;
104
+ }
105
+ export function corroborate(trace, host, hostDir) {
106
+ const base = {
107
+ binding: 'by-directory',
108
+ hostDir,
109
+ witnessed: WITNESSED,
110
+ notWitnessed: NOT_WITNESSED,
111
+ traceAgentCount: trace.agentIds.length,
112
+ };
113
+ if (host.journal === null) {
114
+ return { ...base, verdict: 'inconclusive', hostAgentCount: 0, detail: 'no host journal at ' + hostDir + ' — absent evidence is never agreement' };
115
+ }
116
+ const hostIds = journalAgentIds(host.journal);
117
+ if (hostIds === null) {
118
+ return { ...base, verdict: 'inconclusive', hostAgentCount: 0, detail: 'the host journal is empty or malformed — a partially readable record is not an independent one' };
119
+ }
120
+ // COUNT and MULTISET before ordering: a mismatch here is a real disagreement, and comparing the
121
+ // order of two different sets would be meaningless anyway.
122
+ if (!multisetEqual(trace.agentIds, hostIds)) {
123
+ return {
124
+ ...base,
125
+ verdict: 'disagrees',
126
+ hostAgentCount: hostIds.length,
127
+ detail: `the trace claims ${trace.agentIds.length} agent run(s), the host journal records ${hostIds.length}` +
128
+ (trace.agentIds.length === hostIds.length ? ' — same count, different ids' : ''),
129
+ };
130
+ }
131
+ // Wall-clock order, from the per-agent transcripts (the journal carries no ts). An agent with no
132
+ // readable timestamp makes the ORDER unwitnessable — inconclusive, not a pass on the rest.
133
+ //
134
+ // QE round 1 / M4: `host.agentTranscripts[id]` walks the PROTOTYPE, so an agent literally named
135
+ // `__proto__` (or `constructor`, `toString`, …) read a function off Object.prototype and threw.
136
+ // An own-property check is the fix; the id is data from an outside file and must be treated as such.
137
+ const own = (o, k) => Object.prototype.hasOwnProperty.call(o, k) ? o[k] : undefined;
138
+ const stamps = [];
139
+ for (const id of hostIds) {
140
+ const text = own(host.agentTranscripts, id);
141
+ const at = typeof text !== 'string' ? null : firstTimestamp(text);
142
+ if (at === null) {
143
+ return { ...base, verdict: 'inconclusive', hostAgentCount: hostIds.length, detail: `no readable timestamp for agent ${id} — the wall-clock order cannot be witnessed` };
144
+ }
145
+ stamps.push({ id, at });
146
+ }
147
+ // QE round 1 / H3: two agents sharing a timestamp make their relative order UNKNOWABLE. A stable
148
+ // sort preserved the journal's own order and reported agreement — the sort's tie-breaking rule
149
+ // was silently doing duty as evidence.
150
+ const sorted = [...stamps].sort((a, b) => a.at - b.at);
151
+ for (let i = 1; i < sorted.length; i++) {
152
+ if (sorted[i].at === sorted[i - 1].at) {
153
+ return { ...base, verdict: 'inconclusive', hostAgentCount: hostIds.length, detail: `agents ${sorted[i - 1].id} and ${sorted[i].id} share a timestamp — their relative order cannot be witnessed` };
154
+ }
155
+ }
156
+ // QE round 1 / H2: compare ELEMENT-WISE. `join('|')` collapsed ['x','x|x'] and ['x|x','x'] to the
157
+ // same string, so a reversed order read as agreement — a delimiter chosen for display doing duty
158
+ // as an equality operator.
159
+ const byClock = sorted.map((sv) => sv.id);
160
+ const orderMatches = byClock.length === trace.agentIds.length && byClock.every((id, i) => id === trace.agentIds[i]);
161
+ if (!orderMatches) {
162
+ return { ...base, verdict: 'disagrees', hostAgentCount: hostIds.length, detail: 'the host wall-clock order of the agents differs from the order the trace claims' };
163
+ }
164
+ return {
165
+ ...base,
166
+ verdict: 'agreesWithinScope',
167
+ hostAgentCount: hostIds.length,
168
+ detail: 'the host records agree on which agents ran and in what order. They CANNOT witness ' +
169
+ NOT_WITNESSED.join(', ') + ' — a fabricated one of those would still land here, which is why this is never a bare "agrees"',
170
+ };
171
+ }
172
+ //# sourceMappingURL=trace-corroborate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-corroborate.js","sourceRoot":"","sources":["../src/trace-corroborate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * `workflow-run-dispatch` — the DISPATCHER SEAM of `dz workflow run` (ADR-002 O1).
3
+ *
4
+ * Why a seam at all: the two runtimes disagree about almost everything that matters (stdin open vs
5
+ * closed, envelope shape, where a deliverable appears, what a clean exit means), and the scheduler
6
+ * must not know any of it. What it knows is: ask for a dispatch, get back a typed outcome whose
7
+ * failure reason is a member of ONE list.
8
+ *
9
+ * Everything below the contract is CONVENTION — and every convention here is a MEASURED lesson, not
10
+ * a preference. Each one is named at its definition with the observation that produced it, because
11
+ * a convention whose reason is lost is the next thing somebody "cleans up".
12
+ */
13
+ import type { Deliverable } from './loop-plan.js';
14
+ import { type BridgeFamily } from './qe-bridge.js';
15
+ import type { WfRunReason } from './workflow-run.js';
16
+ /** The dispatch REQUEST — every field resolved by the scheduler, so an adapter never re-decides. */
17
+ export interface DispatchRequest {
18
+ stepId: string;
19
+ /** The fanout member key, or null for a top-level step. */
20
+ itemKey: string | null;
21
+ /** 1-based; INCLUDES the initial attempt. */
22
+ attempt: number;
23
+ /** Fully assembled (USER prompt + shared contract lines + item binding), ingress-defanged. */
24
+ prompt: string;
25
+ /** Resolved at preflight (AM-8) — TOTAL, never inferred inside the adapter. */
26
+ family: BridgeFamily;
27
+ /** The PROBED id, never the requested spec: an allowlist says a name is spellable, only a probe
28
+ * says it answers. */
29
+ resolvedModelId: string;
30
+ deliverable: Deliverable;
31
+ /** Declared reads — the input paths a file-mode step is asked to OPEN. They travel so the adapter
32
+ * (and the scheduler's dispatch-time containment re-check) can hold them to the SAME realpath /
33
+ * symlinked-ancestor discipline as writes: a read that escapes the root is not safer than a write
34
+ * that does (Step-8 re-QE R3-A). */
35
+ expectedReads: string[];
36
+ /** Declared writes. The scheduler owns the landed barrier (it snapshots the baseline); the
37
+ * adapter only needs to know the step is in file mode. */
38
+ expectedWrites: string[];
39
+ timeoutMs: number;
40
+ /** Target tree for file mode; ignored by a return-value claude dispatch (isolated temp cwd). */
41
+ cwd: string;
42
+ }
43
+ export interface DispatchFailure {
44
+ reason: WfRunReason;
45
+ detail: string;
46
+ }
47
+ export interface DispatchResult {
48
+ /** Pinned to the trace settle vocabulary (`loop-trace.ts` settle outcomes) — one word, two planes. */
49
+ outcome: 'ok' | 'null' | 'error';
50
+ /** Envelope-extracted text; null on null/error. */
51
+ text: string | null;
52
+ family: BridgeFamily;
53
+ modelUsed: string | null;
54
+ wallMs: number;
55
+ /** null when the runtime did not report a count — NEVER 0, never estimated (ADR-004 C4). */
56
+ tokensIn: number | null;
57
+ tokensOut: number | null;
58
+ tokensSource: 'claude-envelope' | 'codex-stderr' | null;
59
+ failure?: DispatchFailure;
60
+ }
61
+ export interface ProbeOutcome {
62
+ /** The id that ANSWERED, or null when no candidate did. */
63
+ id: string | null;
64
+ wallMs: number;
65
+ detail: string;
66
+ }
67
+ export interface Dispatcher {
68
+ /** Once per run per family; the result is cached by the SCHEDULER and persisted into run-state
69
+ * (AM-8), so a resume compares against the id that actually ran. */
70
+ probe(candidates: string[]): Promise<ProbeOutcome>;
71
+ dispatch(req: DispatchRequest): Promise<DispatchResult>;
72
+ }
73
+ /**
74
+ * The 4 reasons an ADAPTER may produce — the producer PARTITION of the one 22-member
75
+ * `WF_RUN_REASONS` list (K3). There is no second taxonomy: the type stays `WfRunReason`, and this
76
+ * array is the data a test uses to assert who is allowed to produce what. The other 18 members have
77
+ * preflight, scheduler or state-plane producers.
78
+ */
79
+ export declare const DISPATCH_REASONS: readonly ["dispatch-timeout", "dispatch-dead", "prompt-over-ceiling", "probe-failed"];
80
+ export type DispatchReason = (typeof DISPATCH_REASONS)[number];
81
+ /** Measured 2026-08-12: a codex `exec` at xhigh effort needs this much wall clock at the far end of
82
+ * its distribution. Used as the scheduler's DEFAULT per-stage timeout when the operator gives none. */
83
+ export declare const CODEX_EXEC_XHIGH_TIMEOUT_MS = 560000;
84
+ export interface ChildRun {
85
+ stdout: string;
86
+ stderr: string;
87
+ exitCode: number | null;
88
+ timedOut: boolean;
89
+ spawnError: string | null;
90
+ }
91
+ export type ChildRunner = (bin: string, argv: string[], opts: {
92
+ stdinText: string | null;
93
+ timeoutMs: number;
94
+ cwd: string;
95
+ detached: boolean;
96
+ }) => Promise<ChildRun>;
97
+ /**
98
+ * W1 — the timeout/dead discriminator, decided on the WRAPPER'S OWN FIELDS and nothing else.
99
+ *
100
+ * The distinction is load-bearing because the two have different retry semantics and different
101
+ * operator meanings: a timeout says "it was still working", a dead dispatch says "nothing came
102
+ * back". Deciding it from stderr text would make the verdict depend on a runtime's phrasing.
103
+ *
104
+ * • `timedOut === true` ⇒ `timeout` — the deadline timer FIRED, full stop;
105
+ * • a spawn error, or `exitCode === null` WITHOUT a timeout ⇒ `dead` (the process never ran, or
106
+ * vanished);
107
+ * • anything else ⇒ `exited`, and the FAMILY parser decides. A clean exit with no parseable
108
+ * envelope is ALSO dead — the "spawned but mute" case — but that call belongs to the parser
109
+ * that knows what an envelope looks like, not to this function.
110
+ */
111
+ export declare function classifyChildRun(run: ChildRun): {
112
+ kind: 'timeout';
113
+ } | {
114
+ kind: 'dead';
115
+ detail: string;
116
+ } | {
117
+ kind: 'exited';
118
+ exitCode: number;
119
+ };
120
+ /**
121
+ * Prepended to a RETURN-VALUE codex dispatch. Codex `exec` is an agent with a workspace, not a
122
+ * completion endpoint: without this it will happily start reading files to answer a question whose
123
+ * whole answer is in the prompt. Paired with `--sandbox read-only`, which makes the instruction
124
+ * enforceable rather than advisory.
125
+ */
126
+ export declare const CODEX_SCOPING_PREFIX = "Answer directly from this prompt text alone; no commands, no files, no tools.";
127
+ /**
128
+ * The REAL prompt ceiling for `codex exec`.
129
+ *
130
+ * The folk value 1200 is refuted history: it came from an era when the prompt travelled through a
131
+ * fire-and-forget wrapper. Over-ceiling ⇒ a LOUD `prompt-over-ceiling`, never truncation — a
132
+ * truncated prompt produces a confident answer to a question nobody asked.
133
+ */
134
+ export declare const CODEX_EXEC_PROMPT_CEILING_CHARS = 24000;
135
+ /**
136
+ * argv for one codex dispatch. The prompt travels as ONE argv element (no shell, no quoting), and
137
+ * `stdinText` is ALWAYS null for codex — MEASURED this session: with stdin left open, codex-cli
138
+ * 0.148.0 prints `Reading additional input from stdin...` and waits. `< /dev/null` is not a style
139
+ * choice; it is the difference between a 5.7 s answer and a hang.
140
+ *
141
+ * Return-value mode gets the scoping prefix AND `--sandbox read-only`. File mode gets NEITHER: the
142
+ * step's whole deliverable is a file it must be able to write.
143
+ */
144
+ export declare function codexExecArgv(modelId: string, prompt: string, deliverable: Deliverable): string[];
145
+ /** The liveness probe: an allowlist says an id is SPELLABLE, only a probe says it ANSWERS. */
146
+ export declare function codexProbeArgv(candidateId: string): string[];
147
+ /** Word-bounded `OK` on a clean exit — the `interpretClaudeProbe` twin. */
148
+ export declare function interpretCodexProbe(out: {
149
+ stdout: string;
150
+ exitCode: number | null;
151
+ }): boolean;
152
+ /**
153
+ * Best-effort token extraction from codex stderr — null when absent, NEVER 0 and never estimated.
154
+ *
155
+ * MEASURED (codex-cli 0.148.0, this session): the trailer is a TOTAL only —
156
+ * `tokens used\n9,820` — with no input/output split. `wf-budget-1` has no field for a total, and
157
+ * attributing a total to either half would be a fabrication, so this returns BOTH nulls for that
158
+ * shape and the row's `tokensSource` stays null. The split branch below exists because some
159
+ * builds/configs do print one; it is tested, not assumed. (Named consequence: codex runs report no
160
+ * token counts today. That is the honest state, not a bug to paper over — see the manifest.)
161
+ */
162
+ export declare function extractCodexTokens(stderr: string): {
163
+ tokensIn: number | null;
164
+ tokensOut: number | null;
165
+ };
166
+ /**
167
+ * The claude `--output-format json` USAGE fields, pinned to the LIVE envelope shape.
168
+ *
169
+ * MEASURED this session (`claude -p --output-format json`, sonnet):
170
+ * `usage.input_tokens = 2`, `usage.output_tokens = 4`, alongside `cache_read_input_tokens` and
171
+ * `cache_creation_input_tokens`. Only the two plain counters are reported — cache tokens are a
172
+ * SEPARATE dimension `wf-budget-1` has no field for, and silently folding them into `tokensIn`
173
+ * would inflate every cached run's cost picture. Added to the architecture's export list; see the
174
+ * manifest.
175
+ */
176
+ export declare function extractClaudeUsage(stdout: string): {
177
+ tokensIn: number | null;
178
+ tokensOut: number | null;
179
+ };
180
+ /**
181
+ * The codex adapter. Conventions, each a Confirmation-1 assertion:
182
+ * stdin ALWAYS closed; the prompt as one argv element; scoping prefix + `--sandbox read-only` on
183
+ * return-value and NEITHER on file mode; `detached: true` on every spawn (AM-10).
184
+ */
185
+ export declare function makeCodexExecDispatcher(run: ChildRunner, opts?: {
186
+ bin?: string;
187
+ ceilingChars?: number;
188
+ isolatedCwd?: () => string;
189
+ monotonicMs?: () => number;
190
+ }): Dispatcher;
191
+ /**
192
+ * The claude adapter. Return-value mode is the `dz qe-bridge` ISOLATION discipline verbatim:
193
+ * `claudeReviewArgs(model)` (which carries `CLAUDE_ISOLATION_ARGS`: `--output-format json`,
194
+ * `--safe-mode`, `--strict-mcp-config`, `--tools ''`, `--no-session-persistence`), an EMPTY temp
195
+ * cwd so no project state leaks in, the prompt on STDIN (no ARG_MAX ceiling, no shell), and a
196
+ * LAST-anchored envelope parse so anything a customization printed first is structurally outside
197
+ * the reviewed text.
198
+ *
199
+ * File mode drops `--tools ''` and `--safe-mode` (the step's deliverable is a file it must write)
200
+ * and runs in `req.cwd`, but keeps `--output-format json` and the envelope parse — and the
201
+ * scheduler's landed barrier still has the last word.
202
+ */
203
+ export declare function makeClaudePDispatcher(run: ChildRunner, opts?: {
204
+ bin?: string;
205
+ isolatedCwd?: () => string;
206
+ monotonicMs?: () => number;
207
+ }): Dispatcher;
208
+ /**
209
+ * FILE-mode claude argv: the isolation set MINUS the two flags that would make writing impossible
210
+ * (`--tools ''` and `--safe-mode`). Everything that makes the reply READABLE stays — the envelope
211
+ * is how the runner tells an answer from a banner, in either mode.
212
+ */
213
+ export declare function claudeFileArgs(model: string): string[] | null;
214
+ /**
215
+ * Neutralize anchored `GATE: PASS|FAIL` lines inside UPSTREAM text before it is spliced into a
216
+ * DOWNSTREAM prompt.
217
+ *
218
+ * Why this exists as a second defence, when `gateVerdict` is already LAST-anchored: the two attacks
219
+ * are different. The egress parser stops a single reply from smuggling a verdict past its own
220
+ * terminal line. This stops a reply that legitimately CONTAINS a verdict — an upstream gate's own
221
+ * answer — from becoming the terminal line of a DOWNSTREAM step's reply once the model quotes its
222
+ * input back. Without it, "please review the previous verdict" is a working exploit against a plan
223
+ * that never did anything wrong.
224
+ *
225
+ * NEUTRALIZATION, not deletion: the words survive so the downstream model can still read what the
226
+ * upstream said. Only the ANCHORED grammar is broken. Idempotent — defanging twice is defanging
227
+ * once, so a value that travels through three steps is not progressively mangled.
228
+ */
229
+ export declare function defangGateEchoes(text: string): string;
230
+ //# sourceMappingURL=workflow-run-dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-run-dispatch.d.ts","sourceRoot":"","sources":["../src/workflow-run-dispatch.ts"],"names":[],"mappings":"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"}