unitbob 0.4.2 → 0.4.4

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/README.md CHANGED
@@ -30,7 +30,7 @@ claude plugin install unitbob@unitbob
30
30
  ```
31
31
  codex plugin marketplace add sergeygershun/unitbob-connector
32
32
  codex plugin add unitbob@unitbob
33
- npx -y unitbob@0.4.2 codex-install
33
+ npx -y unitbob@0.4.4 codex-install
34
34
  ```
35
35
 
36
36
  Start a new Claude Code or Codex thread so the installed skill and named agents
@@ -28,13 +28,14 @@ export async function probeBehavioralWorld(projectRoot, deps = {
28
28
  env: {
29
29
  ...process.env,
30
30
  RAILS_ENV: 'test',
31
+ CUCUMBER_PUBLISH_QUIET: 'true',
31
32
  UNITBOB_REPO_ROOT: projectRoot,
32
33
  BUNDLE_GEMFILE: join(projectRoot, '.unitbob', 'behavioral', 'Gemfile'),
33
34
  },
34
35
  });
35
36
  if (result.code === 0)
36
37
  return { status: 'ok' };
37
- const detail = [result.stderr, result.stdout].find((text) => text.trim())?.trim() ?? `exit ${result.code}`;
38
+ const detail = [result.stdout, result.stderr].map((text) => text.trim()).filter(Boolean).join('\n') || `exit ${result.code}`;
38
39
  return { status: 'fixable', message: `The connector-owned Ruby/Cucumber World probe failed: ${detail}` };
39
40
  }
40
41
  catch (error) {
@@ -58,6 +59,14 @@ PROBE_OTHER_TIME_ZONE = PROBE_TIME_ZONE&.name == 'UTC' ? 'Hawaii' : 'UTC'
58
59
  PROBE_LOCALE = I18n.locale
59
60
  PROBE_RECEIVER = Object.new
60
61
 
62
+ # The probe runs in a dedicated process, so replacing its in-memory route set
63
+ # cannot affect the host application after the process exits. Keeping these
64
+ # endpoints here makes the profile check independent of routes the host owns.
65
+ Rails.application.routes.draw do
66
+ match '/__unitbob_world_probe__', to: proc { [200, { 'Content-Type' => 'text/plain' }, ['ok']] }, via: :all
67
+ match '/__unitbob_world_probe_redirect__', to: redirect('/__unitbob_world_probe_target__'), via: :all
68
+ end
69
+
61
70
  Given('the first World probe scenario mutates supported state') do
62
71
  @unitbob_connection.execute("INSERT INTO schema_migrations (version) VALUES ('#{PROBE_VERSION}')")
63
72
  Time.zone = PROBE_OTHER_TIME_ZONE
@@ -33,24 +33,11 @@ export async function runLocal(config, args = [], deps) {
33
33
  // examined the suite.
34
34
  if (!ran)
35
35
  continue;
36
- const spent = spend(config.projectRoot, `run-local:${suiteKind}`);
37
- if (request.budget && spent > request.budget.repair_rounds) {
38
- d.stdout.write(polishedEnoughNotice(suiteKind, spent, request.budget.repair_rounds));
39
- }
36
+ // Kept as compatibility diagnostics only. The bounded repair role owns the
37
+ // mechanical ceiling; this counter never stops execution or classifies reds.
38
+ spend(config.projectRoot, `run-local:${suiteKind}`);
40
39
  }
41
40
  }
42
- // Not a refusal, and deliberately not about the budget either. After eight
43
- // rounds of repair the interesting fact is not that a number ran out — it is
44
- // what the remaining reds most likely are. Both real logs show 3-5 runs of a
45
- // branch as ordinary work, so a branch on its ninth has already been repaired
46
- // past the point where the harness is the usual explanation.
47
- function polishedEnoughNotice(suiteKind, spent, allowed) {
48
- return (`\nThat was run ${spent} of the ${suiteKind} branch; this build budgeted ${allowed}. ` +
49
- 'Reds that survive this many rounds of repair are far more likely to be defects of your product ' +
50
- 'than of the harness around it.\n' +
51
- 'Publish the suite as it stands rather than keep polishing. A first suite that comes out red is ' +
52
- 'a finding, not a failure — finding those reds is what it was written to do.\n');
53
- }
54
41
  // Which branches to run. No argument runs every branch the request asked for —
55
42
  // the same "one suite, one run" shape both recipes insist on, so the default
56
43
  // never teaches the habit the recipes forbid. A named branch is for the repair
@@ -173,7 +173,7 @@ export async function suitePrepare(config, args = [], deps) {
173
173
  // A fixable runner blocker is not a failure: the structural suite still builds this run. Tell the
174
174
  // vibecoder the one command that unblocks the behavioral peer, then re-run suite-prepare.
175
175
  if (fixableNotices.length > 0) {
176
- actual.stdout.write('\nBehavioral suite skipped this run — its BDD runner is not installed yet. ' +
176
+ actual.stdout.write('\nBehavioral suite skipped this run — its runner or connector-owned World profile is not ready. ' +
177
177
  'This is a fixable setup step, not a build failure, and it does not affect the structural suite:\n' +
178
178
  fixableNotices.join('\n') +
179
179
  '\nFix the above, then re-run `unitbob suite-prepare` to build the behavioral peer.\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unitbob",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Unitbob connector — thin local hands for the Unitbob Rails brain. Owns no domain logic: it runs tools, relays bytes over the wire, and prints what the server returns.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,16 +1,37 @@
1
1
  name = "suite-repair-worker"
2
- description = "Completes one bounded Unitbob failure packet using the prior checkpoint and owned files, without widening scope or running the suite."
2
+ description = "Completes and executes one bounded Unitbob owned-slice repair packet without widening scope."
3
3
  model = "gpt-5.6-terra"
4
4
  model_reasoning_effort = "medium"
5
5
  developer_instructions = '''
6
- You receive one failure packet: one validated plan item, its checkpoint, owned
7
- paths, and only related failures or stack traces. This is your complete scope.
6
+ You receive one failure packet: one validated plan item, its checkpoint, branch,
7
+ owned paths and case markers, and only related failures or stack traces. This is
8
+ your complete write scope.
8
9
 
9
10
  Complete `unresolved_promises` first while preserving every completed file and
10
- decision. Then repair only harness problems whose stack points into this slice's
11
- owned files. Do not expand capabilities, promises, planned cases, or paths. Do
12
- not edit host-owned shared files, the connector-owned harness, application
13
- production code, or another slice.
11
+ decision. You may read the plan item's source paths and, only as needed for the
12
+ owned diagnosis, stack-referenced project source, the runner setup and harness
13
+ actually in use, helpers, and factories. Repair only this slice's owned generated
14
+ files and its checkpoint. Do not expand capabilities, promises, planned cases,
15
+ markers, or paths. Do not edit production code, host-owned shared files, the
16
+ connector-owned harness, or another slice.
17
+
18
+ After every owned edit, run
19
+ `npx -y --loglevel=error unitbob@0.4.4 run-local <branch>` and inspect the machine
20
+ report. Look only at examples or scenarios matching your owned paths or case
21
+ markers. Do not require a green exit code from the whole branch: foreign failures
22
+ and an already-confirmed product red do not widen your scope. Repeat the bounded
23
+ `edit → run-local → inspect` loop until every owned case passes or is diagnosed
24
+ as a product defect. Do not run the project's suite directly, boot a dev server,
25
+ or invoke an arbitrary runner command.
26
+
27
+ A product-defect diagnosis must briefly name the violated business contract, the
28
+ reason, and production source references. Never delete a planned case, marker,
29
+ capability binding, or assertion; never add `skip`, `pending`, `todo`, or weaken a
30
+ business promise for green. You may correct a generated expectation only when
31
+ the business promise remains intact and source confirms the correction. If the
32
+ harness is still wrong, continue the loop. If the outcome is ambiguous, the
33
+ runner is unusable, or the turn ceiling stops unfinished work, leave an honest
34
+ branch `build_error`, never a product red. No strict JSON handoff is required.
14
35
 
15
36
  Update the same checkpoint as promises complete. Keep facts compact and
16
37
  source-referenced. The normative JSON shape of one facts entry is:
@@ -19,15 +40,12 @@ source-referenced. The normative JSON shape of one facts entry is:
19
40
  ```
20
41
  Every facts entry is an object in that shape, never a string. Before handoff,
21
42
  make one final read of the checkpoint and confirm every `facts` entry is an
22
- object in the normative shape above. Never run the suite or boot the
23
- application; the coordinator
24
- owns the single final run. Do not delegate a second repair, continue another
25
- agent, or request another repair round. If work remains at the turn ceiling,
26
- record it in `unresolved_promises` so the coordinator can produce an honest
27
- branch `build_error`.
43
+ object in the normative shape above. Do not delegate repair or auto-resume after
44
+ the ceiling. Preserve files and checkpoint for the coordinator's existing
45
+ `Continue once / Stop` choice; record unfinished work in `unresolved_promises`.
28
46
  '''
29
47
 
30
48
  [features.rollout_budget]
31
49
  enabled = true
32
- limit_tokens = 15000
50
+ limit_tokens = 40000
33
51
  reminder_at_remaining_tokens = [3000]