@hone-ai/cli 1.29.1 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/run-report.js +72 -4
  2. package/package.json +1 -1
package/lib/run-report.js CHANGED
@@ -86,14 +86,76 @@ function buildReport(run, extra = {}) {
86
86
  for (const s of brokenSteps) {
87
87
  // Skip the one the run-level item already names, so one problem is one entry.
88
88
  if (run.status === 'failed' && s.stepKey === run.currentStep) continue;
89
+ // HC-GF-036(b): a step that RETURNED AN ADVERSE VERDICT did not break. Saying
90
+ // "code-reviewer FAILED" for a reviewer that ran correctly and said no is the same
91
+ // conflation that was inflating batch failure_rates — and it points the operator at
92
+ // the wrong thing to fix. The verdict kinds name the agent's own vocabulary.
93
+ const kind = (s.diagnostics && s.diagnostics.failure_record || {}).failure_kind;
94
+ const VERDICT = {
95
+ review_reject: 'returned a FAIL review',
96
+ security_high: 'raised a HIGH security finding',
97
+ security_medium: 'raised a MEDIUM security finding',
98
+ test_fail: 'reported failing tests',
99
+ lint_fail: 'reported lint errors',
100
+ perf_finding: 'raised a performance finding',
101
+ validator_rejected: 'produced output the format validator rejected',
102
+ };
103
+ const what = kind && VERDICT[kind]
104
+ ? `${s.stepKey} (${s.agent || 'agent'}) ${VERDICT[kind]}`
105
+ : `${s.stepKey} (${s.agent || 'agent'}) ${s.status === 'failed' ? 'FAILED' : 'was REJECTED'}`;
89
106
  needsYou.push({
90
- what: `${s.stepKey} (${s.agent || 'agent'}) ${s.status === 'failed' ? 'FAILED' : 'was REJECTED'}`
91
- + ` — the run is recorded ${run.status}, so nothing downstream will revisit it`,
107
+ what: `${what} — the run is recorded ${run.status}, so nothing downstream will revisit it`,
92
108
  how: `hone show step ${run.runId} ${s.stepKey}`,
93
109
  howLabel: 'inspect',
94
110
  });
95
111
  }
96
112
 
113
+ // 1c. HC-GF-041: a retry that came back with LESS than the attempt it replaces.
114
+ //
115
+ // The newest attempt REPLACES the previous one for every downstream consumer, so this
116
+ // silently deletes work. Twice it was caught only because an agent refused to treat
117
+ // absence as evidence — step_5d's `UNVERIFIED-HIGH / source-unavailable`, and a
118
+ // reviewer's "I will not approve a P0 reliability primitive I have not read". Neither
119
+ // is a mechanism; both were luck. This is the mechanism.
120
+ //
121
+ // NEEDS YOU, not WORTH KNOWING: the artifact every later step reads is not the one a
122
+ // human approved, and only a human can say whether that is acceptable.
123
+ for (const s of steps) {
124
+ const reg = s.diagnostics && s.diagnostics.artifact_regression;
125
+ if (!reg) continue;
126
+ needsYou.push({
127
+ what: `${s.stepKey} attempt ${s.attempt} carries less than the attempt it replaces`
128
+ + ` — and it is the one every later step reads`,
129
+ detail: (reg.reasons || []).map(String),
130
+ how: `hone show step ${run.runId} ${s.stepKey} --attempt ${s.attempt}`,
131
+ howLabel: 'compare',
132
+ });
133
+ }
134
+
135
+ // 1d. HC-GF-041: two diagnostics the orchestrator has stamped since HC-019n-followup-41
136
+ // and -43, which NOTHING has ever read on this path — the run payload carried only
137
+ // token counts until the `diagnostics` projection was added. HC-GF-016's row specifies
138
+ // these be rendered; this is the first build where they can be.
139
+ //
140
+ // Both are written ONLY when non-empty, so an absent key means "checked, none found"
141
+ // and must not be rendered as a reassuring zero — silence here is correct, an invented
142
+ // "none" would be a claim the report cannot support for a run that never ran the check.
143
+ for (const s of steps) {
144
+ const d = s.diagnostics || {};
145
+ if (Array.isArray(d.invented_paths) && d.invented_paths.length) {
146
+ needsYou.push({
147
+ what: `${s.stepKey} named ${d.invented_paths.length} path(s) that do not exist in the repo, and was accepted anyway`,
148
+ detail: d.invented_paths.map(String),
149
+ how: `hone show step ${run.runId} ${s.stepKey}`,
150
+ howLabel: 'inspect',
151
+ });
152
+ }
153
+ if (Array.isArray(d.composed_missing) && d.composed_missing.length) {
154
+ worthKnowing.push(
155
+ `${s.stepKey} dropped composed guardrail section(s) on a retry and was accepted (budget spent): ${d.composed_missing.join(', ')}`);
156
+ }
157
+ }
158
+
97
159
  // 2. The last verification is ONE event, so it becomes ONE item with sub-lines.
98
160
  // Listing "verification failed" and "lint failed" separately gave two entries
99
161
  // for one problem resolved by one fix — and NEEDS YOU is a list of DISTINCT
@@ -126,10 +188,16 @@ function buildReport(run, extra = {}) {
126
188
  }
127
189
 
128
190
  // ── WORTH KNOWING ──────────────────────────────────────────────────────────
129
- // Retries: the step produced something the pipeline rejected at least once.
191
+ // Retries: the step ran more than once. HC-GF-041(c): this used to append "(its
192
+ // first output was rejected)", which the report never checked and which is often
193
+ // FALSE — on run 08c27392 step_4's attempt 1 was `completed | approved` and it was
194
+ // attempt 2 that got rejected; a route-back retries a step whose first output was
195
+ // fine. Narrating an unchecked cause inside the tool built to be derived-never-
196
+ // narrated is the defect HC-GF-016 exists to prevent. State the count, which is
197
+ // measured, and let the regression check below say when something is wrong.
130
198
  for (const s of steps) {
131
199
  if (Number(s.attempts) > 1) {
132
- worthKnowing.push(`${s.stepKey} retried — ${s.attempts} attempts (its first output was rejected)`);
200
+ worthKnowing.push(`${s.stepKey} ran ${s.attempts} times`);
133
201
  }
134
202
  }
135
203
  // The two "blind run" tells, both from HC-GF-006's preflight reasoning.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hone-ai/cli",
3
- "version": "1.29.1",
3
+ "version": "1.30.0",
4
4
  "description": "Hone AI — Enterprise SDLC Pipeline CLI",
5
5
  "main": "hone-cli.js",
6
6
  "bin": {