agentsclimarketplace

Harness init

Skill oeftimie/vv-claude-harness/skills/harness-init

Initialize a new project with the Long-Running Agent Harness (vv-harness plugin). Sets up feature tracking, git identity capture, context summary, build hooks, quality gate hooks, and an optional workflow size guideline. Use when starting a new multi-session project.From its SKILL.md

Install
npx -y skills add oeftimie/vv-claude-harness --skill harness-init

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 19 stars19 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

18.5 KB, as published. Nobody here has run it

Harness Initializer

Follow these steps in order. Do not skip steps. Ask the user when indicated.

Step 1: Gather Requirements

Ask the user (if not already provided):

  • What are you building? (brief description)
  • What's the tech stack? (language, framework, build tool)
  • Any existing code to preserve?

If the user provided this information in their initial message, proceed without asking.

Step 2: Capture Git Identity

git config user.name
git config user.email
ssh -T [email protected] 2>&1 || true
cat ~/.ssh/config 2>/dev/null | head -30

Record the active identity. Ask the user to confirm:

I detected:
- Git user: [name] <[email]>
- SSH identity: [key file or host alias]

Is this correct for this project? If you use multiple GitHub accounts, tell me which one this project belongs to.

Store the confirmed identity in .harness/harness.json.

Step 3: Create .harness/ Directory

Never hand-transcribe the framework-fixed files below into a project -- run ${CLAUDE_PLUGIN_ROOT}/scripts/stamp.sh, which emits every one of them deterministically from an answers file. Adapted from Setlist's two-phase bootstrap doctrine (Alex Ciortan, CC BY 4.0): "Never hand-write what a stamp can emit; never stamp what a decision shapes."

First, confirm the build hook. If the detected stack is one of typescript, swift, python, go, or rust, show the user the exact PostToolUse hook the stamp is about to wire in (the content of skills/harness-init/templates/posttooluse-<stack>.json -- it catches type/build errors after edits without blocking the agent, since hooks run async) and wait for confirmation before continuing. Any other stack: say plainly that no PostToolUse hook is available for it, and proceed.

Write the answers file:

mkdir -p /tmp/vv-harness-stamp
cat > /tmp/vv-harness-stamp/answers.txt <<EOF
project_name=PROJECT_NAME
stack=DETECTED_OR_SPECIFIED_STACK
mode=new
EOF

mode=new is correct here; mode=upgrade exists in stamp.sh for re-stamping an existing project and is not used by this skill.

Run the stamp from the project root:

"${CLAUDE_PLUGIN_ROOT}/scripts/stamp.sh" /tmp/vv-harness-stamp/answers.txt .

If it aborts (mode=new found an existing file), stop and show the user exactly what it reported; do not work around the abort by deleting their files.

On success this writes, byte-verbatim or rendered from a template in skills/harness-init/templates/ -- never hand-transcribed:

  • .claude/settings.json: statusLine, permissions, and the full hook wiring (PreToolUse scope/git-identity/commit-gate, TaskCompleted), plus the stack-appropriate PostToolUse build-check block selected from templates/posttooluse-<stack>.json when stack is typescript, swift, python, go, or rust; any other stack gets no PostToolUse hook.
  • .claude/hooks/{verify-task-quality.sh, enforce-scope.sh, verify-git-identity.sh, commit-gate.sh, harness_state.py, statusline.sh}, all executable. harness_state.py is the shared, stdlib-only features.json read/write module that verify-task-quality.sh consumes (schema in ${CLAUDE_PLUGIN_ROOT}/schemas/feature.schema.json). commit-gate.sh is a PreToolUse Bash hook that fires only on git commit, denying compound stage-and-commit forms and staged secret-shaped content (see the template's own header for the full check list).
  • .harness/harness.json and .harness/features.json skeletons with project/stack/ created filled in, plus plugin_version (F068) when ${CLAUDE_PLUGIN_ROOT}/ .claude-plugin/plugin.json is readable -- purely mechanical, unlike the two fields below, so the stamp writes it directly rather than deferring it to a follow-up step; git_identity is left null here (this step is the decision that fills it), and workflow.size_guideline is absent until Step 6 decides whether to write it.
  • .gitignore gains .harness/SESSION_INCOMPLETE, .harness/features.json.lock, and .harness/last_gate.json (OVI-107), all three appended idempotently.

.harness/features.json's feature schema. Each feature's shape (the 16 fields, which are required vs. optional, the status enum) is defined once in ${CLAUDE_PLUGIN_ROOT}/schemas/feature.schema.json and illustrated with the one worked example in the Feature Schema section of ${CLAUDE_PLUGIN_ROOT}/rules/parallel-work.md. scripts/validate-features.py enforces it in the test suite.

The done-definition (passing / done / shipped) and the optional claim-matched-proof fields (qa_binding, proof, coverage_target, delivered, design_contract) are defined once, in the Feature Schema section of ${CLAUDE_PLUGIN_ROOT}/rules/parallel-work.md — see that section rather than this one for the current definition.

A feature may also carry a spec verification object; see the Feature Schema section of ${CLAUDE_PLUGIN_ROOT}/rules/parallel-work.md.

Then finish the pieces the stamp deliberately leaves to a decision:

1. Fill in git_identity with the identity confirmed in Step 2:

python3 - <<'PYEOF'
import json

with open(".harness/harness.json") as f:
    data = json.load(f)
data["git_identity"] = {
    "user_name": "DETECTED_NAME",
    "user_email": "DETECTED_EMAIL",
    "ssh_key": "<key file or host alias>",
    "ssh_host": "github.com OR ALIAS",
}
with open(".harness/harness.json", "w") as f:
    json.dump(data, f, indent=2)
PYEOF

2. Record the initial worker block (F016/OVI-57): probe claude --version the same defensive way harness-continue's Step 2.6 does -- unavailable or unparseable output -> skip silently, no worker key written, and epoch tracking simply starts the first time a later session records it:

python3 - <<'PYEOF'
import json
import re
import subprocess

try:
    out = subprocess.check_output(["claude", "--version"], stderr=subprocess.DEVNULL, text=True)
except (FileNotFoundError, subprocess.CalledProcessError):
    raise SystemExit(0)

match = re.search(r"(\d+\.\d+\.\d+)", out)
if not match:
    raise SystemExit(0)

with open(".harness/harness.json") as f:
    data = json.load(f)
data["worker"] = {
    "cli_version": match.group(1),
    "models": {"lead": "opus", "implementer": "sonnet", "reviewer": "opus"},
    "recorded_at": "<ISO8601 UTC>",
}
with open(".harness/harness.json", "w") as f:
    json.dump(data, f, indent=2)
PYEOF

The models values are the CURRENT row values from rules/parallel-work.md's Model Selection table (the single bindings table) at the time you run this -- if that table has since been requalified to different bindings, use those instead of the opus/sonnet/opus shown here. Schema: schemas/feature.schema.json's $defs/harness_worker_block.

plugin_version (F068) is NOT a follow-up step here, unlike git_identity and worker above -- unlike those two, it needs no user decision and no live subprocess probe, only a file already sitting next to scripts/stamp.sh on disk, so the stamp itself writes it directly (see scripts/stamp.sh's own comments). harness-doctor (F068) compares it against the currently installed plugin on later runs and offers to bootstrap or refresh it via --fix if it's ever missing or stale.

3. Write .harness/context_summary.md -- this carries real project judgment (domain, constraints, architecture), never zero-decision content, so it stays hand-authored:

# Context Summary

Persistent record of architectural decisions, discovered patterns, gotchas, and active context.
This file is referenced in CLAUDE.md and loaded every session.

## Active Context
- Currently working on: project initialization
- Next up: first feature implementation

## Cross-Cutting Concerns
- Stack: [stack]
- Architecture: [brief description]
- Key constraints: [any constraints mentioned by user]

## Domain: [Primary Domain]

### Decisions
- [Stack] chosen: [rationale] (ISO_DATE)

### Patterns
- (none yet)

### Gotchas
- (none yet)

## Meta-Patterns
<!-- Coordination insights that apply across features — NOT domain-specific.
     Populated by the retrospective step at session end.
     These transfer to new projects: harness-init can import them as starting context. -->
- (none yet — first retrospective will populate this)

4. Write .harness/claude-progress.txt:

# Claude Progress Log
# Project: PROJECT_NAME
# Created: ISO_DATE

## Session 1 - Initialization
- Created harness scaffolding
- Detected stack: [stack]
- Git identity: [user] <[email]>
- [List what you set up]

5. Configure .harness/init.sh for the detected stack -- the one genuinely decision-shaped file in this set, so the stamp does not touch it. Read the init.sh.template file in this skill's directory, copy it to .harness/init.sh, configure for the detected stack, and make it executable with chmod +x.

The script accepts an optional target argument: smoke_test, focused_test <test_file>, or full_test (default: full_test).

  • smoke_test — compile/syntax check only, completes in <15s. Used by the TaskCompleted hook as a fast first-pass gate.
  • focused_test <test_file> — run exactly one test file. The TaskCompleted hook passes the targeted feature's recorded test_file as the second stage of its gate; the hook detects support by grepping init.sh's non-comment lines for focused_test and stays smoke-only when absent, so older projects keep working unchanged. Exit-code contract: 0 strictly means the test executed and passed; 3 means the script skipped the stage ("skipped, no runner": no per-file runner for the stack, or the recorded test file does not exist), which the hook treats as not-run — accepted on smoke alone, no baseline recorded — never as a pass; any other exit is a real failure that rejects the completion. 3 is reserved for the script's own skip sites: a runner's own exit 3 must be remapped to a failure (the template's run_focused helper does this), since real runners use 3 for genuine failures (pytest INTERNALERROR, mocha's failing-test count).
  • full_test — complete test suite with coverage. Enforced when a feature's status flips to passing (the commit gate runs it whenever a staged features.json contains such a flip) and used by the lead at session end and synthesis phase. It does NOT run on every task completion.

When configuring for the project's stack, ensure all three targets work correctly.

Authoring rule — full_test must be satisfiable mid-project. full_test gates every passing-flip commit, so a check that cannot go green until the whole project is done jams every feature before it. It must also finish comfortably inside Claude Code's PreToolUse command-hook timeout (600s default): the commit gate runs it synchronously on a passing-flip commit, and a hook killed by the timeout allows the command — a too-slow suite silently converts the gate to fail-open. The concrete trap is workspace-aggregate metrics: a hardcoded "aggregate coverage >= 99%" makes feature A's completion depend on feature B's unwritten tests, and an unreachable gate teaches agents to route around gates. Put aggregate metrics in as ratchets — compare against a stored baseline (e.g. .harness/coverage-baseline.json) and fail only on regression, updating the baseline as it improves. Reserve fixed high thresholds (95%, 99%) for per-feature scope (the coverage_target gate already enforces that) or an explicit release feature's acceptance criteria.

Step 3.6: Quality Gate Hooks (via the Stamp)

The stamp run in Step 3 already wrote and chmod +x'd every quality gate hook (verify-task-quality.sh, enforce-scope.sh, verify-git-identity.sh, commit-gate.sh, harness_state.py, statusline.sh) and wired the full .claude/settings.json block (statusLine, permissions, and the PreToolUse/TaskCompleted hooks) -- there is nothing left to do here beyond the verification in Step 3.7.

Do NOT wire a per-project PostCompact hook. The plugin's SessionStart hook (which fires with a compact source after compaction) already injects post-compaction recovery directly into the model's context, so a separate PostCompact hook would be redundant.

Step 3.7: Verify Hooks

After installing hooks, verify they execute correctly:

echo '{}' | "$CLAUDE_PROJECT_DIR"/.claude/hooks/verify-task-quality.sh
echo "Exit code: $?"

Expected results:

  • verify-task-quality.sh: exit 0 if tests pass, exit 2 if tests fail

If the script fails to execute (permission denied, syntax error, missing dependency), fix the issue before proceeding. Silent hook failures mean quality gates don't enforce anything.

Tell the user:

I've set up four hooks plus a status line:
- PreToolUse (scope): blocks writes to lead-owned state files (features.json, context_summary.md). Armed automatically inside workflow-agent worktrees; unrestricted in the main checkout.
- PreToolUse (git identity): blocks git push/pull/clone if identity doesn't match .harness/harness.json.
- PreToolUse (commit gate): blocks git commit if it stages-and-commits in one step, or if staged content looks like a secret.
- TaskCompleted: runs tests when an agent marks work done. Rejects if tests fail.
- Status line: live feature progress (N/M passing, in-progress IDs, incomplete-session flag).

Session orientation and post-compaction recovery are injected by the vv-harness
plugin's SessionStart hook; no per-project PostCompact hook is needed.

Quality gate hooks verified: [pass/fail status for each].

These enforce TDD and context recovery mechanically instead of relying on instructions alone.

Step 4: Update Project CLAUDE.md

If the project already has a CLAUDE.md, append the harness reference. If not, create one:

# [PROJECT_NAME]

[Brief description from user]

## Tech Stack

[Stack details]

## Harness

This project uses the Long-Running Agent Harness (vv-harness plugin).

- Feature tracking: `.harness/features.json`
- Context and decisions: `.harness/context_summary.md` (READ THIS at session start)
- Progress handoff: `.harness/claude-progress.txt`
- Build/test: `.harness/init.sh`
- Quality gates: `.claude/hooks/` (TaskCompleted, scope, git identity, commit gate)

## Git Identity

This project uses: [user_name] <[user_email]> with SSH key [ssh_key].
Always verify identity before push/pull/clone operations.

Step 5: Propose Initial Features

Based on the project description, propose 3-5 initial features. Include scope for each:

Based on your description, here are the initial features I suggest:

F001: [Core feature 1] - Priority 1
  Scope: [directories]
  Depends on: (none)

F002: [Core feature 2] - Priority 2
  Scope: [directories]
  Depends on: (none)

F003: [Supporting feature] - Priority 3
  Scope: [directories]
  Depends on: F001

Should I add these to features.json?

Wait for confirmation of the feature list. Then, BEFORE writing anything to .harness/features.json, run the spec gate (Step 5.1).

Step 5.1: Verify the proposal (spec gate)

Spawn the spec-verification agent as a read-only subagent over the ENTIRE confirmed proposal in one call:

Agent({
  description: "Spec-verify proposed features",
  subagent_type: "vv-harness:spec-verification",
  model: "opus",
  prompt: "[the full proposal: every feature's id, description, scope, depends_on,
            plus the user's project description. Ask for a per-feature verdict line
            in the report.]"
})

Route on the report's VERDICT:

  • PASS: write features.json. For each feature, populate spec with {"hash": sha256(description), "verdict": "PASS", "sv_version": "1.0", "verified_at": ISO8601-UTC, "source": "conversation"} (canonical hash recipe: ${CLAUDE_PLUGIN_ROOT}/schemas/readiness-stamp.md).
  • ASK: relay the numbered OPEN QUESTIONS to the user verbatim; iterate the feature descriptions with their answers; re-run the gate on the amended proposal. Do not write features.json until the gate passes.
  • BLOCK: present the grounds; the user amends or drops the contradicted features; re-run.

If the user explicitly waives the gate ("skip verification"), write the features with "spec": null and note the waiver in claude-progress.txt. Never fill spec for a feature the gate did not pass.

Step 6: Assess Workflow Sizing

Parallel work runs as worktree-isolated agents dispatched by a workflow, sized per run rather than per project. Ask once, about expected parallelism, so later sessions have a stated ceiling to size against:

Parallel work here runs as worktree-isolated agents inside a workflow, sized per run.
What's the expected parallelism for this project?

- small: a handful of independent features at a time
- medium: a moderate parallel front
- large: no ceiling worth stating -- size each run on its own

Or skip this, and I'll size each run on its own with no standing advice.

Map the answer to workflow.size_guideline in .harness/harness.json:

Answerworkflow.size_guidelineWhat it advises
small"small"at most 5 agents per workflow
medium"medium"at most 15 agents per workflow
large"large"no cap
skippedkey not writtenno sizing advice

The key is optional: an absent key means no advice, which is exactly what a project that skipped this question wants. Write it only for an answer the user actually gave:

python3 - <<'PYEOF'
import json

with open(".harness/harness.json") as f:
    data = json.load(f)
data.setdefault("workflow", {})["size_guideline"] = "SMALL_MEDIUM_OR_LARGE"
with open(".harness/harness.json", "w") as f:
    json.dump(data, f, indent=2)
PYEOF

This is a guideline, not a gate. The lead sizes each workflow run on the work actually in front of it during /harness-continue.

Step 7: Commit and Report

git add .harness/ .claude/ CLAUDE.md .gitignore
git commit -m "chore: initialize vv-harness scaffolding"

Report:

Harness (vv-harness plugin) initialized:
- .harness/ created with [N] features (scope, dependencies, spec gate: [passed | waived])
- Git identity captured: [user] <[email]>
- Build hook: [installed | skipped] for [STACK]
- Quality gates: TaskCompleted + PreToolUse hooks installed and verified
- CLAUDE.md updated
- Workflow sizing: [small | medium | large | not set]

Next: run /harness-continue to start working.

Keep looking

Skills are one crate of 628,853. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.