bareloop 0.8.0 → 0.10.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.
package/src/ledger.js CHANGED
@@ -75,10 +75,22 @@ const EXCLUDED_ESCALATIONS = new Set([
75
75
  // real upstream ask would be sourced from anyway.
76
76
  'step-stalled',
77
77
  'step-variance', // A's replan trigger: a planning story, never a lib bug
78
- 'gate-red', // governance working as intended
78
+ // Governance working as intended — and no longer minted anywhere in this tree
79
+ // (a denial streak is a bounded attempt, not a terminal). Kept listed because
80
+ // this set is the EXECUTABLE excluded-set: dropping a name does not delete the
81
+ // category, it re-files any future emission of it as a counted capability gap.
82
+ 'gate-red',
79
83
  'smoke-red', // already counted via primitive-smoke
80
84
  'hitl-close', // by design: a human is the close
81
85
  'close-unsupported', // honest refusal, by design
86
+ // Close authoring (M4, D13) — the interview refusing a job we cannot close: a
87
+ // genre we do not run, a job with no seed to measure against, a locked kind.
88
+ // Honest refusal, exactly like `close-unsupported` above, and excluded for a
89
+ // SECOND reason that matters more: the demand is already counted once, as the
90
+ // `request-red` the same refusal emits with `lib: 'bareloop'` stamped at its
91
+ // emit site. Counting the escalation too would double every refusal in the one
92
+ // number the admission path exists to measure.
93
+ 'close-unauthorable',
82
94
  // Layer 3 (D2 split): the bridge load gate refused a wrong-KIND recipe at the door.
83
95
  // That is the mechanism WORKING — every recipe from a different day is a candidate for
84
96
  // refusal, and the run stopped having spent nothing. Filing it upstream would aim a bug
@@ -99,6 +111,11 @@ const EXCLUDED_ESCALATIONS = new Set([
99
111
  // in the registry. Both are the operator's own state speaking (a stale signature, an
100
112
  // edited registry), and both stop having run nothing.
101
113
  'resume-red',
114
+ // v1.57 §3 — the work branch could not be created: the patient is not a git checkout,
115
+ // or its branch namespace is too crowded to find a free name. The operator's own state
116
+ // speaking, exactly like `registry-red` below, and the run stopped having spent nothing.
117
+ // Filing it upstream would aim a bug report at a library for a patient nobody prepared.
118
+ 'branch-red',
102
119
  'registry-red', // the operator-supplied registry path does not exist — a typo, not a bug
103
120
  'envelope-red', // the envelope does not compose with the signed spec — operator input
104
121
  // the reuse runner also STOPS on the three answers no further try could change, and
package/src/plan.js CHANGED
@@ -25,6 +25,7 @@
25
25
  // plain parsed data; every failure is a named {code, path, detail} red.
26
26
 
27
27
  import { TOOL_MENU, LOCKED_TOOLS, WRITE_VERBS, checkMenu } from './job.js';
28
+ import { declaredStages } from './declaredclose.js';
28
29
  import { globToPrefix, scopeContained, isObj, isNonEmptyString, sweepSecretLiterals, hasNestedQuantifier } from './validate.js';
29
30
 
30
31
  /** the closed exit menu (PRD v1.12 §3 + decision 1's `check-passes`): the
@@ -170,6 +171,30 @@ export function stageClose(close) {
170
171
  return [{ name: 'close', cmd: close.cmd, expect: close.expect, judged: close.judged, gapKeep: close.gapKeep }];
171
172
  }
172
173
 
174
+ /**
175
+ * THE ONE STAGING, one level up: a job's close stages, from EITHER of the two
176
+ * fields a spec may carry.
177
+ *
178
+ * `stageClose` reads a command close; `declaredStages` reads an authored
179
+ * declaration (M4). A spec declares exactly one of them — the job validator reds
180
+ * `close-duplicated` on both — so this is a selection, never a merge.
181
+ *
182
+ * Every consumer calls THIS rather than `stageClose` directly, for the reason
183
+ * W4 wrote `stageClose` in the first place: the drafting prompt, the plan
184
+ * validator, the runner, the bridge registry and the reuse envelope must all see
185
+ * the same stage list, and a consumer that reads only `close` sees a declared
186
+ * job as having no close at all — an empty check menu offered to a drafter whose
187
+ * plan the validator would then red for referencing a stage nobody offered.
188
+ * @param {any} job the job spec, any shape
189
+ * @returns {any[]|null} the stage list, or null when the job names no close
190
+ */
191
+ export function closeStagesOf(job) {
192
+ if (!isObj(job)) return null;
193
+ const declared = declaredStages(job.closeDecl);
194
+ if (declared) return declared;
195
+ return stageClose(job.close);
196
+ }
197
+
173
198
  /** @typedef {{code: string, path: string, detail?: string, verb?: string}} Red */
174
199
 
175
200
  /**
@@ -235,7 +260,7 @@ export function validatePlan(input, { job, maxStepRounds = 40, scopes, seedRed,
235
260
  // (gold/rubric/hitl) stages nothing, so it offers nothing — the runner
236
261
  // escalates `close-unsupported` on the same null, and an empty menu is already
237
262
  // the honest reading here (every check-passes becomes a check-unknown).
238
- const checkNames = checkMenu(stageClose(spec.close) ?? []).map((m) => m.name);
263
+ const checkNames = checkMenu(closeStagesOf(spec) ?? []).map((m) => m.name);
239
264
  // The offered scope menu. A caller-supplied menu must be the same one the
240
265
  // prompt enumerated; with none, derive from the signed fence — fail-CLOSED,
241
266
  // so omitting the option narrows the agent's choices and never widens them.