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 +3 -3
- package/README.fr.md +3 -3
- package/README.ja.md +3 -3
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/assets/skill-commands/repo-harness-gptpro/SKILL.md +26 -3
- package/assets/skill-version.json +6 -2
- package/assets/templates/helpers/architecture-queue.sh +45 -12
- package/assets/templates/helpers/check-architecture-sync.sh +56 -9
- package/assets/templates/helpers/check-context-files.sh +3 -2
- package/docs/repo-harness-chatgpt-browser-engine.md +9 -0
- package/package.json +1 -1
- package/scripts/architecture-queue.sh +45 -12
- package/scripts/check-architecture-sync.sh +56 -9
- package/scripts/check-context-files.sh +3 -2
- package/src/cli/chatgpt-browser/engine.ts +20 -1
- package/src/cli/chatgpt-browser/oracle-provider.ts +22 -0
- package/src/cli/chatgpt-browser/session-store.ts +2 -0
- package/src/cli/chatgpt-browser/types.ts +2 -0
- package/src/cli/commands/adopt-plan.ts +3 -0
- package/src/cli/commands/chatgpt.ts +6 -0
- package/src/cli/commands/mcp.ts +4 -0
- package/src/cli/index.ts +2 -0
- package/src/cli/mcp/auth.ts +47 -21
- package/src/cli/mcp/paths.ts +20 -6
- package/src/cli/mcp/policy.ts +21 -9
- package/src/cli/mcp/server.ts +2 -0
- package/src/cli/mcp/setup.ts +172 -25
- package/src/cli/mcp/tools.ts +232 -36
- package/src/cli/mcp/transports/http.ts +5 -3
- package/src/cli/mcp/types.ts +1 -0
- package/src/core/adoption/plan.ts +4 -2
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.
|
|
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.
|
|
423
|
-
- Generated workflow stamp: `repo-harness@0.7.
|
|
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.
|
|
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.
|
|
428
|
-
- Generated workflow stamp : `repo-harness@0.7.
|
|
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.
|
|
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.
|
|
402
|
-
- Generated workflow stamp:`repo-harness@0.7.
|
|
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.
|
|
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.
|
|
497
|
-
- Generated workflow stamp: `repo-harness@0.7.
|
|
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.
|
|
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.
|
|
441
|
-
- Generated workflow stamp:`repo-harness@0.7.
|
|
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
|
|
40
|
-
13.
|
|
41
|
-
14.
|
|
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
|
-
"templateVersion": "0.7.
|
|
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 !
|
|
84
|
-
echo "architecture-queue:
|
|
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 !
|
|
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 !
|
|
444
|
-
echo "[ArchitectureQueue] WARN:
|
|
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
|
|
482
|
+
if capability_resolver_available; then
|
|
450
483
|
resolver_stderr="$(mktemp)"
|
|
451
|
-
if ! capability_match="$(
|
|
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
|
|
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
|
-
|
|
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
|
|
250
|
+
echo "[ArchitectureSync] strict gate failed: missing architecture-queue helper" >&2
|
|
204
251
|
exit 1
|
|
205
252
|
fi
|
|
206
|
-
echo "[ArchitectureSync] WARN: missing
|
|
253
|
+
echo "[ArchitectureSync] WARN: missing architecture-queue helper; skipping advisory freshness gate" >&2
|
|
207
254
|
exit 0
|
|
208
255
|
fi
|
|
209
256
|
|
|
210
|
-
if !
|
|
211
|
-
echo "[ArchitectureSync] architecture request index is stale; run
|
|
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 !
|
|
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
|
|
273
|
+
echo "[ArchitectureSync] strict gate failed: missing capability-resolver helper" >&2
|
|
227
274
|
exit 1
|
|
228
275
|
fi
|
|
229
|
-
echo "[ArchitectureSync] WARN: missing
|
|
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" |
|
|
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
|
@@ -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 !
|
|
84
|
-
echo "architecture-queue:
|
|
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 !
|
|
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 !
|
|
444
|
-
echo "[ArchitectureQueue] WARN:
|
|
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
|
|
482
|
+
if capability_resolver_available; then
|
|
450
483
|
resolver_stderr="$(mktemp)"
|
|
451
|
-
if ! capability_match="$(
|
|
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
|
|
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
|
-
|
|
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
|
|
250
|
+
echo "[ArchitectureSync] strict gate failed: missing architecture-queue helper" >&2
|
|
204
251
|
exit 1
|
|
205
252
|
fi
|
|
206
|
-
echo "[ArchitectureSync] WARN: missing
|
|
253
|
+
echo "[ArchitectureSync] WARN: missing architecture-queue helper; skipping advisory freshness gate" >&2
|
|
207
254
|
exit 0
|
|
208
255
|
fi
|
|
209
256
|
|
|
210
|
-
if !
|
|
211
|
-
echo "[ArchitectureSync] architecture request index is stale; run
|
|
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 !
|
|
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
|
|
273
|
+
echo "[ArchitectureSync] strict gate failed: missing capability-resolver helper" >&2
|
|
227
274
|
exit 1
|
|
228
275
|
fi
|
|
229
|
-
echo "[ArchitectureSync] WARN: missing
|
|
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" |
|
|
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 || "[]");
|