repo-harness 0.7.3 → 0.7.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.es.md CHANGED
@@ -85,7 +85,7 @@ artifacts.
85
85
  ## Novedades
86
86
 
87
87
  Las notas de versión viven en [`docs/CHANGELOG.md`](docs/CHANGELOG.md). La línea
88
- actual es `0.7.3`.
88
+ actual es `0.7.4`.
89
89
 
90
90
  ## Cómo funciona
91
91
 
@@ -419,8 +419,8 @@ Guards habituales:
419
419
 
420
420
  ## Release actual
421
421
 
422
- - npm package: `repo-harness@0.7.3`
423
- - Generated workflow stamp: `repo-harness@0.7.3+template@0.7.3`
422
+ - npm package: `repo-harness@0.7.4`
423
+ - Generated workflow stamp: `repo-harness@0.7.4+template@0.7.4`
424
424
  - GitHub repository: `Ancienttwo/repo-harness`
425
425
  - Release history: [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
426
426
 
package/README.fr.md CHANGED
@@ -85,7 +85,7 @@ l'emportent.
85
85
  ## Nouveautés
86
86
 
87
87
  Les notes de version vivent dans [`docs/CHANGELOG.md`](docs/CHANGELOG.md). La
88
- ligne actuelle est `0.7.3`.
88
+ ligne actuelle est `0.7.4`.
89
89
 
90
90
  ## Comment ça marche
91
91
 
@@ -424,8 +424,8 @@ Guards courants :
424
424
 
425
425
  ## Release actuelle
426
426
 
427
- - npm package : `repo-harness@0.7.3`
428
- - Generated workflow stamp : `repo-harness@0.7.3+template@0.7.3`
427
+ - npm package : `repo-harness@0.7.4`
428
+ - Generated workflow stamp : `repo-harness@0.7.4+template@0.7.4`
429
429
  - GitHub repository : `Ancienttwo/repo-harness`
430
430
  - Release history : [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
431
431
 
package/README.ja.md CHANGED
@@ -75,7 +75,7 @@ review、checks、handoff と食い違う場合は、source artifacts を優先
75
75
  ## What's New
76
76
 
77
77
  リリースノートは [`docs/CHANGELOG.md`](docs/CHANGELOG.md) にあります。現在の
78
- ラインは `0.7.3` です。
78
+ ラインは `0.7.4` です。
79
79
 
80
80
  ## 仕組み
81
81
 
@@ -398,8 +398,8 @@ hook がブロックしたときは、まず terminal の構造化された出
398
398
 
399
399
  ## 現在の Release
400
400
 
401
- - npm package:`repo-harness@0.7.3`
402
- - Generated workflow stamp:`repo-harness@0.7.3+template@0.7.3`
401
+ - npm package:`repo-harness@0.7.4`
402
+ - Generated workflow stamp:`repo-harness@0.7.4+template@0.7.4`
403
403
  - GitHub repository:`Ancienttwo/repo-harness`
404
404
  - Release history:[`docs/CHANGELOG.md`](docs/CHANGELOG.md)
405
405
 
package/README.md CHANGED
@@ -78,7 +78,7 @@ active plan, contract, review, checks, or handoff, the source artifacts win.
78
78
  ## What's New
79
79
 
80
80
  Release notes live in [`docs/CHANGELOG.md`](docs/CHANGELOG.md). The current line
81
- is `0.7.3`.
81
+ is `0.7.4`.
82
82
 
83
83
  ## How It Works
84
84
 
@@ -493,8 +493,8 @@ Most common guards:
493
493
 
494
494
  ## Current Release
495
495
 
496
- - npm package: `repo-harness@0.7.3`
497
- - Generated workflow stamp: `repo-harness@0.7.3+template@0.7.3`
496
+ - npm package: `repo-harness@0.7.4`
497
+ - Generated workflow stamp: `repo-harness@0.7.4+template@0.7.4`
498
498
  - GitHub repository: `Ancienttwo/repo-harness`
499
499
  - Release history: [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
500
500
 
package/README.zh-CN.md CHANGED
@@ -69,7 +69,7 @@ review、checks 或 handoff 冲突,以 source artifacts 为准。
69
69
 
70
70
  ## What's New
71
71
 
72
- Release notes 见 [`docs/CHANGELOG.md`](docs/CHANGELOG.md),当前版本线是 `0.7.3`。
72
+ Release notes 见 [`docs/CHANGELOG.md`](docs/CHANGELOG.md),当前版本线是 `0.7.4`。
73
73
 
74
74
  ## 工作原理
75
75
 
@@ -437,8 +437,8 @@ hook block 工作时,先看 terminal 里的结构化输出。核心字段是
437
437
 
438
438
  ## 当前 Release
439
439
 
440
- - npm package:`repo-harness@0.7.3`
441
- - Generated workflow stamp:`repo-harness@0.7.3+template@0.7.3`
440
+ - npm package:`repo-harness@0.7.4`
441
+ - Generated workflow stamp:`repo-harness@0.7.4+template@0.7.4`
442
442
  - GitHub repository:`Ancienttwo/repo-harness`
443
443
  - Release history:[`docs/CHANGELOG.md`](docs/CHANGELOG.md)
444
444
 
@@ -36,22 +36,45 @@ Use GPT Pro language with the user. Treat the `browser-*` command names as imple
36
36
  `stamp="$(date -u +%Y%m%dT%H%M%SZ)"; slug="<short-purpose>"; mkdir -p .ai/harness/handoff/gptpro; out=".ai/harness/handoff/gptpro/gptpro-${stamp}-${slug}.md"; repo-harness chatgpt browser-consult --repo <repo> --provider oracle --model gpt-5.5-pro --heartbeat 59 --title "gptpro-${stamp}-${slug}" --prompt <prompt> --write-output "$out"`
37
37
  10. Use `--dry-run` first when attaching files, then run the real consult only after the prompt bundle and allowed paths are clear.
38
38
  11. For GPT Pro reviews or acceptance checks, resolve the recorded ChatGPT MCP server name from `repo-harness mcp doctor --repo <repo> --json` or `.repo-harness/mcp.local.json` (`chatgpt.serverName`). Treat `chatgpt.serverNameConfigured:false` or a missing `chatgpt.serverName` as setup-incomplete, then route to `repo-harness:gptpro_setup` before an MCP read-back review. Do not substitute a user-specific hard-coded MCP name.
39
- 12. When the user asks for a reasoning mode, pass repo-harness `--thinking <light|standard|extended|heavy>` only after `browser-doctor --provider oracle` reports `browserThinkingTime:true`; repo-harness maps it to Oracle `--browser-thinking-time`.
40
- 13. For long GPT Pro analysis tasks, keep Oracle heartbeat enabled at 59 seconds unless the user explicitly disables it; repo-harness streams heartbeat/diagnostic lines to stderr and reserves stdout for final JSON.
41
- 14. Report the GPT Pro result with: session id, timestamped output path, conversation URL if present, whether it was a new consult or follow-up, and any visible-browser blocker.
39
+ 12. When MCP read-back is required, pass the recorded server name as an explicit ChatGPT app preselect: `serverName="$(repo-harness mcp doctor --repo <repo> --json | jq -r '.chatgpt.serverName // empty')"` and add `--chatgpt-app "$serverName"` to `browser-consult` or `browser-followup`. If the command fails with `ORACLE_APP_PRESELECT_UNSUPPORTED`, the selected Oracle binary cannot click the ChatGPT app selector yet; report that as a browser-trigger blocker instead of relying on prompt text like `@serverName`.
40
+ 13. When the user asks for a reasoning mode, pass repo-harness `--thinking <light|standard|extended|heavy>` only after `browser-doctor --provider oracle` reports `browserThinkingTime:true`; repo-harness maps it to Oracle `--browser-thinking-time`.
41
+ 14. For long GPT Pro analysis tasks, expect detailed Pro Extended planning/review runs to take 15 minutes or more. Do not treat elapsed time as failure while the session is still alive; wait for a final answer or a concrete browser, login, capture, or tool-call failure.
42
+ 15. Keep Oracle heartbeat enabled at 59 seconds unless the user explicitly disables it; repo-harness streams heartbeat/diagnostic lines to stderr and reserves stdout for final JSON. Heartbeat lines like `no thinking status detected yet` are progress diagnostics, not a blocker by themselves.
43
+ 16. Report the GPT Pro result with: session id, timestamped output path, conversation URL if present, whether it was a new consult or follow-up, and any visible-browser blocker.
42
44
 
43
45
  ## MCP Read-Back Acceptance
44
46
 
45
47
  When asking GPT Pro to review repo updates, include an explicit acceptance requirement in the prompt:
46
48
 
47
49
  - Use the recorded ChatGPT MCP server name from `chatgpt.serverName` to read the current repo state before producing findings or a merge/readiness verdict.
50
+ - Before a Pro MCP attempt, open ChatGPT Settings -> Connectors for the recorded server name, run Refresh or Scan Tools, verify the expected Action is listed, then start a fresh chat and select the Connector from `+` -> More.
48
51
  - Read at least the changed-file list or status, the relevant diffs or changed files, and any requested session/handoff artifacts through that recorded MCP server; pasted summaries are context, not sufficient evidence.
49
52
  - Include a short `MCP Read Evidence` section in the final answer naming the recorded MCP server, the reads performed, and the files, diffs, or artifacts inspected.
50
53
  - If the recorded MCP server name is missing, or `mcp doctor --json` reports `chatgpt.serverNameConfigured:false`, route to `repo-harness:gptpro_setup` so initialization can record it before review.
51
54
  - If the recorded MCP server is unavailable, blocked, stale, or cannot read the requested paths, classify the result as blocked or partial instead of issuing a merge-ready verdict.
52
55
  - A prompt that asks ChatGPT to use the recorded MCP server is not sufficient by itself; the ChatGPT conversation must expose the app/action schema. If the conversation reports that the app is not exposed, use a fresh app-enabled conversation or a GitHub PR/diff evidence source instead of claiming MCP read-back evidence.
56
+ - For Pro runs, the normal tool-call runtime UI may not appear the way it does for other models because Pro uses a sandbox/process flow. In the visible ChatGPT Web UI, click the assistant's `Thinking` / `Thought for ...` disclosure to open the right-side process pane. Use that pane to confirm whether Pro actually emitted a `Called tool` event for the selected app, which action it chose, or whether it only reasoned inside the sandbox without invoking MCP.
57
+ - Treat `Called tool` with an action/result, or an equivalent captured tool-call transcript, as the only accepted MCP invocation evidence. Reject connector selection, assistant self-report, plausible JSON, and sandbox shell exploration as proof.
58
+ - Classify Pro outcomes explicitly: `invocation_verified` for a real tool call, `approval_pending` for a real confirmation prompt, `surface_blocked` for sandbox-only reasoning or `app_unavailable` with no tool event, and `bundle_fallback` when Pro reviews a local evidence bundle instead of reading through MCP.
53
59
  - Do not ask GPT Pro to retrieve secrets, cookies, browser storage, ignored private operations state, or other denied paths through the recorded MCP server.
54
60
 
61
+ ## Pro Surface Fallback
62
+
63
+ - When Pro is `surface_blocked`, stop retrying the same connector prompt after one explicit-tool retry. Do not delete/recreate the Connector as the first response to a Pro-only dispatch failure.
64
+ - Reuse the existing local GPT Pro/Oracle handoff path. Build a bounded evidence bundle from local files, diffs, checks, and known external findings, then ask Pro for a plan or review over that bundle.
65
+ - The fallback prompt must include a provenance header:
66
+
67
+ ```yaml
68
+ source: local_repo_harness_bundle
69
+ pro_invoked_mcp: false
70
+ working_tree: clean | dirty
71
+ included_paths: [...]
72
+ omitted_or_truncated: [...]
73
+ ```
74
+
75
+ - Tell Pro that anything outside the bundle is unknown. Codex executes and verifies locally, then creates a fresh post-change bundle for another Pro review if needed.
76
+ - Distinguish permissions: repo-scope setup is repo-bound; broad repo discovery requires explicit user-scope setup with full-disk read. Do not recommend full-disk read by default.
77
+
55
78
  ## Research Promotion
56
79
 
57
80
  - Treat `.ai/harness/handoff/gptpro/*.md` as raw local GPT Pro evidence. These files are timestamped and ignored so repeated reviews do not collide or pollute tracked workflow handoff files.
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "0.7.3",
3
- "templateVersion": "0.7.3",
2
+ "version": "0.7.4",
3
+ "templateVersion": "0.7.4",
4
4
  "skillName": "repo-harness",
5
5
  "contractId": "tasks-first-harness-v1",
6
6
  "compatibility": {
@@ -155,6 +155,10 @@
155
155
  {
156
156
  "version": "0.7.3",
157
157
  "description": "Compacts package-dispatched helper migration, preserves ChatGPT MCP bind settings, and hardens Codex delegation lifecycle retries"
158
+ },
159
+ {
160
+ "version": "0.7.4",
161
+ "description": "Adds user-scope ChatGPT MCP full-disk repo discovery, GPT Pro Connector read-back safeguards, and package-dispatched architecture helper fixes while retiring compact adopt root wrappers"
158
162
  }
159
163
  ],
160
164
  "generatedProjectStamp": {
@@ -71,26 +71,59 @@ index_file="docs/architecture/index.md"
71
71
  requests_dir="docs/architecture/requests"
72
72
  event_file=".ai/harness/architecture/events.jsonl"
73
73
 
74
+ helper_sibling() {
75
+ local helper_name="$1"
76
+ local helper_dir=""
77
+ if [[ -n "${REPO_HARNESS_HELPER_SOURCE_PATH:-}" ]]; then
78
+ helper_dir="$(dirname "$REPO_HARNESS_HELPER_SOURCE_PATH")"
79
+ fi
80
+ if [[ -n "$helper_dir" && -f "$helper_dir/$helper_name" ]]; then
81
+ printf '%s\n' "$helper_dir/$helper_name"
82
+ return 0
83
+ fi
84
+ return 1
85
+ }
86
+
74
87
  architecture_event() {
88
+ local sibling=""
75
89
  if command -v bun >/dev/null 2>&1 && [[ -f "scripts/architecture-event.ts" ]]; then
76
90
  bun scripts/architecture-event.ts "$@"
77
91
  return $?
78
92
  fi
93
+ sibling="$(helper_sibling architecture-event.ts || true)"
94
+ if command -v bun >/dev/null 2>&1 && [[ -n "$sibling" ]]; then
95
+ bun "$sibling" "$@"
96
+ return $?
97
+ fi
79
98
  return 127
80
99
  }
81
100
 
82
101
  architecture_event_required() {
83
- if ! command -v bun >/dev/null 2>&1; then
84
- echo "architecture-queue: bun is required for $command_name" >&2
85
- return 127
86
- fi
87
- if [[ ! -f "scripts/architecture-event.ts" ]]; then
88
- echo "architecture-queue: missing scripts/architecture-event.ts" >&2
102
+ if ! architecture_event safe-token --value probe >/dev/null 2>&1; then
103
+ echo "architecture-queue: missing architecture-event helper" >&2
89
104
  return 127
90
105
  fi
91
106
  return 0
92
107
  }
93
108
 
109
+ capability_resolver() {
110
+ local sibling=""
111
+ if command -v bun >/dev/null 2>&1 && [[ -f "scripts/capability-resolver.ts" ]]; then
112
+ bun scripts/capability-resolver.ts "$@"
113
+ return $?
114
+ fi
115
+ sibling="$(helper_sibling capability-resolver.ts || true)"
116
+ if command -v bun >/dev/null 2>&1 && [[ -n "$sibling" ]]; then
117
+ bun "$sibling" "$@"
118
+ return $?
119
+ fi
120
+ return 127
121
+ }
122
+
123
+ capability_resolver_available() {
124
+ capability_resolver list --format json >/dev/null 2>&1
125
+ }
126
+
94
127
  json_escape() {
95
128
  local value="$1"
96
129
  value="${value//\\/\\\\}"
@@ -404,7 +437,7 @@ status_command() {
404
437
  return 0
405
438
  ;;
406
439
  strict)
407
- if ! command -v bun >/dev/null 2>&1 || [[ ! -f "scripts/architecture-event.ts" || ! -f "scripts/capability-resolver.ts" ]]; then
440
+ if ! architecture_event_required >/dev/null 2>&1 || ! capability_resolver_available; then
408
441
  echo "[ArchitectureQueue] strict gate failed: missing queue dependencies" >&2
409
442
  return 1
410
443
  fi
@@ -440,15 +473,15 @@ record_command() {
440
473
  exit 0
441
474
  fi
442
475
 
443
- if ! command -v bun >/dev/null 2>&1 || [[ ! -f "scripts/architecture-event.ts" ]]; then
444
- echo "[ArchitectureQueue] WARN: bun and scripts/architecture-event.ts are required to record $rel_path; skipping advisory queue update"
476
+ if ! architecture_event_required >/dev/null 2>&1; then
477
+ echo "[ArchitectureQueue] WARN: architecture-event helper is required to record $rel_path; skipping advisory queue update"
445
478
  exit 0
446
479
  fi
447
480
 
448
481
  capability_match=""
449
- if [[ -f "scripts/capability-resolver.ts" ]]; then
482
+ if capability_resolver_available; then
450
483
  resolver_stderr="$(mktemp)"
451
- if ! capability_match="$(bun scripts/capability-resolver.ts match --path "$rel_path" --format json 2>"$resolver_stderr")"; then
484
+ if ! capability_match="$(capability_resolver match --path "$rel_path" --format json 2>"$resolver_stderr")"; then
452
485
  [[ -n "$capability_match" ]] && echo "$capability_match" >&2
453
486
  cat "$resolver_stderr" >&2
454
487
  rm -f "$resolver_stderr"
@@ -475,7 +508,7 @@ record_command() {
475
508
  matched_prefix="$(json_get "$capability_match" "matched_prefix")"
476
509
  capability_id="$(json_get "$capability_match" "capability_id")"
477
510
  capability_resolved="true"
478
- elif [[ ! -f "scripts/capability-resolver.ts" ]]; then
511
+ elif ! capability_resolver_available; then
479
512
  functional_block="$(match_functional_block "$rel_path")"
480
513
  matched_prefix="$functional_block"
481
514
  capability_id="$(safe_token "$functional_block")"
@@ -90,6 +90,19 @@ try {
90
90
  printf '%s' "${value:-$default_value}"
91
91
  }
92
92
 
93
+ helper_sibling() {
94
+ local helper_name="$1"
95
+ local helper_dir=""
96
+ if [[ -n "${REPO_HARNESS_HELPER_SOURCE_PATH:-}" ]]; then
97
+ helper_dir="$(dirname "$REPO_HARNESS_HELPER_SOURCE_PATH")"
98
+ fi
99
+ if [[ -n "$helper_dir" && -f "$helper_dir/$helper_name" ]]; then
100
+ printf '%s\n' "$helper_dir/$helper_name"
101
+ return 0
102
+ fi
103
+ return 1
104
+ }
105
+
93
106
  severity_rank() {
94
107
  case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in
95
108
  critical) printf '4' ;;
@@ -198,17 +211,51 @@ case "$mode" in
198
211
  ;;
199
212
  esac
200
213
 
201
- if [[ ! -x "scripts/architecture-queue.sh" ]]; then
214
+ run_architecture_queue() {
215
+ local sibling=""
216
+ if [[ -x "scripts/architecture-queue.sh" ]]; then
217
+ bash scripts/architecture-queue.sh "$@"
218
+ return $?
219
+ fi
220
+ sibling="$(helper_sibling architecture-queue.sh || true)"
221
+ if [[ -n "$sibling" ]]; then
222
+ bash "$sibling" "$@"
223
+ return $?
224
+ fi
225
+ return 127
226
+ }
227
+
228
+ architecture_queue_available() {
229
+ [[ -x "scripts/architecture-queue.sh" ]] && return 0
230
+ helper_sibling architecture-queue.sh >/dev/null 2>&1 && return 0
231
+ return 1
232
+ }
233
+
234
+ run_capability_resolver() {
235
+ local sibling=""
236
+ if command -v bun >/dev/null 2>&1 && [[ -f "scripts/capability-resolver.ts" ]]; then
237
+ bun scripts/capability-resolver.ts "$@"
238
+ return $?
239
+ fi
240
+ sibling="$(helper_sibling capability-resolver.ts || true)"
241
+ if command -v bun >/dev/null 2>&1 && [[ -n "$sibling" ]]; then
242
+ bun "$sibling" "$@"
243
+ return $?
244
+ fi
245
+ return 127
246
+ }
247
+
248
+ if ! architecture_queue_available; then
202
249
  if [[ "$mode" == "strict" ]]; then
203
- echo "[ArchitectureSync] strict gate failed: missing scripts/architecture-queue.sh" >&2
250
+ echo "[ArchitectureSync] strict gate failed: missing architecture-queue helper" >&2
204
251
  exit 1
205
252
  fi
206
- echo "[ArchitectureSync] WARN: missing scripts/architecture-queue.sh; skipping advisory freshness gate" >&2
253
+ echo "[ArchitectureSync] WARN: missing architecture-queue helper; skipping advisory freshness gate" >&2
207
254
  exit 0
208
255
  fi
209
256
 
210
- if ! bash scripts/architecture-queue.sh reindex --check >/dev/null; then
211
- echo "[ArchitectureSync] architecture request index is stale; run bash scripts/architecture-queue.sh reindex" >&2
257
+ if ! run_architecture_queue reindex --check >/dev/null; then
258
+ echo "[ArchitectureSync] architecture request index is stale; run repo-harness run architecture-queue reindex" >&2
212
259
  exit 1
213
260
  fi
214
261
 
@@ -221,12 +268,12 @@ if [[ "$mode" == "off" ]]; then
221
268
  exit 0
222
269
  fi
223
270
 
224
- if ! command -v bun >/dev/null 2>&1 || [[ ! -f "scripts/capability-resolver.ts" ]]; then
271
+ if ! run_capability_resolver list --format json >/dev/null 2>&1; then
225
272
  if [[ "$mode" == "strict" ]]; then
226
- echo "[ArchitectureSync] strict gate failed: missing bun or scripts/capability-resolver.ts" >&2
273
+ echo "[ArchitectureSync] strict gate failed: missing capability-resolver helper" >&2
227
274
  exit 1
228
275
  fi
229
- echo "[ArchitectureSync] WARN: missing bun or scripts/capability-resolver.ts; skipping advisory freshness gate" >&2
276
+ echo "[ArchitectureSync] WARN: missing capability-resolver helper; skipping advisory freshness gate" >&2
230
277
  exit 0
231
278
  fi
232
279
 
@@ -240,7 +287,7 @@ if [[ -z "$changed_files" ]]; then
240
287
  exit 0
241
288
  fi
242
289
 
243
- matches_json="$(printf '%s\n' "$changed_files" | bun scripts/capability-resolver.ts match --paths-from - --format json)"
290
+ matches_json="$(printf '%s\n' "$changed_files" | run_capability_resolver match --paths-from - --format json)"
244
291
  capabilities="$(
245
292
  MATCHES_JSON="$matches_json" node -e '
246
293
  const matches = JSON.parse(process.env.MATCHES_JSON || "[]");
@@ -15,7 +15,7 @@ fi
15
15
  issues=0
16
16
  files="$(
17
17
  find . \
18
- \( -path './.git' -o -path './node_modules' -o -path './_ref' -o -path './_ops' -o -path './.worktrees' \) -prune -o \
18
+ \( -path './.git' -o -path './node_modules' -o -path './_ref' -o -path './_ops' -o -path './.worktrees' -o -path './.video-agent-refactor-backup' -o -path './.ai/harness/archive' -o -path './.ai/harness/backups' -o -path './.repo-harness' \) -prune -o \
19
19
  -type f \( -name 'AGENTS.md' -o -name 'CLAUDE.md' \) -print \
20
20
  | sort
21
21
  )"
@@ -29,8 +29,9 @@ scan_pattern() {
29
29
  local label="$1"
30
30
  local regex="$2"
31
31
  local match
32
+ local benign_negative='(never|do not|don'\''t|must not|should not)[^:;.!?]*(print|show|copy|upload|send|read|cat)'
32
33
 
33
- match="$(printf '%s\n' "$files" | xargs grep -Eni "$regex" 2>/dev/null | head -1 || true)"
34
+ match="$(printf '%s\n' "$files" | xargs grep -Eni "$regex" 2>/dev/null | grep -Eiv "$benign_negative" | head -1 || true)"
34
35
  if [[ -n "$match" ]]; then
35
36
  echo "[ContextScan] ${label}: ${match}"
36
37
  issues=$((issues + 1))
@@ -101,6 +101,15 @@ The wrapper maps repo-harness input to `oracle --engine browser --browser-archiv
101
101
 
102
102
  The oracle binary is resolved in a fixed, auditable order — `--oracle-bin`, then `REPO_HARNESS_ORACLE_BIN`, then repo-local `node_modules/.bin/oracle`, then `oracle` on `PATH`. A missing binary fails with `ORACLE_NOT_INSTALLED`; explicitly configured binaries (`--oracle-bin` or `REPO_HARNESS_ORACLE_BIN`) fail closed when invalid and do not silently fall through to the next source. repo-harness never implicitly downloads or `npx`-executes an unpinned oracle. `browser-doctor --provider oracle --json` runs `--help`, `--debug-help`, `--version`, plus an isolated `--browser-thinking-time` dry-run parser probe, and reports `installed`, resolved `binary`, `version`, `nodeCompatible`, a `capabilities` map (`browserEngine`, `writeOutput`, `browserFollowup`, `sessionFollowup`, `browserArchive`, `browserModelStrategy`, `browserCookiePath`, `browserThinkingTime`, `chatgptUrl`, `heartbeat`), and opt-in `agent_actions` when a GPT Pro setup repair can install, upgrade, or re-point the selected pinned external CLI; `status:"ready"` requires every capability for every flag repo-harness may send at runtime.
103
103
 
104
+ When a ChatGPT MCP Connector app must be active for read-back, use `--chatgpt-app <serverName>` with the server name recorded by `repo-harness mcp doctor --repo <repo> --json` under `chatgpt.serverName`. repo-harness maps that to Oracle `--browser-app <serverName>` so Oracle selects the composer app before submitting the prompt. This is an opt-in capability: it is reported under `oracle.optionalCapabilities.browserAppPreselect` and is required only when `--chatgpt-app` is present. If the selected Oracle binary lacks `--browser-app`, the run fails before prompt submission with `ORACLE_APP_PRESELECT_UNSUPPORTED`; do not rely on plain prompt text such as `@serverName` as evidence that ChatGPT exposed MCP tools.
105
+
106
+ App selection and tool availability are separate gates. `--chatgpt-app` only
107
+ selects the Connector in the composer; ChatGPT can still see a stale scanned
108
+ tool schema. If a run proves the app is selected but ChatGPT reports a specific
109
+ tool unavailable, compare the live MCP `/mcp` `tools/list` against the
110
+ Connector's visible tools and use ChatGPT Connector **Scan Tools** to refresh the
111
+ schema.
112
+
104
113
  Long Oracle browser runs default to `--heartbeat 59`. repo-harness streams Oracle diagnostics and heartbeat lines to stderr while preserving stdout for the final JSON payload, so humans and agents get a periodic liveness signal without breaking automation that parses command output.
105
114
 
106
115
  Oracle browser mode supports model selection through `--model` and thinking intensity through `--browser-thinking-time <light|standard|extended|heavy>`. repo-harness maps its `--thinking` value directly to that Oracle browser flag after doctor has verified parser support. Oracle also supports `--browser-manual-login`, but repo-harness intentionally does not send it on the bound-profile path because it skips cookie copy and would make the selected Chrome profile cookie DB non-authoritative.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repo-harness",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Installs, migrates, audits, and repairs repo-local agentic development harnesses",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -71,26 +71,59 @@ index_file="docs/architecture/index.md"
71
71
  requests_dir="docs/architecture/requests"
72
72
  event_file=".ai/harness/architecture/events.jsonl"
73
73
 
74
+ helper_sibling() {
75
+ local helper_name="$1"
76
+ local helper_dir=""
77
+ if [[ -n "${REPO_HARNESS_HELPER_SOURCE_PATH:-}" ]]; then
78
+ helper_dir="$(dirname "$REPO_HARNESS_HELPER_SOURCE_PATH")"
79
+ fi
80
+ if [[ -n "$helper_dir" && -f "$helper_dir/$helper_name" ]]; then
81
+ printf '%s\n' "$helper_dir/$helper_name"
82
+ return 0
83
+ fi
84
+ return 1
85
+ }
86
+
74
87
  architecture_event() {
88
+ local sibling=""
75
89
  if command -v bun >/dev/null 2>&1 && [[ -f "scripts/architecture-event.ts" ]]; then
76
90
  bun scripts/architecture-event.ts "$@"
77
91
  return $?
78
92
  fi
93
+ sibling="$(helper_sibling architecture-event.ts || true)"
94
+ if command -v bun >/dev/null 2>&1 && [[ -n "$sibling" ]]; then
95
+ bun "$sibling" "$@"
96
+ return $?
97
+ fi
79
98
  return 127
80
99
  }
81
100
 
82
101
  architecture_event_required() {
83
- if ! command -v bun >/dev/null 2>&1; then
84
- echo "architecture-queue: bun is required for $command_name" >&2
85
- return 127
86
- fi
87
- if [[ ! -f "scripts/architecture-event.ts" ]]; then
88
- echo "architecture-queue: missing scripts/architecture-event.ts" >&2
102
+ if ! architecture_event safe-token --value probe >/dev/null 2>&1; then
103
+ echo "architecture-queue: missing architecture-event helper" >&2
89
104
  return 127
90
105
  fi
91
106
  return 0
92
107
  }
93
108
 
109
+ capability_resolver() {
110
+ local sibling=""
111
+ if command -v bun >/dev/null 2>&1 && [[ -f "scripts/capability-resolver.ts" ]]; then
112
+ bun scripts/capability-resolver.ts "$@"
113
+ return $?
114
+ fi
115
+ sibling="$(helper_sibling capability-resolver.ts || true)"
116
+ if command -v bun >/dev/null 2>&1 && [[ -n "$sibling" ]]; then
117
+ bun "$sibling" "$@"
118
+ return $?
119
+ fi
120
+ return 127
121
+ }
122
+
123
+ capability_resolver_available() {
124
+ capability_resolver list --format json >/dev/null 2>&1
125
+ }
126
+
94
127
  json_escape() {
95
128
  local value="$1"
96
129
  value="${value//\\/\\\\}"
@@ -404,7 +437,7 @@ status_command() {
404
437
  return 0
405
438
  ;;
406
439
  strict)
407
- if ! command -v bun >/dev/null 2>&1 || [[ ! -f "scripts/architecture-event.ts" || ! -f "scripts/capability-resolver.ts" ]]; then
440
+ if ! architecture_event_required >/dev/null 2>&1 || ! capability_resolver_available; then
408
441
  echo "[ArchitectureQueue] strict gate failed: missing queue dependencies" >&2
409
442
  return 1
410
443
  fi
@@ -440,15 +473,15 @@ record_command() {
440
473
  exit 0
441
474
  fi
442
475
 
443
- if ! command -v bun >/dev/null 2>&1 || [[ ! -f "scripts/architecture-event.ts" ]]; then
444
- echo "[ArchitectureQueue] WARN: bun and scripts/architecture-event.ts are required to record $rel_path; skipping advisory queue update"
476
+ if ! architecture_event_required >/dev/null 2>&1; then
477
+ echo "[ArchitectureQueue] WARN: architecture-event helper is required to record $rel_path; skipping advisory queue update"
445
478
  exit 0
446
479
  fi
447
480
 
448
481
  capability_match=""
449
- if [[ -f "scripts/capability-resolver.ts" ]]; then
482
+ if capability_resolver_available; then
450
483
  resolver_stderr="$(mktemp)"
451
- if ! capability_match="$(bun scripts/capability-resolver.ts match --path "$rel_path" --format json 2>"$resolver_stderr")"; then
484
+ if ! capability_match="$(capability_resolver match --path "$rel_path" --format json 2>"$resolver_stderr")"; then
452
485
  [[ -n "$capability_match" ]] && echo "$capability_match" >&2
453
486
  cat "$resolver_stderr" >&2
454
487
  rm -f "$resolver_stderr"
@@ -475,7 +508,7 @@ record_command() {
475
508
  matched_prefix="$(json_get "$capability_match" "matched_prefix")"
476
509
  capability_id="$(json_get "$capability_match" "capability_id")"
477
510
  capability_resolved="true"
478
- elif [[ ! -f "scripts/capability-resolver.ts" ]]; then
511
+ elif ! capability_resolver_available; then
479
512
  functional_block="$(match_functional_block "$rel_path")"
480
513
  matched_prefix="$functional_block"
481
514
  capability_id="$(safe_token "$functional_block")"
@@ -90,6 +90,19 @@ try {
90
90
  printf '%s' "${value:-$default_value}"
91
91
  }
92
92
 
93
+ helper_sibling() {
94
+ local helper_name="$1"
95
+ local helper_dir=""
96
+ if [[ -n "${REPO_HARNESS_HELPER_SOURCE_PATH:-}" ]]; then
97
+ helper_dir="$(dirname "$REPO_HARNESS_HELPER_SOURCE_PATH")"
98
+ fi
99
+ if [[ -n "$helper_dir" && -f "$helper_dir/$helper_name" ]]; then
100
+ printf '%s\n' "$helper_dir/$helper_name"
101
+ return 0
102
+ fi
103
+ return 1
104
+ }
105
+
93
106
  severity_rank() {
94
107
  case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in
95
108
  critical) printf '4' ;;
@@ -198,17 +211,51 @@ case "$mode" in
198
211
  ;;
199
212
  esac
200
213
 
201
- if [[ ! -x "scripts/architecture-queue.sh" ]]; then
214
+ run_architecture_queue() {
215
+ local sibling=""
216
+ if [[ -x "scripts/architecture-queue.sh" ]]; then
217
+ bash scripts/architecture-queue.sh "$@"
218
+ return $?
219
+ fi
220
+ sibling="$(helper_sibling architecture-queue.sh || true)"
221
+ if [[ -n "$sibling" ]]; then
222
+ bash "$sibling" "$@"
223
+ return $?
224
+ fi
225
+ return 127
226
+ }
227
+
228
+ architecture_queue_available() {
229
+ [[ -x "scripts/architecture-queue.sh" ]] && return 0
230
+ helper_sibling architecture-queue.sh >/dev/null 2>&1 && return 0
231
+ return 1
232
+ }
233
+
234
+ run_capability_resolver() {
235
+ local sibling=""
236
+ if command -v bun >/dev/null 2>&1 && [[ -f "scripts/capability-resolver.ts" ]]; then
237
+ bun scripts/capability-resolver.ts "$@"
238
+ return $?
239
+ fi
240
+ sibling="$(helper_sibling capability-resolver.ts || true)"
241
+ if command -v bun >/dev/null 2>&1 && [[ -n "$sibling" ]]; then
242
+ bun "$sibling" "$@"
243
+ return $?
244
+ fi
245
+ return 127
246
+ }
247
+
248
+ if ! architecture_queue_available; then
202
249
  if [[ "$mode" == "strict" ]]; then
203
- echo "[ArchitectureSync] strict gate failed: missing scripts/architecture-queue.sh" >&2
250
+ echo "[ArchitectureSync] strict gate failed: missing architecture-queue helper" >&2
204
251
  exit 1
205
252
  fi
206
- echo "[ArchitectureSync] WARN: missing scripts/architecture-queue.sh; skipping advisory freshness gate" >&2
253
+ echo "[ArchitectureSync] WARN: missing architecture-queue helper; skipping advisory freshness gate" >&2
207
254
  exit 0
208
255
  fi
209
256
 
210
- if ! bash scripts/architecture-queue.sh reindex --check >/dev/null; then
211
- echo "[ArchitectureSync] architecture request index is stale; run bash scripts/architecture-queue.sh reindex" >&2
257
+ if ! run_architecture_queue reindex --check >/dev/null; then
258
+ echo "[ArchitectureSync] architecture request index is stale; run repo-harness run architecture-queue reindex" >&2
212
259
  exit 1
213
260
  fi
214
261
 
@@ -221,12 +268,12 @@ if [[ "$mode" == "off" ]]; then
221
268
  exit 0
222
269
  fi
223
270
 
224
- if ! command -v bun >/dev/null 2>&1 || [[ ! -f "scripts/capability-resolver.ts" ]]; then
271
+ if ! run_capability_resolver list --format json >/dev/null 2>&1; then
225
272
  if [[ "$mode" == "strict" ]]; then
226
- echo "[ArchitectureSync] strict gate failed: missing bun or scripts/capability-resolver.ts" >&2
273
+ echo "[ArchitectureSync] strict gate failed: missing capability-resolver helper" >&2
227
274
  exit 1
228
275
  fi
229
- echo "[ArchitectureSync] WARN: missing bun or scripts/capability-resolver.ts; skipping advisory freshness gate" >&2
276
+ echo "[ArchitectureSync] WARN: missing capability-resolver helper; skipping advisory freshness gate" >&2
230
277
  exit 0
231
278
  fi
232
279
 
@@ -240,7 +287,7 @@ if [[ -z "$changed_files" ]]; then
240
287
  exit 0
241
288
  fi
242
289
 
243
- matches_json="$(printf '%s\n' "$changed_files" | bun scripts/capability-resolver.ts match --paths-from - --format json)"
290
+ matches_json="$(printf '%s\n' "$changed_files" | run_capability_resolver match --paths-from - --format json)"
244
291
  capabilities="$(
245
292
  MATCHES_JSON="$matches_json" node -e '
246
293
  const matches = JSON.parse(process.env.MATCHES_JSON || "[]");