@lannguyensi/harness 0.14.0 → 0.16.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/CHANGELOG.md +45 -0
- package/README.md +20 -2
- package/dist/cli/doctor/format.js +24 -0
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/index.d.ts +7 -0
- package/dist/cli/doctor/index.js +10 -0
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/rogue-ledger.d.ts +25 -0
- package/dist/cli/doctor/rogue-ledger.js +106 -0
- package/dist/cli/doctor/rogue-ledger.js.map +1 -0
- package/dist/cli/doctor/types.d.ts +10 -1
- package/dist/cli/doctor/types.js.map +1 -1
- package/dist/cli/index.js +177 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/composer.d.ts +29 -0
- package/dist/cli/init/composer.js +377 -0
- package/dist/cli/init/composer.js.map +1 -0
- package/dist/cli/init/dependencies.d.ts +25 -0
- package/dist/cli/init/dependencies.js +100 -10
- package/dist/cli/init/dependencies.js.map +1 -1
- package/dist/cli/init/index.d.ts +18 -1
- package/dist/cli/init/index.js +17 -7
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/interactive.d.ts +31 -2
- package/dist/cli/init/interactive.js +321 -79
- package/dist/cli/init/interactive.js.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -1
- package/dist/cli/init/templates.js +60 -9
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/pack/hook-branch-protection.d.ts +30 -0
- package/dist/cli/pack/hook-branch-protection.js +279 -0
- package/dist/cli/pack/hook-branch-protection.js.map +1 -0
- package/dist/cli/pack/hook-codex-pre-tool-use.js +3 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.d.ts +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +42 -3
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/understanding-report-schema-hint.d.ts +13 -0
- package/dist/cli/pack/understanding-report-schema-hint.js +54 -0
- package/dist/cli/pack/understanding-report-schema-hint.js.map +1 -0
- package/dist/cli/session-start/branch-check.d.ts +44 -0
- package/dist/cli/session-start/branch-check.js +165 -0
- package/dist/cli/session-start/branch-check.js.map +1 -0
- package/dist/cli/uninstall/index.d.ts +68 -0
- package/dist/cli/uninstall/index.js +586 -0
- package/dist/cli/uninstall/index.js.map +1 -0
- package/dist/cli/uninstall/snapshot.d.ts +40 -0
- package/dist/cli/uninstall/snapshot.js +34 -0
- package/dist/cli/uninstall/snapshot.js.map +1 -0
- package/dist/cli/validate/checks.d.ts +1 -1
- package/dist/cli/validate/checks.js +1 -7
- package/dist/cli/validate/checks.js.map +1 -1
- package/dist/io/harness-lock.js +1 -9
- package/dist/io/harness-lock.js.map +1 -1
- package/dist/policies/ledger-client.js +3 -9
- package/dist/policies/ledger-client.js.map +1 -1
- package/dist/policies/producers.d.ts +12 -0
- package/dist/policies/producers.js +61 -0
- package/dist/policies/producers.js.map +1 -0
- package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +47 -0
- package/dist/policy-packs/builtin/branch-protection-runtime.js +92 -0
- package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -0
- package/dist/policy-packs/builtin/branch-protection.d.ts +9 -0
- package/dist/policy-packs/builtin/branch-protection.js +146 -0
- package/dist/policy-packs/builtin/branch-protection.js.map +1 -0
- package/dist/policy-packs/registry.d.ts +1 -1
- package/dist/policy-packs/registry.js +10 -3
- package/dist/policy-packs/registry.js.map +1 -1
- package/dist/runtime/expand-home.d.ts +14 -0
- package/dist/runtime/expand-home.js +54 -0
- package/dist/runtime/expand-home.js.map +1 -0
- package/dist/runtime/intercept.js +13 -2
- package/dist/runtime/intercept.js.map +1 -1
- package/dist/runtime/ledger-add.js +10 -3
- package/dist/runtime/ledger-add.js.map +1 -1
- package/dist/runtime/ledger-record.js +11 -10
- package/dist/runtime/ledger-record.js.map +1 -1
- package/dist/schema/index.d.ts +281 -101
- package/dist/schema/permission-profiles.d.ts +125 -125
- package/dist/schema/policies.d.ts +261 -0
- package/dist/schema/policies.js +50 -0
- package/dist/schema/policies.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const MINIMAL_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template minimal`.\n#\n# This is the empty-but-valid manifest. Run `harness validate` to confirm it\n# parses, then add entries under the five top-level keys:\n#\n# grounding: evidence-ledger + claim-gate config (see docs/ARCHITECTURE.md \u00A72)\n# tools: mcp / cli / skills / builtin inventory (\u00A73)\n# memory: directories, retention, scopes (\u00A74)\n# hooks: event-bound shell commands (\u00A75)\n# policies: named rules that bind hooks to triggers (\u00A76)\n#\n# Phase 2 verbs to add entries safely: `harness add mcp <name> ...`,\n# `harness add cli`, `harness add hook`, `harness add skill`.\n# Per-machine overrides live at ~/.claude/machines/<discriminator>.harness.overrides.yaml\n# (ARCHITECTURE.md \u00A78) for paths that vary per host.\n#\n# Docs: https://github.com/LanNguyenSi/harness\n\nversion: 1\n";
|
|
2
|
-
export declare const FULL_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template full`. The reference manifest:\n# every example policy from docs/examples/full-manifest.yaml wired through\n# the generic `harness policy intercept` engine, so no external shell\n# scripts under ~/.claude/hooks/ are required.\n#\n# Canonical source for the policy + policy_packs sections is\n# docs/examples/full-manifest.yaml. A parity vitest\n# (tests/cli/init-full-template-parity.test.ts) fails the build if the\n# two diverge on policy names or load-bearing fields.\n#\n# What you still need on PATH (the wizard offers to `npm i -g` these on\n# init): agent-tasks-mcp-bridge, grounding-mcp, memory-router-*,\n# understanding-gate-claude-*. Optional add-on: a local codebase-oracle\n# MCP server (see comment under tools.mcp below).\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n policies_source: ~/.claude/harness.d/policies/claim-gate.yaml\n\ntools:\n mcp:\n # codebase-oracle (the Pandora RAG MCP server) is intentionally NOT\n # in this default. The npm name `codebase-oracle` is already taken\n # by an unrelated CLI, and the Pandora variant is not yet published\n # under a non-colliding scope. Operators who run from a local\n # checkout can add it back with (note: `harness add` splits the\n # command on commas, not whitespace):\n # harness add mcp codebase-oracle \\\n # --command 'npx,tsx,~/git/pandora/codebase-oracle/src/mcp-server.ts'\n - name: agent-tasks\n # Zero-setup entry: `@agent-tasks/mcp-bridge` exposes the\n # `agent-tasks-mcp-bridge` binary on PATH. The bridge owns token\n # storage and defaults to the hosted backend; override with\n # `AGENT_TASKS_BASE_URL` / `AGENT_TASKS_TOKEN` for self-hosted.\n # `min_version` floor: 0.6.0 added the `--version` short-circuit\n # the doctor probe needs (PR agent-tasks/240, release-cut PR 241).\n # Bump the floor whenever a fix you depend on lands; loose floors\n # are fine, the point is the drift signal not pinning a specific cut.\n command: [agent-tasks-mcp-bridge]\n min_version: \"0.6.0\"\n health:\n verb: projects_list\n timeout_ms: 5000\n enabled: true\n - name: grounding-mcp\n # Published bin from `@lannguyensi/grounding-mcp`. No env is set:\n # the bundled default resolves to `~/.evidence-ledger/ledger.db`\n # via os.homedir() at startup. Passing a literal tilde in env\n # bypasses shell expansion and creates rogue cwd-relative DB files\n # (see agent-tasks/42d224a6 incident). `min_version` floor: 0.2.0\n # added the `--version` short-circuit the doctor probe needs (PR\n # agent-grounding/76, release-cut PR 77).\n command: [grounding-mcp]\n min_version: \"0.2.0\"\n health:\n verb: ledger_status\n timeout_ms: 5000\n enabled: true\n\n cli:\n - name: gh\n binary: gh\n required: true\n\n skills:\n enabled:\n - simplify\n - init\n - review\n - security-review\n source_dirs:\n - ~/.claude/skills\n\n builtin:\n known: [Read, Edit, Write, Bash, Agent, Skill, TaskCreate, Glob, Grep]\n\nmemory:\n directories:\n - path: ~/.claude/projects/{project}/memory\n scope: project\n router:\n # Published bin from `@lannguyensi/memory-router`.\n # `min_version` floor: 0.3.0 added the `--version` short-circuit\n # the doctor probe needs (PR agent-memory/40, release-cut PR 41).\n command: [memory-router-user-prompt-submit]\n min_version: \"0.3.0\"\n enabled: true\n retention:\n staleness_days: 180\n broken_refs: warn\n scopes:\n default: project\n allowed: [project, user]\n\n# All PreToolUse hooks share the generic `harness policy intercept` CLI\n# entrypoint. The engine reads the tool event on stdin, evaluates whichever\n# policy below has a matching trigger (`match` + optional `bash_match`),\n# and emits Claude Code's deny envelope when the required ledger tag is\n# absent. No external shell scripts are required.\n#\n# The `git-preflight` SessionStart hook is the producer side of the\n# `preflight-before-*` policies: `harness session-start preflight` runs\n# agent-preflight against the session cwd and, on a ready:true result,\n# records `preflight:${REPO}` to the evidence ledger. It needs the\n# `preflight` binary on PATH (`npm i -g @lannguyensi/agent-preflight`); when\n# that is absent the hook logs to stderr and exits 0, so the session is\n# never broken \u2014 the preflight gates just stay closed until a tag is\n# produced some other way.\nhooks:\n - name: git-preflight\n event: SessionStart\n command: harness session-start preflight\n blocking: false\n budget_ms: 30000\n\n - name: require-review-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-dogfood-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)'\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-preflight-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b'\n command: harness policy intercept\n blocking: hard\n budget_ms: 1000\n\n - name: require-review-subagent-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_create\"\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-preflight-push-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b'\n command: harness policy intercept\n blocking: hard\n budget_ms: 1000\n\npolicies:\n - name: review-before-merge\n description: Block PR merges unless a ledger entry tagged review:<pr-number> exists for this session.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n extract:\n PR_NUMBER: \"toolArgs.prNumber\"\n requires:\n ledger_tag: \"review:${PR_NUMBER}\"\n hook: require-review-evidence\n enforcement: block\n\n - name: dogfood-before-release\n description: Block npm publish / git tag v* without a recent dogfood ledger entry.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)'\n requires:\n ledger_tag: \"dogfood:${SESSION_ID}\"\n within: 24h\n hook: require-dogfood-evidence\n enforcement: block\n\n - name: two-reviewers-required\n description: At least two distinct reviewer ledger entries must exist for the PR.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n extract:\n PR_NUMBER: \"toolArgs.prNumber\"\n requires:\n ledger_tag: \"review:${PR_NUMBER}\"\n count:\n min: 2\n hook: require-review-evidence\n enforcement: warn\n\n - name: preflight-before-investigation\n description: Block investigative git reads (status/log/diff/branch) when agent-preflight has not run recently with ready:true for the current repo.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b'\n requires:\n ledger_tag: \"preflight:${REPO}\"\n within: 1h\n hook: require-preflight-evidence\n enforcement: block\n\n - name: review-subagent-before-pr-create\n description: Block agent-tasks PR creation unless a review-subagent ledger entry tagged for this task already exists. Forces the rigorous review BEFORE the PR opens, not after.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_create\"\n extract:\n TASK_ID: \"toolArgs.taskId\"\n requires:\n ledger_tag: \"review-subagent:${TASK_ID}\"\n hook: require-review-subagent-evidence\n enforcement: block\n\n - name: preflight-before-push\n description: Block git push unless a fresh preflight ledger entry exists for the current branch. Catches the stale-checkout class of incident at the last reversible step.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b'\n requires:\n ledger_tag: \"preflight:${BRANCH}\"\n within: 10m\n hook: require-preflight-push-evidence\n enforcement: block\n\n# Full inherits the Solo/Team understanding-gate stack: the Stop hook\n# persists each Understanding Report and the PreToolUse pre-tool-use\n# blocker refuses Edit/Write/Bash until the report is approved. Drop\n# this block if you want the reference policies above without the\n# baseline gate.\npolicy_packs:\n - name: understanding-before-execution\n source: builtin\n enabled: true\n description: Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.\n config:\n mode: grill_me\n";
|
|
2
|
+
export declare const FULL_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template full`. The reference manifest:\n# every example policy from docs/examples/full-manifest.yaml wired through\n# the generic `harness policy intercept` engine, so no external shell\n# scripts under ~/.claude/hooks/ are required.\n#\n# Canonical source for the policy + policy_packs sections is\n# docs/examples/full-manifest.yaml. A parity vitest\n# (tests/cli/init-full-template-parity.test.ts) fails the build if the\n# two diverge on policy names or load-bearing fields.\n#\n# What you still need on PATH (the wizard offers to `npm i -g` these on\n# init): agent-tasks-mcp-bridge, grounding-mcp, memory-router-*,\n# understanding-gate-claude-*.\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n policies_source: ~/.claude/harness.d/policies/claim-gate.yaml\n\ntools:\n mcp:\n # codebase-oracle (the Pandora RAG MCP server) is intentionally NOT\n # in the Full default. It is published as\n # `@lannguyensi/codebase-oracle` and works fine standalone, but it\n # is an opinionated workflow add-on (multi-repo semantic search)\n # rather than infrastructure harness itself assumes. Operators who\n # want it wire it explicitly:\n # npm i -g @lannguyensi/codebase-oracle\n # harness add mcp codebase-oracle --command codebase-oracle,mcp\n # Set ORACLE_SCAN_ROOT (absolute path; tilde is not expanded by the\n # MCP env block) and OPENAI_API_KEY (or switch providers via\n # ORACLE_LLM_PROVIDER) before the first call.\n - name: agent-tasks\n # Zero-setup entry: `@agent-tasks/mcp-bridge` exposes the\n # `agent-tasks-mcp-bridge` binary on PATH. The bridge owns token\n # storage and defaults to the hosted backend; override with\n # `AGENT_TASKS_BASE_URL` / `AGENT_TASKS_TOKEN` for self-hosted.\n # `min_version` floor: 0.6.0 added the `--version` short-circuit\n # the doctor probe needs (PR agent-tasks/240, release-cut PR 241).\n # Bump the floor whenever a fix you depend on lands; loose floors\n # are fine, the point is the drift signal not pinning a specific cut.\n command: [agent-tasks-mcp-bridge]\n min_version: \"0.6.0\"\n health:\n verb: projects_list\n timeout_ms: 5000\n enabled: true\n - name: grounding-mcp\n # Published bin from `@lannguyensi/grounding-mcp`. No env is set:\n # the bundled default resolves to `~/.evidence-ledger/ledger.db`\n # via os.homedir() at startup. Passing a literal tilde in env\n # bypasses shell expansion and creates rogue cwd-relative DB files\n # (see agent-tasks/42d224a6 incident). `min_version` floor: 0.2.0\n # added the `--version` short-circuit the doctor probe needs (PR\n # agent-grounding/76, release-cut PR 77).\n command: [grounding-mcp]\n min_version: \"0.2.0\"\n health:\n verb: ledger_status\n timeout_ms: 5000\n enabled: true\n\n cli:\n - name: gh\n binary: gh\n required: true\n\n skills:\n enabled:\n - simplify\n - init\n - review\n - security-review\n source_dirs:\n - ~/.claude/skills\n\n builtin:\n known: [Read, Edit, Write, Bash, Agent, Skill, TaskCreate, Glob, Grep]\n\nmemory:\n directories:\n - path: ~/.claude/projects/{project}/memory\n scope: project\n router:\n # Published bin from `@lannguyensi/memory-router`.\n # `min_version` floor: 0.3.0 added the `--version` short-circuit\n # the doctor probe needs (PR agent-memory/40, release-cut PR 41).\n command: [memory-router-user-prompt-submit]\n min_version: \"0.3.0\"\n enabled: true\n retention:\n staleness_days: 180\n broken_refs: warn\n scopes:\n default: project\n allowed: [project, user]\n\n# All PreToolUse hooks share the generic `harness policy intercept` CLI\n# entrypoint. The engine reads the tool event on stdin, evaluates whichever\n# policy below has a matching trigger (`match` + optional `bash_match`),\n# and emits Claude Code's deny envelope when the required ledger tag is\n# absent. No external shell scripts are required.\n#\n# The `git-preflight` SessionStart hook is the producer side of the\n# `preflight-before-*` policies: `harness session-start preflight` runs\n# agent-preflight against the session cwd and, on a ready:true result,\n# records `preflight:${REPO}` to the evidence ledger. It needs the\n# `preflight` binary on PATH (`npm i -g @lannguyensi/agent-preflight`); when\n# that is absent the hook logs to stderr and exits 0, so the session is\n# never broken \u2014 the preflight gates just stay closed until a tag is\n# produced some other way.\nhooks:\n - name: git-preflight\n event: SessionStart\n command: harness session-start preflight\n blocking: false\n budget_ms: 30000\n\n - name: require-review-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-dogfood-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)'\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-preflight-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b'\n command: harness policy intercept\n blocking: hard\n budget_ms: 1000\n\n - name: require-review-subagent-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_create\"\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-preflight-push-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b'\n command: harness policy intercept\n blocking: hard\n budget_ms: 1000\n\npolicies:\n - name: review-before-merge\n description: Block PR merges unless a ledger entry tagged review:<pr-number> exists for this session.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n extract:\n PR_NUMBER: \"toolArgs.prNumber\"\n requires:\n ledger_tag: \"review:${PR_NUMBER}\"\n hook: require-review-evidence\n enforcement: block\n producers:\n - kind: mcp\n verb: mcp__agent-grounding__ledger_add\n example: '{type:\"fact\", content:\"review:${PR_NUMBER} \u2014 <verdict + key findings + nits>\", source:\"Agent(general-purpose) review\"}'\n description: Spawn a review subagent against the PR diff, capture its verdict, then persist a ledger entry tagged with the PR number. The content should be self-contained enough for an auditor to read without re-opening the chat.\n\n - name: dogfood-before-release\n description: Block npm publish / git tag v* without a recent dogfood ledger entry.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)'\n requires:\n ledger_tag: \"dogfood:${SESSION_ID}\"\n within: 24h\n hook: require-dogfood-evidence\n enforcement: block\n producers:\n - kind: mcp\n verb: mcp__agent-grounding__ledger_add\n example: '{type:\"fact\", content:\"dogfood:${SESSION_ID} \u2014 <end-to-end smoke summary against the live system>\", source:\"manual smoke test\"}'\n description: Before tagging or publishing, run the release path end-to-end against the live system (not just unit tests) and persist the result as a session-tagged ledger entry. Document what you exercised (install, CLI happy path, MCP handshake, etc.) so a future auditor can tell whether the smoke covered the change.\n\n - name: two-reviewers-required\n description: At least two distinct reviewer ledger entries must exist for the PR.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n extract:\n PR_NUMBER: \"toolArgs.prNumber\"\n requires:\n ledger_tag: \"review:${PR_NUMBER}\"\n count:\n min: 2\n hook: require-review-evidence\n enforcement: warn\n producers:\n - kind: mcp\n verb: mcp__agent-grounding__ledger_add\n example: '{type:\"fact\", content:\"review:${PR_NUMBER} \u2014 <verdict + key findings + nits>\", source:\"Agent(general-purpose) review (reviewer 2)\"}'\n description: Same shape as review-before-merge but TWO DISTINCT reviewer entries must exist before the gate is satisfied (count.min 2). Distinguish reviewers by source so the count is honest. Warn-level enforcement, so the agent CAN merge with one reviewer but should consider spawning a second for load-bearing changes.\n\n - name: preflight-before-investigation\n description: Block investigative git reads (status/log/diff/branch) when agent-preflight has not run recently with ready:true for the current repo.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b'\n requires:\n ledger_tag: \"preflight:${REPO}\"\n within: 1h\n hook: require-preflight-evidence\n enforcement: block\n producers:\n - kind: bash\n command: harness session-start preflight\n description: Runs agent-preflight against the current cwd; on ready:true, records preflight:${REPO} to the ledger. Standard producer.\n - kind: mcp\n verb: mcp__agent-grounding__ledger_add\n example: '{type:\"fact\", content:\"preflight:${REPO}\", source:\"manual\"}'\n description: Direct ledger write. Use when the Bash hook is locked down (e.g. understanding-gate active) or when the standard producer is unavailable.\n\n - name: review-subagent-before-pr-create\n description: Block agent-tasks PR creation unless a review-subagent ledger entry tagged for this task already exists. Forces the rigorous review BEFORE the PR opens, not after.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_create\"\n extract:\n TASK_ID: \"toolArgs.taskId\"\n requires:\n ledger_tag: \"review-subagent:${TASK_ID}\"\n hook: require-review-subagent-evidence\n enforcement: block\n producers:\n - kind: mcp\n verb: mcp__agent-grounding__ledger_add\n example: '{type:\"fact\", content:\"review-subagent:${TASK_ID} \u2014 <verdict + key findings + nits>\", source:\"Agent(general-purpose) review\"}'\n description: After running a review subagent against the staged diff, persist its verdict + load-bearing findings as a ledger entry tagged with the task UUID. The content should be self-contained enough to audit later without re-reading the chat.\n\n - name: preflight-before-push\n description: Block git push unless a fresh preflight ledger entry exists for the current branch. Catches the stale-checkout class of incident at the last reversible step.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b'\n requires:\n ledger_tag: \"preflight:${BRANCH}\"\n within: 10m\n hook: require-preflight-push-evidence\n enforcement: block\n producers:\n - kind: bash\n command: harness session-start preflight\n description: Runs agent-preflight against the current cwd; on ready:true, records preflight:${BRANCH} to the ledger. Standard producer.\n - kind: mcp\n verb: mcp__agent-grounding__ledger_add\n example: '{type:\"fact\", content:\"preflight:${BRANCH} \u2014 <summary of what is on the branch + smoke results>\", source:\"manual\"}'\n description: Direct ledger write. The branch is the WIP review surface; the content should summarise what is staged + the smoke evidence so a reviewer can audit later without re-reading the chat.\n\n# Full inherits the Solo/Team understanding-gate stack: the Stop hook\n# persists each Understanding Report and the PreToolUse pre-tool-use\n# blocker refuses Edit/Write/Bash until the report is approved. Drop\n# this block if you want the reference policies above without the\n# baseline gate.\npolicy_packs:\n - name: understanding-before-execution\n source: builtin\n enabled: true\n description: Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.\n config:\n mode: grill_me\n # Producers (agent-tasks/25bced52): rendered into the gate's deny\n # envelope by the same engine as policy producers. Constraint at\n # this layer: at-least-one `ask`. Post-v0.14.0 the gate signal\n # is a filesystem marker and the mcp ledger_add path no longer\n # satisfies the gate; the canonical unblock surface is the\n # operator-approval prompt.\n producers:\n - kind: ask\n command: harness approve understanding\n description: \"Bare command, no pipes or chaining. The hook recognises it via isEscapeCommand and emits permissionDecision:ask; the operator's go on that prompt IS the gate approval. Golden path.\"\n - kind: bash\n command: harness approve understanding\n description: Same command from any un-hooked terminal (operator only, not reachable from inside the gated session). Writes the canonical marker at harness.generated/.approvals/${SESSION_ID}.\n";
|
|
3
3
|
export type TemplateName = "minimal" | "full" | "solo" | "team";
|
|
4
4
|
export declare function getTemplate(name: TemplateName): string;
|
|
@@ -34,8 +34,7 @@ export const FULL_TEMPLATE = `# ~/.claude/harness.yaml
|
|
|
34
34
|
#
|
|
35
35
|
# What you still need on PATH (the wizard offers to \`npm i -g\` these on
|
|
36
36
|
# init): agent-tasks-mcp-bridge, grounding-mcp, memory-router-*,
|
|
37
|
-
# understanding-gate-claude-*.
|
|
38
|
-
# MCP server (see comment under tools.mcp below).
|
|
37
|
+
# understanding-gate-claude-*.
|
|
39
38
|
|
|
40
39
|
version: 1
|
|
41
40
|
|
|
@@ -51,13 +50,16 @@ grounding:
|
|
|
51
50
|
tools:
|
|
52
51
|
mcp:
|
|
53
52
|
# codebase-oracle (the Pandora RAG MCP server) is intentionally NOT
|
|
54
|
-
# in
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
53
|
+
# in the Full default. It is published as
|
|
54
|
+
# \`@lannguyensi/codebase-oracle\` and works fine standalone, but it
|
|
55
|
+
# is an opinionated workflow add-on (multi-repo semantic search)
|
|
56
|
+
# rather than infrastructure harness itself assumes. Operators who
|
|
57
|
+
# want it wire it explicitly:
|
|
58
|
+
# npm i -g @lannguyensi/codebase-oracle
|
|
59
|
+
# harness add mcp codebase-oracle --command codebase-oracle,mcp
|
|
60
|
+
# Set ORACLE_SCAN_ROOT (absolute path; tilde is not expanded by the
|
|
61
|
+
# MCP env block) and OPENAI_API_KEY (or switch providers via
|
|
62
|
+
# ORACLE_LLM_PROVIDER) before the first call.
|
|
61
63
|
- name: agent-tasks
|
|
62
64
|
# Zero-setup entry: \`@agent-tasks/mcp-bridge\` exposes the
|
|
63
65
|
# \`agent-tasks-mcp-bridge\` binary on PATH. The bridge owns token
|
|
@@ -194,6 +196,11 @@ policies:
|
|
|
194
196
|
ledger_tag: "review:\${PR_NUMBER}"
|
|
195
197
|
hook: require-review-evidence
|
|
196
198
|
enforcement: block
|
|
199
|
+
producers:
|
|
200
|
+
- kind: mcp
|
|
201
|
+
verb: mcp__agent-grounding__ledger_add
|
|
202
|
+
example: '{type:"fact", content:"review:\${PR_NUMBER} — <verdict + key findings + nits>", source:"Agent(general-purpose) review"}'
|
|
203
|
+
description: Spawn a review subagent against the PR diff, capture its verdict, then persist a ledger entry tagged with the PR number. The content should be self-contained enough for an auditor to read without re-opening the chat.
|
|
197
204
|
|
|
198
205
|
- name: dogfood-before-release
|
|
199
206
|
description: Block npm publish / git tag v* without a recent dogfood ledger entry.
|
|
@@ -206,6 +213,11 @@ policies:
|
|
|
206
213
|
within: 24h
|
|
207
214
|
hook: require-dogfood-evidence
|
|
208
215
|
enforcement: block
|
|
216
|
+
producers:
|
|
217
|
+
- kind: mcp
|
|
218
|
+
verb: mcp__agent-grounding__ledger_add
|
|
219
|
+
example: '{type:"fact", content:"dogfood:\${SESSION_ID} — <end-to-end smoke summary against the live system>", source:"manual smoke test"}'
|
|
220
|
+
description: Before tagging or publishing, run the release path end-to-end against the live system (not just unit tests) and persist the result as a session-tagged ledger entry. Document what you exercised (install, CLI happy path, MCP handshake, etc.) so a future auditor can tell whether the smoke covered the change.
|
|
209
221
|
|
|
210
222
|
- name: two-reviewers-required
|
|
211
223
|
description: At least two distinct reviewer ledger entries must exist for the PR.
|
|
@@ -220,6 +232,11 @@ policies:
|
|
|
220
232
|
min: 2
|
|
221
233
|
hook: require-review-evidence
|
|
222
234
|
enforcement: warn
|
|
235
|
+
producers:
|
|
236
|
+
- kind: mcp
|
|
237
|
+
verb: mcp__agent-grounding__ledger_add
|
|
238
|
+
example: '{type:"fact", content:"review:\${PR_NUMBER} — <verdict + key findings + nits>", source:"Agent(general-purpose) review (reviewer 2)"}'
|
|
239
|
+
description: Same shape as review-before-merge but TWO DISTINCT reviewer entries must exist before the gate is satisfied (count.min 2). Distinguish reviewers by source so the count is honest. Warn-level enforcement, so the agent CAN merge with one reviewer but should consider spawning a second for load-bearing changes.
|
|
223
240
|
|
|
224
241
|
- name: preflight-before-investigation
|
|
225
242
|
description: Block investigative git reads (status/log/diff/branch) when agent-preflight has not run recently with ready:true for the current repo.
|
|
@@ -232,6 +249,14 @@ policies:
|
|
|
232
249
|
within: 1h
|
|
233
250
|
hook: require-preflight-evidence
|
|
234
251
|
enforcement: block
|
|
252
|
+
producers:
|
|
253
|
+
- kind: bash
|
|
254
|
+
command: harness session-start preflight
|
|
255
|
+
description: Runs agent-preflight against the current cwd; on ready:true, records preflight:\${REPO} to the ledger. Standard producer.
|
|
256
|
+
- kind: mcp
|
|
257
|
+
verb: mcp__agent-grounding__ledger_add
|
|
258
|
+
example: '{type:"fact", content:"preflight:\${REPO}", source:"manual"}'
|
|
259
|
+
description: Direct ledger write. Use when the Bash hook is locked down (e.g. understanding-gate active) or when the standard producer is unavailable.
|
|
235
260
|
|
|
236
261
|
- name: review-subagent-before-pr-create
|
|
237
262
|
description: Block agent-tasks PR creation unless a review-subagent ledger entry tagged for this task already exists. Forces the rigorous review BEFORE the PR opens, not after.
|
|
@@ -244,6 +269,11 @@ policies:
|
|
|
244
269
|
ledger_tag: "review-subagent:\${TASK_ID}"
|
|
245
270
|
hook: require-review-subagent-evidence
|
|
246
271
|
enforcement: block
|
|
272
|
+
producers:
|
|
273
|
+
- kind: mcp
|
|
274
|
+
verb: mcp__agent-grounding__ledger_add
|
|
275
|
+
example: '{type:"fact", content:"review-subagent:\${TASK_ID} — <verdict + key findings + nits>", source:"Agent(general-purpose) review"}'
|
|
276
|
+
description: After running a review subagent against the staged diff, persist its verdict + load-bearing findings as a ledger entry tagged with the task UUID. The content should be self-contained enough to audit later without re-reading the chat.
|
|
247
277
|
|
|
248
278
|
- name: preflight-before-push
|
|
249
279
|
description: Block git push unless a fresh preflight ledger entry exists for the current branch. Catches the stale-checkout class of incident at the last reversible step.
|
|
@@ -256,6 +286,14 @@ policies:
|
|
|
256
286
|
within: 10m
|
|
257
287
|
hook: require-preflight-push-evidence
|
|
258
288
|
enforcement: block
|
|
289
|
+
producers:
|
|
290
|
+
- kind: bash
|
|
291
|
+
command: harness session-start preflight
|
|
292
|
+
description: Runs agent-preflight against the current cwd; on ready:true, records preflight:\${BRANCH} to the ledger. Standard producer.
|
|
293
|
+
- kind: mcp
|
|
294
|
+
verb: mcp__agent-grounding__ledger_add
|
|
295
|
+
example: '{type:"fact", content:"preflight:\${BRANCH} — <summary of what is on the branch + smoke results>", source:"manual"}'
|
|
296
|
+
description: Direct ledger write. The branch is the WIP review surface; the content should summarise what is staged + the smoke evidence so a reviewer can audit later without re-reading the chat.
|
|
259
297
|
|
|
260
298
|
# Full inherits the Solo/Team understanding-gate stack: the Stop hook
|
|
261
299
|
# persists each Understanding Report and the PreToolUse pre-tool-use
|
|
@@ -269,6 +307,19 @@ policy_packs:
|
|
|
269
307
|
description: Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.
|
|
270
308
|
config:
|
|
271
309
|
mode: grill_me
|
|
310
|
+
# Producers (agent-tasks/25bced52): rendered into the gate's deny
|
|
311
|
+
# envelope by the same engine as policy producers. Constraint at
|
|
312
|
+
# this layer: at-least-one \`ask\`. Post-v0.14.0 the gate signal
|
|
313
|
+
# is a filesystem marker and the mcp ledger_add path no longer
|
|
314
|
+
# satisfies the gate; the canonical unblock surface is the
|
|
315
|
+
# operator-approval prompt.
|
|
316
|
+
producers:
|
|
317
|
+
- kind: ask
|
|
318
|
+
command: harness approve understanding
|
|
319
|
+
description: "Bare command, no pipes or chaining. The hook recognises it via isEscapeCommand and emits permissionDecision:ask; the operator's go on that prompt IS the gate approval. Golden path."
|
|
320
|
+
- kind: bash
|
|
321
|
+
command: harness approve understanding
|
|
322
|
+
description: Same command from any un-hooked terminal (operator only, not reachable from inside the gated session). Writes the canonical marker at harness.generated/.approvals/\${SESSION_ID}.
|
|
272
323
|
`;
|
|
273
324
|
import { SOLO_TEMPLATE, TEAM_TEMPLATE } from "./profiles.js";
|
|
274
325
|
export function getTemplate(name) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/cli/init/templates.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqB/B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/cli/init/templates.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqB/B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4S5B,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI7D,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,aAAa,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,aAAa,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,aAAa,CAAC;QACvB,KAAK,SAAS;YACZ,OAAO,gBAAgB,CAAC;IAC5B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type LedgerEntry } from "../../policies/index.js";
|
|
2
|
+
import type { Manifest } from "../../schema/index.js";
|
|
3
|
+
import { type LoaderOptions } from "../loader.js";
|
|
4
|
+
export interface PackHookBranchProtectionOptions extends LoaderOptions {
|
|
5
|
+
/** Defaults to process.stdin. */
|
|
6
|
+
stdin?: NodeJS.ReadableStream;
|
|
7
|
+
/** Defaults to process.stdout. */
|
|
8
|
+
stdout?: NodeJS.WritableStream;
|
|
9
|
+
/** Defaults to process.stderr. */
|
|
10
|
+
stderr?: NodeJS.WritableStream;
|
|
11
|
+
/** Override "now" for deterministic freshness-window tests. */
|
|
12
|
+
now?: Date;
|
|
13
|
+
/** Override the cwd resolution (test injection). */
|
|
14
|
+
cwd?: string;
|
|
15
|
+
/** Per-call ledger timeout in ms. */
|
|
16
|
+
ledgerTimeoutMs?: number;
|
|
17
|
+
/** Inject a manifest (test). */
|
|
18
|
+
manifest?: Manifest;
|
|
19
|
+
/** Inject a fake ledger query (test). */
|
|
20
|
+
ledgerQuery?: (sessionId: string) => Promise<LedgerEntry[] | {
|
|
21
|
+
degraded: string;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export interface PackHookBranchProtectionResult {
|
|
25
|
+
exitCode: number;
|
|
26
|
+
blocked: boolean;
|
|
27
|
+
/** Diagnostic line emitted to stderr (always, even on allow). */
|
|
28
|
+
diagnostic: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function runPackHookBranchProtectionCli(opts?: PackHookBranchProtectionOptions): Promise<PackHookBranchProtectionResult>;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// `harness pack hook branch-protection` — PreToolUse blocker for the
|
|
2
|
+
// `branch-protection` policy pack.
|
|
3
|
+
//
|
|
4
|
+
// Receives Claude Code's PreToolUse event JSON on stdin and emits a
|
|
5
|
+
// `{ decision: "block" }` envelope when the agent is about to mutate
|
|
6
|
+
// source on a protected branch without a satisfying ledger tag.
|
|
7
|
+
//
|
|
8
|
+
// Two paths satisfy the gate:
|
|
9
|
+
//
|
|
10
|
+
// 1. **Producer path** — a `branch:non-protected` tag exists in the
|
|
11
|
+
// ledger from within the last 5 minutes (set by
|
|
12
|
+
// `harness session-start branch-check` when the session opened on
|
|
13
|
+
// a non-protected branch).
|
|
14
|
+
//
|
|
15
|
+
// 2. **Override path** — a `branch-protection-ack:` tag exists in the
|
|
16
|
+
// ledger (any age). The operator writes this from outside the
|
|
17
|
+
// gated shell via `mcp__agent-grounding__ledger_add` to bless a
|
|
18
|
+
// deliberate protected-branch edit (version bumps, CI workflow
|
|
19
|
+
// patches, hotfixes). The `:<reason>` suffix is free-form so the
|
|
20
|
+
// audit log can read WHY the override fired.
|
|
21
|
+
//
|
|
22
|
+
// Failure mode: any error in load / parse / ledger query resolves to
|
|
23
|
+
// BLOCK. This is the inverse of understanding-before-execution's
|
|
24
|
+
// fail-open contract: branch-protection's whole job is to prevent
|
|
25
|
+
// edit-on-master incidents, so a bug in the blocker that silently
|
|
26
|
+
// allowed Writes through would defeat the purpose. The block envelope
|
|
27
|
+
// always names a recovery path so the operator is never wedged.
|
|
28
|
+
import { queryLedgerByTag, } from "../../policies/index.js";
|
|
29
|
+
import { ACK_TAG_PREFIX, DEFAULT_PROTECTED_BRANCHES, NON_PROTECTED_TAG_PREFIX, PACK_NAME, PRODUCER_FRESHNESS_MS, resolveProtectedBranches, } from "../../policy-packs/builtin/branch-protection-runtime.js";
|
|
30
|
+
import { resolveGitContext } from "../../runtime/git-context.js";
|
|
31
|
+
import { POLICY_DECISION_TYPE } from "../../runtime/ledger-record.js";
|
|
32
|
+
import { loadManifest } from "../loader.js";
|
|
33
|
+
async function readStdin(stream) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
let data = "";
|
|
36
|
+
stream.setEncoding("utf8");
|
|
37
|
+
stream.on("data", (chunk) => {
|
|
38
|
+
data += chunk;
|
|
39
|
+
});
|
|
40
|
+
stream.on("end", () => resolve(data));
|
|
41
|
+
stream.on("error", (err) => reject(err));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function findGroundingMcp(manifest) {
|
|
45
|
+
return manifest.tools.mcp.find((m) => m.name === "grounding-mcp") ?? null;
|
|
46
|
+
}
|
|
47
|
+
function evaluateEntries(entries, now) {
|
|
48
|
+
const cutoff = now.getTime() - PRODUCER_FRESHNESS_MS;
|
|
49
|
+
let hasFreshProducer = false;
|
|
50
|
+
let hasAck = false;
|
|
51
|
+
let freshProducerContent = null;
|
|
52
|
+
let ackContent = null;
|
|
53
|
+
for (const e of entries) {
|
|
54
|
+
// Skip policy_decision audit rows: their serialized payload
|
|
55
|
+
// incidentally contains the tag they're about (e.g. a denied
|
|
56
|
+
// decision the engine recorded for THIS pack would carry the
|
|
57
|
+
// literal "branch:non-protected" or "branch-protection-ack" in
|
|
58
|
+
// its JSON, falsely satisfying the gate). Two-tier filter
|
|
59
|
+
// mirrors `src/policies/requires.ts:75-83`: by-type for current
|
|
60
|
+
// ledger rows, by-content-prefix as a backstop for legacy rows
|
|
61
|
+
// a pre-Phase-5-#4 ledger may still carry.
|
|
62
|
+
if (e.type === POLICY_DECISION_TYPE)
|
|
63
|
+
continue;
|
|
64
|
+
if (e.content.startsWith(`${POLICY_DECISION_TYPE}:`))
|
|
65
|
+
continue;
|
|
66
|
+
if (e.content.includes(ACK_TAG_PREFIX)) {
|
|
67
|
+
hasAck = true;
|
|
68
|
+
if (ackContent === null)
|
|
69
|
+
ackContent = e.content;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!e.content.includes(NON_PROTECTED_TAG_PREFIX))
|
|
73
|
+
continue;
|
|
74
|
+
const ts = e.createdAt instanceof Date ? e.createdAt : new Date(e.createdAt);
|
|
75
|
+
if (Number.isNaN(ts.getTime()))
|
|
76
|
+
continue;
|
|
77
|
+
if (ts.getTime() >= cutoff) {
|
|
78
|
+
hasFreshProducer = true;
|
|
79
|
+
if (freshProducerContent === null)
|
|
80
|
+
freshProducerContent = e.content;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
hasFreshProducer,
|
|
85
|
+
hasAck,
|
|
86
|
+
freshProducerContent,
|
|
87
|
+
ackContent,
|
|
88
|
+
totalEntries: entries.length,
|
|
89
|
+
degraded: null,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async function probeLedger(manifest, sessionId, opts) {
|
|
93
|
+
if (opts.ledgerQuery) {
|
|
94
|
+
const r = await opts.ledgerQuery(sessionId);
|
|
95
|
+
if ("degraded" in r) {
|
|
96
|
+
return {
|
|
97
|
+
hasFreshProducer: false,
|
|
98
|
+
hasAck: false,
|
|
99
|
+
freshProducerContent: null,
|
|
100
|
+
ackContent: null,
|
|
101
|
+
totalEntries: 0,
|
|
102
|
+
degraded: r.degraded,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return evaluateEntries(r, opts.now ?? new Date());
|
|
106
|
+
}
|
|
107
|
+
if (!manifest) {
|
|
108
|
+
return {
|
|
109
|
+
hasFreshProducer: false,
|
|
110
|
+
hasAck: false,
|
|
111
|
+
freshProducerContent: null,
|
|
112
|
+
ackContent: null,
|
|
113
|
+
totalEntries: 0,
|
|
114
|
+
degraded: "manifest unavailable",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const server = findGroundingMcp(manifest);
|
|
118
|
+
if (!server) {
|
|
119
|
+
return {
|
|
120
|
+
hasFreshProducer: false,
|
|
121
|
+
hasAck: false,
|
|
122
|
+
freshProducerContent: null,
|
|
123
|
+
ackContent: null,
|
|
124
|
+
totalEntries: 0,
|
|
125
|
+
degraded: "grounding-mcp not declared in manifest",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const command = Array.isArray(server.command)
|
|
129
|
+
? server.command
|
|
130
|
+
: server.command.trim().split(/\s+/);
|
|
131
|
+
const env = server.env ?? undefined;
|
|
132
|
+
const timeoutMs = opts.ledgerTimeoutMs ?? server.health?.timeout_ms ?? 5_000;
|
|
133
|
+
const result = await queryLedgerByTag({
|
|
134
|
+
mcpCommand: command,
|
|
135
|
+
...(env && { mcpEnv: env }),
|
|
136
|
+
sessionId,
|
|
137
|
+
timeoutMs,
|
|
138
|
+
});
|
|
139
|
+
if (result.kind === "degraded") {
|
|
140
|
+
return {
|
|
141
|
+
hasFreshProducer: false,
|
|
142
|
+
hasAck: false,
|
|
143
|
+
freshProducerContent: null,
|
|
144
|
+
ackContent: null,
|
|
145
|
+
totalEntries: 0,
|
|
146
|
+
degraded: result.reason,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return evaluateEntries(result.entries, opts.now ?? new Date());
|
|
150
|
+
}
|
|
151
|
+
function blockJson(toolName, branch, detail, protectedList) {
|
|
152
|
+
const minutes = Math.round(PRODUCER_FRESHNESS_MS / 60000);
|
|
153
|
+
const reasonText = `branch-protection: refusing ${toolName} on protected branch "${branch}". ` +
|
|
154
|
+
`${detail}\n` +
|
|
155
|
+
`To proceed, cut a feature branch and re-run the producer:\n` +
|
|
156
|
+
` git checkout -b <feature-slug>\n` +
|
|
157
|
+
` harness session-start branch-check\n` +
|
|
158
|
+
`Once the gate sees a fresh ${NON_PROTECTED_TAG_PREFIX} tag (within ${minutes}m), this tool call will succeed.\n` +
|
|
159
|
+
`\n` +
|
|
160
|
+
`Override (use sparingly): write \`${ACK_TAG_PREFIX}:<reason>\` to the ledger via mcp__agent-grounding__ledger_add. ` +
|
|
161
|
+
`The override survives the session and bypasses this gate.\n` +
|
|
162
|
+
`\n` +
|
|
163
|
+
`Protected branches: ${protectedList.join(", ")}.`;
|
|
164
|
+
return JSON.stringify({
|
|
165
|
+
decision: "block",
|
|
166
|
+
reason: reasonText,
|
|
167
|
+
hookSpecificOutput: {
|
|
168
|
+
hookEventName: "PreToolUse",
|
|
169
|
+
permissionDecision: "deny",
|
|
170
|
+
permissionDecisionReason: reasonText,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
export async function runPackHookBranchProtectionCli(opts = {}) {
|
|
175
|
+
const stdin = opts.stdin ?? process.stdin;
|
|
176
|
+
const stdout = opts.stdout ?? process.stdout;
|
|
177
|
+
const stderr = opts.stderr ?? process.stderr;
|
|
178
|
+
const note = (msg) => {
|
|
179
|
+
stderr.write(`harness pack hook branch-protection: ${msg}\n`);
|
|
180
|
+
};
|
|
181
|
+
// Defensive stdin parse. Empty / malformed input resolves to BLOCK
|
|
182
|
+
// (the inverse of understanding-before-execution's allow-on-malformed
|
|
183
|
+
// default): we'd rather block a Write we couldn't classify than let
|
|
184
|
+
// it through silently.
|
|
185
|
+
const raw = await readStdin(stdin);
|
|
186
|
+
let event = {};
|
|
187
|
+
try {
|
|
188
|
+
event = JSON.parse(raw.trim() || "{}");
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
/* event stays {} — handled by the sessionId check below */
|
|
192
|
+
}
|
|
193
|
+
const sessionId = (typeof event.session_id === "string" ? event.session_id : undefined) ??
|
|
194
|
+
process.env.CLAUDE_SESSION_ID ??
|
|
195
|
+
"";
|
|
196
|
+
const toolName = typeof event.tool_name === "string" ? event.tool_name : "(unknown)";
|
|
197
|
+
const cwd = typeof opts.cwd === "string" && opts.cwd.length > 0
|
|
198
|
+
? opts.cwd
|
|
199
|
+
: typeof event.cwd === "string" && event.cwd.length > 0
|
|
200
|
+
? event.cwd
|
|
201
|
+
: process.cwd();
|
|
202
|
+
// Load manifest to resolve the protected-branches list AND the
|
|
203
|
+
// grounding-mcp wiring. A manifest load failure forces BLOCK with a
|
|
204
|
+
// clear hint — we can't know if the gate should fire if we can't
|
|
205
|
+
// read its config.
|
|
206
|
+
let manifest = null;
|
|
207
|
+
if (opts.manifest) {
|
|
208
|
+
manifest = opts.manifest;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
try {
|
|
212
|
+
manifest = loadManifest(opts).manifest;
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
const reason = `manifest load failed (${err.message}); refusing on failsafe`;
|
|
216
|
+
const diagnostic = `BLOCK — ${reason}`;
|
|
217
|
+
note(diagnostic);
|
|
218
|
+
stdout.write(`${blockJson(toolName, "(unresolvable)", reason, DEFAULT_PROTECTED_BRANCHES)}\n`);
|
|
219
|
+
return { exitCode: 0, blocked: true, diagnostic };
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const pack = manifest.policy_packs.find((p) => p.name === PACK_NAME);
|
|
223
|
+
if (!pack) {
|
|
224
|
+
const diagnostic = `pack "${PACK_NAME}" not declared in manifest, allowing`;
|
|
225
|
+
note(diagnostic);
|
|
226
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
227
|
+
}
|
|
228
|
+
if (!pack.enabled) {
|
|
229
|
+
const diagnostic = `pack "${PACK_NAME}" is enabled:false, allowing`;
|
|
230
|
+
note(diagnostic);
|
|
231
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
232
|
+
}
|
|
233
|
+
const { branches: protectedList } = resolveProtectedBranches(pack);
|
|
234
|
+
const { branch } = resolveGitContext(cwd);
|
|
235
|
+
// Outside a git work tree (or detached HEAD) we can't tell what the
|
|
236
|
+
// edit would land on. We choose to allow here — the alternative is
|
|
237
|
+
// blocking every Write in non-git workspaces, which would be hostile
|
|
238
|
+
// to standalone-script workflows. A detached HEAD on an in-repo cwd
|
|
239
|
+
// also lands here; arguably should block, but git-detached-HEAD
|
|
240
|
+
// edits don't auto-push to a protected ref so the downstream
|
|
241
|
+
// `preflight-before-push` gate still catches the actual hazard.
|
|
242
|
+
if (branch === "") {
|
|
243
|
+
const diagnostic = `cwd is not on a named branch (detached HEAD or outside a git work tree); allowing`;
|
|
244
|
+
note(diagnostic);
|
|
245
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
246
|
+
}
|
|
247
|
+
if (!protectedList.includes(branch)) {
|
|
248
|
+
const diagnostic = `branch "${branch}" is not in the protected list (${protectedList.join(", ")}); allowing`;
|
|
249
|
+
note(diagnostic);
|
|
250
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
251
|
+
}
|
|
252
|
+
// On a protected branch: probe the ledger for either gate path.
|
|
253
|
+
if (sessionId === "") {
|
|
254
|
+
const reason = `no session_id resolvable from stdin or $CLAUDE_SESSION_ID; cannot consult ledger`;
|
|
255
|
+
const diagnostic = `BLOCK — ${reason}`;
|
|
256
|
+
note(diagnostic);
|
|
257
|
+
stdout.write(`${blockJson(toolName, branch, reason, protectedList)}\n`);
|
|
258
|
+
return { exitCode: 0, blocked: true, diagnostic };
|
|
259
|
+
}
|
|
260
|
+
const check = await probeLedger(manifest, sessionId, opts);
|
|
261
|
+
if (check.hasAck) {
|
|
262
|
+
const diagnostic = `ACK override active (${check.ackContent ?? ACK_TAG_PREFIX}); allowing`;
|
|
263
|
+
note(diagnostic);
|
|
264
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
265
|
+
}
|
|
266
|
+
if (check.hasFreshProducer) {
|
|
267
|
+
const diagnostic = `fresh producer tag (${check.freshProducerContent ?? NON_PROTECTED_TAG_PREFIX}); allowing`;
|
|
268
|
+
note(diagnostic);
|
|
269
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
270
|
+
}
|
|
271
|
+
const why = check.degraded !== null
|
|
272
|
+
? `ledger degraded (${check.degraded}); refusing on failsafe`
|
|
273
|
+
: `no fresh ${NON_PROTECTED_TAG_PREFIX} tag (${check.totalEntries} entries scanned) and no ${ACK_TAG_PREFIX} override`;
|
|
274
|
+
const diagnostic = `BLOCK — ${why}`;
|
|
275
|
+
note(diagnostic);
|
|
276
|
+
stdout.write(`${blockJson(toolName, branch, why, protectedList)}\n`);
|
|
277
|
+
return { exitCode: 0, blocked: true, diagnostic };
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=hook-branch-protection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-branch-protection.js","sourceRoot":"","sources":["../../../src/cli/pack/hook-branch-protection.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ import { queryLedgerByTag } from "../../policies/index.js";
|
|
|
23
23
|
import { checkApprovalMarker, checkPersistedReport, defaultReportsDir, matchLedgerEntries, } from "../../policy-packs/builtin/understanding-before-execution-runtime.js";
|
|
24
24
|
import { resolveGeneratedDir } from "../../runtime/pending-approval.js";
|
|
25
25
|
import { loadManifest } from "../loader.js";
|
|
26
|
+
import { renderReportSchemaHint } from "./understanding-report-schema-hint.js";
|
|
26
27
|
const PACK_NAME = "understanding-before-execution";
|
|
27
28
|
const EXIT_BLOCK = 2;
|
|
28
29
|
async function readStdin(stream) {
|
|
@@ -163,7 +164,8 @@ export async function runPackHookCodexPreToolUseCli(opts = {}) {
|
|
|
163
164
|
? `no approval marker for session ${sessionId}; ${report.detail}; ${ledger.detail}`
|
|
164
165
|
: `generatedDir not resolvable (test/injection path); ${report.detail}; ${ledger.detail}`;
|
|
165
166
|
const diagnostic = `harness pack hook codex: BLOCK: ${reason}. Tool: ${toolName}. ` +
|
|
166
|
-
"Run `harness approve understanding` once you have produced and confirmed an Understanding Report
|
|
167
|
+
"Run `harness approve understanding` once you have produced and confirmed an Understanding Report.\n" +
|
|
168
|
+
renderReportSchemaHint();
|
|
167
169
|
stderr.write(`${diagnostic}\n`);
|
|
168
170
|
return {
|
|
169
171
|
exitCode: EXIT_BLOCK,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-codex-pre-tool-use.js","sourceRoot":"","sources":["../../../src/cli/pack/hook-codex-pre-tool-use.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,4BAA4B;AAC5B,EAAE;AACF,+DAA+D;AAC/D,wEAAwE;AACxE,+DAA+D;AAC/D,0CAA0C;AAC1C,mEAAmE;AACnE,sCAAsC;AACtC,qEAAqE;AACrE,oEAAoE;AACpE,sEAAsE;AACtE,0DAA0D;AAC1D,EAAE;AACF,uEAAuE;AACvE,uEAAuE;AACvE,sEAAsE;AACtE,qEAAqE;AAErE,OAAO,EAAE,gBAAgB,EAAoB,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GAEnB,MAAM,sEAAsE,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAExE,OAAO,EAAE,YAAY,EAAsB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"hook-codex-pre-tool-use.js","sourceRoot":"","sources":["../../../src/cli/pack/hook-codex-pre-tool-use.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type LedgerEntry } from "../../policies/index.js";
|
|
2
2
|
import { type ApprovalCheckResult } from "../../policy-packs/builtin/understanding-before-execution-runtime.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type Manifest } from "../../schema/index.js";
|
|
4
4
|
import { type LoaderOptions } from "../loader.js";
|
|
5
5
|
export interface PackHookPreToolUseOptions extends LoaderOptions {
|
|
6
6
|
/** Pack name to evaluate. Defaults to understanding-before-execution. */
|