Spinning the agent harness out of henrik-me/guesswhatisnext into its own repo, with a second consumer (henrik-me/sub-invaders) battle-testing it before guesswhatisnext migrates onto it.
Distribution model: start private, switch to public after we've self-hosted (CS11) and used it on the harness repo for several dev CSs (CS12–CS14). Stay on npx -y github:henrik-me/agent-harness#vX.Y.Z (Option B) indefinitely; npm publication is an optional, deferred decision in the final CS.
Self-leverage: the harness repo follows its own process from CS01 (hand-authored proto docs, manual discipline) and is fully self-hosted from CS11 onward (CI gate prevents drift between template/managed/ and root files).
Sub-agent parallelism: every CS lists internally-parallelisable sub-tasks; the orchestrator fans those out to sub-agents.
This revision incorporates GPT-5.5 rubber-duck findings: composed file class for "managed core + local extension" docs, README ownership split, machine-readable PILOT parity manifest, full-history secret scan + license/IP review before public flip, CS17 split into Sub Invaders battle-test + shadow-migration, CS18 split into design-prep + freshness-bound execution, hot-fix stability counter, SemVer-on-process-docs concretised, reusable-workflow version-pinning linter, lock-file schema in CS02, permissions prerequisites, full PR-policy hardening before public flip.
| # | Decision | Choice |
|---|---|---|
| 1 | Repo license | MIT |
| 2 | Distribution while private | npx -y github:henrik-me/agent-harness#vX.Y.Z (works on private repos via PAT/GitHub App token in consumer CI) |
| 3 | Repo visibility | Private at CS01, hardened at CS15a, flip to public at CS15b after self-hosting is proven through CS11–CS14 dev cycles AND full-history secret scan AND PR policy hardening complete |
| 4 | npm publication | Deferred; revisited as a decision in CS20. Stay on git-ref unless a concrete reason emerges. |
| 5 | First non-guesswhatisnext consumer | Sub Invaders (sea-themed Space Invaders) |
| 6 | Sub Invaders persistence v1 | Azure Storage Tables (followed by re-eval CS for Upstash Redis / Cloudflare KV) |
| 7 | Sub Invaders deployment v1 | Azure Static Web Apps (followed by re-eval CS for Cloudflare Pages + Workers full stack) |
| 8 | Sub Invaders frontend | Pure TypeScript via tsc only, HTML5 Canvas, ES modules, zero runtime deps, PWA service worker for offline |
| 9 | Sub Invaders backend | Single Azure Function (Node 20) inside the SWA project: POST /score, GET /leaderboard?period=daily|all, with rate-limit + replay protection (no sign-in v1) |
| 10 | Harvest cadence | Weekly orchestrator-triggered + bounded before-claim user prompt (only stale process/architectural learnings or claim_area-relevant learnings; supports deferred_until; auto-escalates repeatedly-deferred items to weekly only) |
| 11 | Migration safety net | PILOT-A baseline (CS18b) executed under existing in-repo harness; PILOT-B parity (CS19/PR-2) executed under migrated harness; gates compared via machine-readable parity manifest |
| 12 | PILOT-A candidate | Picked during CS18a |
| 13 | File classes | Three classes: managed (overwrite on sync), composed (managed core + marker-preserved local blocks), seeded (create-if-missing, never overwrite) |
| 14 | Implementation model | Claude Opus 4.7 1M (orchestrator), Haiku for parallelisable mechanical sub-tasks, Sonnet for non-trivial sub-tasks |
| 15 | Local review model | GPT-5.5 rubber-duck on every CS implementation before opening PR; on every plan/template revision before commit |
| 16 | PR review (private phase, CS01–CS14) | GPT-5.5 rubber-duck + user review; Copilot review optional |
| 17 | PR review (public phase, CS15b+) | GPT-5.5 rubber-duck + Copilot review + user review on CODEOWNERS-protected paths |
| 18 | Signed commits on main |
Off until CS15b; on from CS15b |
| 19 | Branch naming | cs<NN>/<slug> mirroring guesswhatisnext |
| 20 | Agent ID schema (per guesswhatisnext TRACKING.md § Agent Identification, generalised) | Format: <machine-short>-<repo-short>[-c<N>]. machine-short: lowercase first meaningful hostname segment (HENRIKM-YOGA → yoga). repo-short: project-defined in harness.config.json → project.agent_suffix. -c<N>: derived from clone folder: <repo>_copilot<N> → -c<N>; <repo><N> (bare numeric distinguisher) → -c<N>; otherwise omitted. Override env var name: see Decision #20c. |
| 20a | Harness repo agent_suffix |
ah (so my session becomes yoga-ah) |
| 20b | Sub Invaders agent_suffix |
si |
| 20c | Override env var pattern (revised per GPT-5.5 #6) | HARNESS_AGENT_<SUFFIX_UPPER>_MACHINE (e.g. HARNESS_AGENT_AH_MACHINE, HARNESS_AGENT_SI_MACHINE). Harness-namespaced to avoid collisions; project.agent_env_var overrides default. harness whoami --explain prints derivation chain. |
| 22 | GPT-5.5 outage fallback (per GPT-5.5 #7, revised per re-review #5 + 4th-pass #6) | Primary: GPT-5.5 rubber-duck. If unavailable >30min or 2 failed attempts: fallback to Claude Sonnet 4.6 rubber-duck (different model family/configuration than Opus 4.7 implementer) OR explicit user waiver. Independence invariant: fallback reviewer must be a model/configuration not used to materially implement the reviewed CS. If Sonnet 4.6 performed non-trivial implementation sub-tasks within the CS being reviewed, fallback to Sonnet for that CS is forbidden — escalate to GPT-5.5 or user waiver. High-risk CSs (CS03, CS11, CS15a/b, CS18b, CS19) require GPT-5.5 OR explicit user waiver — no Sonnet fallback regardless. PR body records: model, timestamp, fallback reason, implementer-model-list-for-CS. |
| 23 | WORKBOARD claim mechanism (per GPT-5.5 #9, revised per re-review #2) | Tiny PRs auto-merged via dedicated GitHub Action for claim/closeout WORKBOARD updates. No direct-push-to-main exception. Mechanism: PR is labeled workboard-only; a dedicated workflow (workboard-auto-approve.yml) verifies (a) only WORKBOARD.md and clickstop rename paths changed, (b) label present, (c) author is in approved-actors list, then a GitHub App / bot submits the approval and triggers auto-merge. Global "Require ≥1 approving review" stays in place; the bot's review satisfies it. CI must still pass. No Ruleset label-bypass assumed — all gating is via the workflow + bot approval mechanism, which is mechanically valid on GitHub today. CS15a dry-run validates this end-to-end before becoming required. |
| 24 | Public-artifact redaction (per GPT-5.5 #5, revised per re-review #10) | All post-CS15b archived artifacts (shadow reports, pilot JSONs, manifests) sanitized before commit. Raw artifacts stay in source-repo private CI; only normalized gate results commit publicly. check-public-artifact.mjs linter (CS06) enforces. public_artifact_redaction config (CS02) declares per-artifact-type: (a) allowed_placeholders — explicit safe values (https://example.com, 00000000-0000-0000-0000-000000000000, ghp_FAKE_*); (b) forbidden_field_patterns — regex denylist (tokens, tenant IDs, internal URL patterns); (c) max_log_bytes_per_artifact — bounded inclusion of log content (default 8 KB) instead of vague "no logs"; (d) required_normalized_fields — must be present in pilot/shadow JSON; (e) raw_artifact_paths_forbidden — regex denylist for artifact paths that must never commit publicly. Reduces false-positive rate; gives a concrete contract. |
| 21 | Hot-fix policy during battle-test | Hot-fixes allowed; reset stability counter and require ≥1 clean Sub Invaders CS post-fix before tagging next harness version |
- GitHub permission to create private repos under
henrik-me - GitHub permission to flip repo visibility to public (verified before CS15, but confirm now)
- GitHub permission to configure branch protection rules and required status checks
- GitHub Actions enabled at the org level for
henrik-me - Ability to create GitHub Releases and tags
- Ability to manage repo secrets and Dependabot
- Azure subscription accessible for Sub Invaders (CS16) — confirm before CS16 not CS01
- (Optional, CS20)
@henrik-menpm scope availability and publish rights
Goal: Stand up the repo with the directory layout from our design and hand-authored proto versions of the process docs so the repo follows its own process from commit 1. Deliverables:
henrik-me/agent-harnessprivate repo on GitHub- Layout:
bin/,lib/,template/{managed,seeded}/,scripts/,scaffolds/,schemas/,.github/workflows/ package.json(private:true initially), MITLICENSE,.gitignore,.editorconfig- Hand-authored
INSTRUCTIONS.md,CONVENTIONS.md,OPERATIONS.md,REVIEWS.md,TRACKING.md,RETROSPECTIVES.md,CONTEXT.md,WORKBOARD.md,LEARNINGS.md,ARCHITECTURE.md,README.md(project-owned, never synced),.github/copilot-instructions.md,.github/pull_request_template.md,.github/CODEOWNERS project/clickstops/{planned,active,done}/.gitkeep- The two pre-CS01 planning artifacts (
harness-extraction-plan.md,harness-cs-plan.md) moved intoproject/clickstops/done/done_cs01_bootstrap-repo/(or referenced from it) - Branch protection on
main: deferred to CS15b per LRN-001. Requires GitHub Pro on private repos; user chose discipline-only enforcement for CS01–CS14. Exit: EmptyWORKBOARD.mdinitialised with orchestrator table; CS01 itself filed underproject/clickstops/done/to demonstrate the lifecycle. Parallelisable: No (foundational; discipline-only enforcement applies from commit 2 per LRN-001). Depends on: prerequisites checklist
Goal: Pin down all contracts before any code. Deliverables:
schemas/harness.config.schema.json(Draft-2020-12). Keys:version(pinned harness ref),project(name,cs_prefix,repo,agent_suffix— used in agent-ID derivation per Decision #20,agent_env_var— defaults toHARNESS_AGENT_<SUFFIX_UPPER>_MACHINEper Decision #20c),managed,composed,seeded(file-class allowlists with per-file overrides),scaffolds(opt-in list),linters(enable/disable + per-linter config),templating(substitution variables),local_blocks(per-file allowed block IDs),composed_block_migrations(per GPT-5.5 #12 — schema-only in v0.1.0; sync fails with clear "block ID renamed/split needs migration spec" message),public_artifact_redaction(per Decision #24 — per-artifact-type field allowlists/blocklists)schemas/harness-lock.schema.jsonfor.harness-lock.json. Required fields:harness_ref,resolved_sha,config_schema_version,synced_at(informational only — not used in drift comparisons),files[](each:target,source_template,class,rendered_hash,action, for composed filesblocks[]per GPT-5.5 #13:id,source_line_range,body_hash,template_marker_hash,provenance(user-authored/seeded-empty/migrated-from-legacy)),scaffolds[](with versions),excluded[](project-owned files explicitly skipped)schemas/learning.schema.jsonfor per-entry frontmatter- ADR documenting the three file classes:
managed(overwrite),composed(managed core + marker-preserved local blocks by ID, e.g.<!-- harness:local-start id=conventions.project -->...<!-- harness:local-end id=conventions.project -->),seeded(create-if-missing) - ADR documenting README ownership split: harness repo's root
README.mdis project-owned and excluded from sync;template/seeded/README.mdis the consumer skeleton - Worked examples:
harness.config.jsonfor guesswhatisnext + sub-invaders + the harness repo itself - CI wiring: install
ajv(or equivalent) in CI; add avalidate-schemasworkflow job that runs all three schemas against all three worked examples on every PR. (First CI workflow in the repo; status check name =validate-schemas. CS06 expands the CI surface.) Exit: All three schemas validate the three example configs; both ADRs merged; CI green; CS01 LEARNINGS LRN-001..005 validate againstlearning.schema.json. Parallelisable: 3 schemas + 2 ADRs + 3 examples + 1 CI wiring → 9 sub-tasks. Depends on: CS01
Goal: Pure-Node copy-with-templating engine that respects all three file classes and writes a .harness-lock.json.
Deliverables:
lib/sync.mjs— orchestrates classeslib/templating.mjs—{{project_name}}-style substitutionlib/lock.mjs— read/write.harness-lock.jsonper schemalib/composed.mjs— composed-class merge with hardened parser (per GPT-5.5 #1):- Markers recognized only when: occupy whole line except whitespace; outside fenced code blocks (
```and~~~); outside indented code blocks (4+ spaces);idmatches strict regex[a-z][a-z0-9.-]*; start/end IDs match exactly - Fails on: dropped/duplicated/unclosed blocks; nested local blocks; marker-looking text inside code fences (rejected unless escaped)
- Records each block's body hash + template-marker hash in lock file per GPT-5.5 #13
- Markers recognized only when: occupy whole line except whitespace; outside fenced code blocks (
- Modes:
apply(write files),check(exit non-zero on drift; ignoressynced_at),dry-run(print diff with classification per file) - Sync invariant (per GPT-5.5 re-review #8): for any composed target,
harness syncrefuses to overwrite if the target contains non-template, non-block content unlesslegacy_composed_mapping.jsonexplicitly maps each unmarked region to a block ID OR explicitly discards it. This is a sync-engine guarantee, not just a separate audit — exit non-zero, no partial write. Fixtures: composed target with legacy unmarked content + no mapping → exit non-zero; mapping to block → content preserved with provenancemigrated-from-legacy; explicit discard → omitted, recorded in lock; unmapped content → impossible to apply. - Unit tests via
node --test. Zero runtime deps. - Fixtures covering each class + each parser edge case: marker-inside-fenced-code, marker-inside-indented-code, marker-in-prose-comment, duplicate-marker-in-example, nested local blocks, block-dropped, block-ID-renamed, template-reordered-around-blocks
Exit: Tests pass;
sync --checkagainst fixtures behaves correctly. Parallelisable: sync.mjs / templating.mjs / lock.mjs / composed.mjs / fixtures → 5 sub-tasks. Depends on: CS02
Goal: Single entry point with subcommands.
Deliverables: harness <init|sync|check|lint|harvest|check-migration|composed-audit|pack|version|whoami> with --cwd, --config, --dry-run, --report, --ref, --accept-major, --explain flags.
whoami [--explain]derives the agent ID per Decision #20: reads hostname → machine-short, reads cwd folder → applies_copilot<N>/ bare-numeric-distinguisher rules → repo-short fromproject.agent_suffixin config → appliesHARNESS_AGENT_<SUFFIX_UPPER>_MACHINEoverride (orproject.agent_env_varif customised).--explainprints each derivation source: hostname, cwd, env-var-name, env-var-value-if-set, config-suffix, final-ID. Used byharness syncandharness harvestto identify the calling agent in WORKBOARD updates and learnings frontmatter.composed-audit --from-existing-harness(per GPT-5.5 #2): for each composed target in the consumer repo, detects legacy unmarked sections, proposes block-ID mapping, lists unmapped content, emitscomposed-migration-manifest.json+ before/after diff. Exits non-zero if unmapped content would be lost. Required CS19/PR-1 attachment.initscaffoldsharness.config.json+ seeded files into a targetsync --dry-run --reportemits a structured migration report classifying every file (overwrite / preserve / skip / conflict / project-owned)check-migration --from-existing-harnessaudits an existing repo against the harness templates and emits a duplicate-script + workflow-ref + config-override report (used in CS19 PR-1)harvestruns the full harvest procedure AND a bounded before-claim check: only staleopenlearnings taggedprocess/architecturalor tagged with theclaim_areametadata trigger a prompt;--snooze=<reason>:<deferred_until>accepted; repeated defers auto-escalate the learning to weekly-harvest-only--accept-majorrequired to sync across a major version bump; CLI warns if syncing while a CS isactivein WORKBOARDpackrunsnpm pack --dry-runand verifies the file whitelist- Helpful
--helpper subcommand. Exit codes documented in OPERATIONS.md. Exit:npx . initworks against an empty dir;npx . sync --checkworks in this repo (will fail until CS11);--accept-majorand dry-run-report verified end-to-end. Parallelisable: One sub-task per subcommand → 8 sub-tasks. Depends on: CS03
Goal: Establish the linter pattern with one fully-implemented example.
Deliverables: lib/doc-schema.mjs (frontmatter parser, heading-tree assertion, table-shape assertion, link resolver). scripts/check-learnings.mjs validating: required headings, per-entry frontmatter (id: LRN-NNN, category, status, source_cs, date, tags[], claim_area?, deferred_until?), allowed status values (open/applied/obsolete/deferred), disposition required for applied/obsolete, age-out warning for stale open entries, escalation flag for repeatedly-deferred entries.
Exit: Linter passes against the bootstrap LEARNINGS.md (which will be authored to satisfy it).
Parallelisable: doc-schema.mjs / check-learnings.mjs / fixtures → 3 sub-tasks.
Depends on: CS04
Goal: One linter per structured doc, all built on doc-schema.mjs.
Deliverables:
check-context.mjs,check-workboard.mjs,check-architecture.mjs,check-clickstop.mjs,check-instructions.mjs(cross-link integrity + dead-section detection),check-readme.mjs(enforces READMEGUIDE from CS08),check-composed-blocks.mjs(audits composed-class files for required block IDs present, no duplicates, no orphan IDs, no markers inside code fences per GPT-5.5 #1)check-workflow-pins.mjs(per GPT-5.5 #10): scans.github/workflows/*.ymlforhenrik-me/agent-harness/...@refreferences and asserts every ref matchesharness.config.jsonversion. Prevents local/CI rule drift.check-public-artifact.mjs(per GPT-5.5 #5): scans archived shadow/pilot/migration artifacts for forbidden fields (tokens, tenant/subscription IDs, internal URLs, full logs, unredacted telemetry identifiers). Driven bypublic_artifact_redactionconfig. Mandatory check from CS15a onward.- Each linter ≤ ~80 LOC with fixtures Exit: All linters pass against this repo's hand-authored docs; failure modes documented. Parallelisable: 9 linters → 9 sub-tasks. Depends on: CS05
Goal: Port the truly-generic checks from guesswhatisnext.
Deliverables: check-pr-body.mjs, check-commit-trailers.mjs, check-compose-v2.mjs, render-deploy-summary.mjs — refactored to ESM, config-driven (no hard-coded project assumptions), tested against fixtures.
Exit: Each linter has fixture tests and is wired into harness lint.
Parallelisable: 4 ports → 4 sub-tasks. Can run in parallel with CS05 + CS06.
Depends on: CS04
Goal: Write the canonical INSTRUCTIONS / CONVENTIONS / OPERATIONS / REVIEWS / TRACKING / RETROSPECTIVES / READMEGUIDE as templates. Classify each file correctly (per the file-class ADR from CS02). Deliverables:
template/managed/INSTRUCTIONS.md— quick-reference checklist + "When to add X" decision tree pointing at scaffolds + harvest cadence (weekly + bounded before-claim)template/composed/CONVENTIONS.md— language-agnostic core (managed) + local blockid=conventions.projectfor project-specific language/framework conventionstemplate/composed/OPERATIONS.md— claim/dispatch/handoff/sync/harvest core (managed) + local blockid=operations.project-deployfor project-specific deploy commands. WORKBOARD-claim mechanism (per Decision #23): documents the tiny-PR + auto-approve-bot pattern —workboard-onlylabel, dedicatedworkboard-auto-approve.ymlworkflow verifies path-restriction + label + actor-allowlist, GitHub App / bot submits approval and auto-merges, global review-required stays in force. Replaces guesswhatisnext's direct-push exception.template/composed/REVIEWS.md— review loop core (managed) + local blockid=reviews.project-gatesfor project-specific review gates. Documents GPT-5.5 fallback policy (Decision #22).template/managed/TRACKING.md— clickstop lifecycle, workboard state machine, § Agent Identification parameterised onproject.agent_suffix(format<machine-short>-<repo-short>[-c<N>], override viaHARNESS_AGENT_<SUFFIX_UPPER>_MACHINEenv var per Decision #20c — or whateverproject.agent_env_varis set to — derivation rules per Decision #20)template/managed/RETROSPECTIVES.md— precise definition of "learning", category taxonomy (architectural/operational/tooling/process/anti-pattern), harvest procedure, disposition states, both cadences with bounded prompt rulestemplate/managed/READMEGUIDE.md— harness's opinion on consumer READMEs (one-liner, status badges, quickstart, harness pointer, contributing pointer, license, screenshot/demo if applicable, links to ARCHITECTURE.md and CONTEXT.md) — enforced bycheck-readme.mjstemplate/managed/.github/copilot-instructions.md,pull_request_template.md,CODEOWNERStemplate- SemVer policy section in OPERATIONS.md (per GPT-5.5 #9):
- Major: removes/renames required files/headings/states; changes clickstop lifecycle; changes required gates; changes local-block IDs incompatibly; changes config schema incompatibly
- Minor: adds optional scaffold/linter; adds non-blocking recommendations; adds new managed section with default-compatible behavior
- Patch: typo, clarification, bug fix, linter false-positive fix with no new required behavior
- Update guidance: harness updates happen in their own PR/CS; do not run
harness syncmid-clickstop unless fixing a harness blocker; CLI warns on mid-CS or major sync Exit: Allcheck-*linters pass against these templates. Parallelisable: 7 docs + SemVer section → 8 sub-tasks; merge step at end for cross-link integrity. Depends on: CS06
Goal: Empty/structural templates a consumer fills in. Deliverables:
template/seeded/CONTEXT.md— required H2s: Codebase State, Architecture pointer, Blockers, Last updatedtemplate/seeded/ARCHITECTURE.md— Overview + mermaid placeholder, Components, Data model, External integrations, Cross-cutting concerns, Decision log, Known constraintstemplate/seeded/LEARNINGS.md— header + harvest pointer + empty entry slot conforming to schematemplate/seeded/WORKBOARD.md— orchestrator table + active-work table headerstemplate/seeded/README.md— consumer skeleton conforming to READMEGUIDEtemplate/seeded/project/clickstops/{planned,active,done}/.gitkeeptemplate/seeded/harness.config.jsonexample- Fixture test (per GPT-5.5 #1): a fresh
harness initagainst an empty fixture directory must produceREADME.mdfromtemplate/seeded/README.md(proves the seeded README path is exercised even though the harness repo's own root README is project-owned) Exit:harness initagainst an empty repo produces a tree that passes all linters with zero edits; fixture test green. Parallelisable: 5 skeletons + fixture test → 6 sub-tasks. Depends on: CS08
Goal: Copy-and-customize starting points for opt-in patterns.
Deliverables: scaffolds/{smoke,migrations,container-validate,health-check,seed,verify-deploy,feature-flags,cs-probes}/ — each with README.md (the pattern, contract, customization points, when to use), template files with // TODO: customize markers, optional shipped linter (e.g., check-migration-policy.mjs, check-feature-flag-policy.mjs) parameterised via harness.config.json.
Exit: harness init --with-scaffold smoke drops a working stub.
Parallelisable: 8 scaffolds → 8 sub-tasks.
Depends on: CS09
Goal: Replace the bootstrap docs from CS01 with harness sync outputs from template/managed/ + template/composed/ (preserving any local blocks) + template/seeded/. This repo becomes the first consumer.
Deliverables:
harness.config.jsonat repo root pinningversion: self, with explicit exclusion of project-owned files (rootREADME.md,LICENSE,package.json)- Run
harness syncto overwrite root files fromtemplate/managed/; composed files merge any in-flight local blocks; seeded files left untouched - Run
harness lint, commit - CI workflow
.github/workflows/harness-self-check.ymlrunsharness sync --check && harness lint && check-workflow-pinson every PR — guarantees no drift betweentemplate/managed|composed/and root files - Reviewer checklist (per GPT-5.5 #6) attached to the CS11 PR:
- Managed files: root copies must match
template/managed/byte-for-byte - Composed files: managed sections match template; local blocks unchanged
- Seeded files: existing project state preserved
- Project-owned files: README/LICENSE/package.json excluded from sync — verify still intact
- Managed files: root copies must match
- CS01 hand-authored bootstrap docs archived as a CS11 clickstop artifact under
project/clickstops/done/done_cs11_self-host/bootstrap-snapshot/, not as live root docs - Add
harness sync --dry-run --reportoutput as a CS11 PR-attached artifact for review Exit: CI green; intentional drift becomes impossible without updating the template; bootstrap snapshot archived. Parallelisable: No (single coordinated swap). Depends on: CS10
Goal: Two reusable artifacts consumers can adopt with ~10 lines. Deliverables:
.github/workflows/harness-checks.yml(withon: workflow_call) runningharness lint+ selectedcheck-*scripts- The reusable workflow is version-locked: it invokes the consumer-pinned CLI version from
harness.config.jsonrather than the workflow-ref version, so local and CI run the exact same rules (per GPT-5.5 #10) template/managed/.github/workflows/harness-drift.yml— scheduled weekly job in consumers that runsharness sync --checkand opens a PR viapeter-evans/create-pull-requestif drift detected- Documentation in OPERATIONS.md
Exit: Both workflows used by this repo's own CI;
check-workflow-pinsfrom CS06 verifies version coherence. Parallelisable: Reusable workflow / drift workflow / docs → 3 sub-tasks. Depends on: CS11
Goal: Make npm publish a future no-op trigger, even if we never ship to npm.
Deliverables: package.json with "type": "module", "bin": { "harness": "./bin/harness.mjs" }, "files" whitelist (template/, scaffolds/, scripts/, schemas/, lib/, bin/, README.md, LICENSE), engines.node >= 20, zero runtime deps. npm pack --dry-run job in CI verifying tarball size + contents. Schema published with $id URL for editor autocomplete. README install/usage sections covering both npx github:... (Option B) and npx @henrik-me/agent-harness (Option C, future).
Exit: npm pack --dry-run reproducible; tarball ≤ target size; nothing extraneous.
Parallelisable: package.json / CI dry-run / README sections / schema $id → 4 sub-tasks.
Depends on: CS12
Goal: Versioning discipline + verified private-distribution path before any consumer pins us. Deliverables:
- Changesets (or release-please) configured;
CHANGELOG.mdautomation .github/workflows/release.ymlcutting GitHub Releases on tag- SemVer policy already documented in OPERATIONS.md (CS08)
- Tag
v0.1.0, draft GitHub Release - Private-consumption smoke test (per GPT-5.5 #11): in a clean GitHub Actions runner using a fine-grained PAT scoped to
contents:readon the harness repo, runnpx -y github:henrik-me/agent-harness#v0.1.0 --help. Document exact token scopes required while private. Fixture token in any examples uses obvious placeholder (ghp_FAKE_DO_NOT_USE). Exit: Tag exists; private smoke test green; consumers (when they appear) can donpx -y github:henrik-me/agent-harness#v0.1.0 init. Parallelisable: Release tooling / workflow / smoke test → 3 sub-tasks. Depends on: CS13
Goal: Stand up everything that can be prepared while the repo is still private + free-tier (per LRN-001) — public-facing files, CODEOWNERS, bot workflow code, secret/IP review, written Ruleset spec — without actually creating the GitHub Ruleset (impossible until CS15b flips public). Does NOT flip visibility.
Pre-conditions checklist:
Process health:
- CS11 self-host CI gate has been green for ≥ all of CS12–CS14
harness sync --checkruns in < 5s;harness lintruns in < 10sLEARNINGS.mdcontains ≥ 3appliedlearnings from CS12–CS14 demonstrating the harvest loop works- All
openlearnings dispositioned (statusapplied/obsolete/deferredwith explicitdeferred_until) — per LRN-003. Tightens prior wording. Zeroopenlearnings of any age before CS15b proceeds. - Hot-fix stability counter (per GPT-5.5 #16): ≥ 1 CS landed cleanly with no harness changes during execution
Ruleset specification (written, not applied — application moves to CS15b per LRN-001):
6. Ruleset spec committed as docs/ruleset/main-protection.json — the JSON spec for the Ruleset that will be POSTed to GitHub at CS15b. Includes: PR-required, ≥1 approving review, dismiss stale, squash-merge only, linear history, conversation resolution required, signed-commits required, status-checks list (harness-self-check, harness-lint, secret-scan (gitleaks), npm-pack-dry-run, commit-trailers, pr-body, check-workflow-pins, check-public-artifact), no force pushes, no deletions, include administrators (no ad-hoc bypass). Bot threat model (per re-review #3): GitHub App with least privilege (PR-review/write only; no admin/workflow/secrets); bot is NOT a CODEOWNER for any non-WORKBOARD path; CODEOWNERS require human review for code/config/workflow paths so bot approval alone only works for verified WORKBOARD-only PRs; workboard-auto-approve.yml validates exact changed paths + actor allowlist + label + branch naming + absence of workflow/config changes before invoking bot credentials; App credentials stored only in protected/trusted context, never exposed to untrusted PR code.
7. CODEOWNERS coverage spec: every path in template/managed/, template/composed/, schemas/, lib/sync.mjs, lib/composed.mjs, bin/harness.mjs, .github/workflows/ requires owner review (CODEOWNERS file already shipped at CS15a; mechanically enforced from CS15b once Ruleset live).
8. workboard-auto-approve.yml workflow + GitHub App / bot identity built and dry-run tested without protected-branch requirements (using a throwaway PR on the cs01-style discipline-only model). Mechanical activation deferred to CS15b.
Required public-facing files (committed at CS15a):
9. SECURITY.md (vulnerability reporting policy + supported versions table)
10. CONTRIBUTING.md (public-facing contributor flow)
11. CODE_OF_CONDUCT.md
12. .github/ISSUE_TEMPLATE/{bug,feature,learning}.yml
13. .github/pull_request_template.md audited for public phrasing
14. Dependabot or Renovate config
Repo settings (free-tier-compatible): 15. Squash-merge only; auto-delete head branches 16. Wikis disabled; Discussions opt-in 17. Vulnerability alerts + automated security fixes on 18. "Allow auto-merge" enabled (required for tiny-PR claim model once Ruleset is live at CS15b)
Secret hygiene + license/IP review (per GPT-5.5 #4 + #15):
19. gitleaks detect --source . --redact over full history → zero findings
20. All extracted content from guesswhatisnext owned by you / MIT-compatible
21. No tenant IDs, internal URLs, internal operational details, or private repo URLs in any commit
22. All fixture tokens use obvious placeholders (ghp_FAKE_DO_NOT_USE)
23. Release artifacts and packed tarball reviewed for sensitive content
24. If anything sensitive found: rotate + history-rewrite or clean re-export to a fresh public repo
Status-check existence (proves they exist before CS15b makes them required): 25. All status checks listed in #6 have appeared green on at least one CS01–CS14 PR (auditable from GitHub Actions history). No "configure-then-fail" surprises at CS15b.
Deliverables: All 25 preconditions satisfied; repo ready to flip but still private; final pre-flip-readiness.md artifact summarizing scan results, CODEOWNERS coverage, Ruleset spec, bot dry-run results.
Exit: Pre-flip readiness signed off; CS15b can proceed; no GitHub Ruleset created yet (application happens at CS15b).
Parallelisable: Process-health audit / Ruleset spec authoring / bot workflow build + dry-run / public-facing files / repo settings / secret-scan + IP review → 6 sub-tasks.
Depends on: CS14
Goal: Freeze, do final pre-flip checks, flip public, apply the Ruleset and bot wiring authored at CS15a (now possible since the repo is public — per LRN-001 the Ruleset endpoint returns 403 on private free-tier), verify, retrospect. Pre-conditions: CS15a complete (all 25 items satisfied). Freeze: no other PRs land between CS15a sign-off and flip. Deliverables:
- Final scans (immediately before flip):
- Re-run
gitleaks detect --source . --redactover full history (catch anything since CS15a) - Re-run license/IP review on any commits since CS15a
- Confirm no
harness-shadow/branches or other private experimental branches remain
- Re-run
- Flip: repo visibility → public via GitHub settings
- Apply Ruleset (newly possible per LRN-001): POST
docs/ruleset/main-protection.json(authored at CS15a) torepos/henrik-me/agent-harness/rulesets. Verify all required status checks are recognised. - Activate
workboard-auto-approve.ymlworkflow + GitHub App now that the Ruleset enforces the global PR/review requirement that the bot satisfies. - Signed commits flip on (Decision #18) — Ruleset updated to require signed commits.
- README updated to remove private-token install instructions; add public
npx -y github:henrik-me/agent-harness#v0.1.0example. - Post-flip verification:
- External CI run executes
npx -y github:henrik-me/agent-harness#v0.1.0 --helpwith no token → succeeds - Test workboard tiny-PR claim flow against the live Ruleset → bot approves + auto-merges; CI green
- Verify a non-bot PR with disallowed paths is correctly blocked
- CI tokens in any prep-work consumer repos rotated/removed (no longer needed)
- First public GitHub Release notes published
- External CI run executes
- Retrospective: learnings filed about the public-flip process; any surprises during scans dispositioned. Exit: Repo public; Ruleset live + verified; bot auto-merge live + verified; no-token external consumption verified; retrospective filed. Parallelisable: Final scans / Ruleset application + bot activation / README rework / verification (incl. blocked-PR test) / retrospective → 5 sub-tasks. Depends on: CS15a
Goal: First real consumer; validate that harness init produces a working repo on a non-trivial project.
Deliverables:
- New
henrik-me/sub-invadersrepo harness.config.jsonpinningv0.1.0from public git-ref (no token needed since CS15b flipped public)- Seeded files filled in:
ARCHITECTURE.mddocuments the locked-in stack: pure TS + HTML5 Canvas + ES modules + PWA service worker frontend; SWA-hosted Azure Function backend (POST /score,GET /leaderboard); Azure Storage Tables persistence; rate-limit + replay-protection designCONTEXT.mddocuments bootstrap stateREADME.mdfollows READMEGUIDEWORKBOARD.mdinitialised
- Composed files customised:
CONVENTIONS.mdid=conventions.projectblock populated for TS/Canvas;OPERATIONS.mdid=operations.project-deployblock populated for SWA deploy;REVIEWS.mdid=reviews.project-gatesblock populated for SWA-specific gates - First Sub Invaders CS executed end-to-end under harness governance:
SI-CS01: project skeleton + canvas hello-world + SWA staging deploy - Two follow-up CSs filed under
project/clickstops/planned/:planned_sicsNN_re-evaluate-persistence.md— re-evaluate Upstash Redis vs Cloudflare KV vs Azure Storage Tables once leaderboard traffic data existsplanned_sicsNN_re-evaluate-cloudflare-full-stack.md— re-evaluate moving entire stack (Pages + Workers + KV/D1) off Azure once v1 ships Exit: Sub Invaders CI green;harness lintpasses;SI-CS01indone/; staging URL live. Parallelisable: TS+canvas skeleton / SWA infra / leaderboard Function stub / ARCHITECTURE authoring / composed-block customisation → 5 sub-agents. Depends on: CS15b
Goal: Force the harness through real gameplay-development cycles.
Deliverables: ~3–5 small CSs in Sub Invaders covering: a feature flag (e.g., dailyChallenge), a migration-equivalent (Tables schema or partition-key change), a verify-deploy probe, a learnings-harvest cycle, and a prod deploy. Each surfaces friction → file learnings in harness repo. Disposition learnings; tag harness v0.2.0.
Hot-fix policy (per GPT-5.5 #16): harness hot-fixes during a Sub Invaders CS are not failures; they are expected. Each hot-fix resets the stability counter and requires ≥1 additional Sub Invaders CS landed cleanly post-fix before tagging v0.2.0.
Exit: Stability counter ≥ 1 satisfied; harvest cycle completed; v0.2.0 tagged.
Parallelisable: Each Sub Invaders CS is independent → up to 5 sub-agents.
Depends on: CS16
CS17b · Shadow-migration dry-run against guesswhatisnext throwaway branch [GUARDRAIL, per GPT-5.5 #7]
Goal: Validate migration mechanics + mature-app surface coverage that Sub Invaders cannot exercise (doc drift, duplicate-script retirement, reusable-workflow integration against mature CI, composed-block legacy mapping). Explicit non-goal (per GPT-5.5 #10): does NOT validate migrated production behavior — environment protection rules, prod secrets, OIDC, approval gates, App Insights wiring are validated only at CS19/PR-2 against the migration branch's environment. Deliverables:
- Throwaway branch
harness-shadow/of guesswhatisnext (no merge intent) - Run on the branch:
harness sync --dry-run --report— capture which existing files would be overwritten/preserved/skipped/conflictedharness lint— capture every existing file's linter resultharness check-migration --from-existing-harness— capture duplicate scripts, workflow-ref mismatches, config overrides requiredharness composed-audit --from-existing-harness— capture legacy unmarked content in CONVENTIONS/OPERATIONS/REVIEWS that needs explicit block-ID mapping (per GPT-5.5 #2)- Reusable-workflow swap dry-run — wire up the reusable workflow in a separate workflow file (no replacement of existing workflow) and confirm it runs green on the throwaway branch
- Compile findings into
shadow-migration-report.md(sanitized per Decision #24) archived in harnessproject/clickstops/done/done_cs17b_shadow-migration/. Raw run logs/secrets stay in private CI artifacts. - Each surprise → harness learning + (if needed) harness fix; iterate until shadow run is clean
legacy_composed_mapping.jsonproduced ready-to-edit (per re-review #11) with per-region confidence levels:auto_mapped(parser-confident match to a known block ID),needs_user_choice(multiple plausible block IDs),discard_candidate(orphaned/superseded content the parser flags for likely discard),unmapped(no proposal). CS17b exit requiresunmapped == 0— every region has at least a tentative classification. CS19 only reviews and approves the mapping; it does not discover the workload for the first time.- Throwaway branch deleted after report archived
Exit: Shadow-migration report shows zero unexpected findings;
composed-auditproduceslegacy_composed_mapping.jsonwithunmapped == 0and explicit confidence levels; harness adjustments (if any) tagged into av0.2.xpatch;v0.2.xready for real migration. Parallelisable: Each report subsection → 5 sub-tasks (sync/lint/check-migration/composed-audit/workflow-dry-run). Depends on: CS17a
Goal: Define the PILOT framework so CS18b execution and CS19/PR-2 parity are objective gates, not vibes. Deliverables:
- PILOT candidate selection criteria document: small diff, exercises every gate (PR checks, staging deploy, container-validate, prod deploy with approval, App Insights soak/verify-traces), low blast radius. Examples: copy tweak with telemetry tag, noop refactor with feature-flag gate, admin-only endpoint addition.
- Per-gate parity manifest schema (per GPT-5.5 #3): for each gate, declare:
{ "gate": "container-validate", "required": true, "expected_status": "pass", "required_artifacts": ["container-validate.log", "summary.json"], "normalized_fields": ["exit_code", "check_names", "required_probe_results"], "ignored_fields": ["timestamp", "run_id", "duration_ms", "commit_sha"], "max_duration_delta_pct": 50 } parity-comparator.mjsscript that diffspilot-a-baseline.jsonvspilot-b-result.jsonper the manifest and exits non-zero on unapproved deltaspilot-parity-allowlist.jsonschema; allowlist entries must be predeclared (no post-hoc rationalisation)- "Equivalent in shape" defined precisely: PILOT-B must exercise the exact same named gates as PILOT-A in the same order, not merely a similar-sized change
- Candidate exclusion (per re-review #2): PILOT candidates must be mergeable and comparable under both the existing in-repo harness AND the migrated harness using equivalent named gates. Changes whose value depends on a migrated-harness-only gate (e.g. a feature flag that requires
check-feature-flag-policywhich only exists in the migrated harness) are NOT valid PILOTs — they are handled as a separate post-migration smoke/acceptance PR after CS19. - Approval process: any allowlist additions require user approval before PR-2 opens
- Storage location: artifacts live in harness repo
project/clickstops/active/CS18b/andCS19/ - Comparator self-test: contrived PILOT-A and PILOT-B fixtures with intentional deltas verify the comparator catches and approves correctly Exit: Schema, comparator, allowlist format, and selection criteria all reviewed and merged. Comparator self-test green. Parallelisable: Selection criteria / manifest schema / comparator / allowlist / self-test → 5 sub-tasks. Depends on: CS01 (can start any time after CS01; serializes against CS18b only).
Goal: Execute PILOT-A under the current in-repo harness; capture the baseline regression spec.
Pre-conditions: CS17b clean; CS18a artifacts merged. Freshness SLA: baseline must be ≤ 7 days old at CS19 PILOT-B merge-ready time AND no relevant guesswhatisnext workflow/harness/deploy changes have landed since baseline. If freshness fails, re-run CS18b. (Note: the stacked-PR design in CS19 — see GPT-5.5 #3+#4 fix — runs PILOT-B against the migration branch before PR-1 merges, eliminating the previous expiry-after-merge risk.)
Freshness calendar artifact (per GPT-5.5 #14): CS18b emits freshness-calendar.md recording: baseline timestamp, expiry timestamp (baseline + 7d), planned PILOT-B execution window, planned PR-1 merge window. CS19 startup checks the calendar and refuses to begin if windows don't fit before expiry. Forces upfront scheduling honesty.
Deliverables:
- Pick PILOT-A using CS18a criteria
- Execute end-to-end under existing in-repo harness:
- claim → WORKBOARD update
- branch + PR → all PR-body / commit-trailer / docs-consistency checks
- local review loop + Copilot review + thread resolution
- merge to main
- staging deploy via existing workflow
- ephemeral smoke + container-validate
- prod deploy (with explicit user approval gate)
- 60-min App Insights soak / verify-traces
- CS file moved to
done/, learnings filed
- Capture every gate output to
pilot-a-baseline.json(machine-readable, per CS18a manifest) +PILOT-A-baseline.md(human narrative). Both committed to harness repoproject/clickstops/active/CS18b/. Exit: PILOT-A merged to prod; soak passed; baseline artifacts committed; freshness SLA timer started. Parallelisable: No (deliberately serial — observing live pipeline). Depends on: CS17b, CS18a.
Goal: Swap guesswhatisnext to consume the harness with PILOT-B parity verified before the migration PR merges (per GPT-5.5 #3+#4 stacked-PR fix; refined per re-review #1, #3, #4, #9). Eliminates the previous "PILOT-B as rollback" weakness — parity is now a true pre-merge gate.
Pre-conditions:
- CS17b clean;
legacy_composed_mapping.json(withunmapped == 0) reviewed and approved - CS18b baseline complete;
freshness-calendar.mdshows planned PR-1 + PILOT-B + final-merge windows fit before expiry - Stacked-PR strategy: all migration work happens on long-lived branch
migration/harness-pr1; PILOT-B runs against that branch (and a temporary staging slot wired to it) before the migration squash-merges tomain. - Migration-base SHA recorded at branch creation (per re-review #4):
migration_base_shacaptured inmigration-meta.json. This is themainSHA the migration is anchored to.
Scope of the parity gate (per re-review #3 — honest reduced-scope option chosen):
The CS19 pre-merge parity gate covers staging + container-validate + CI gates only. Production parity is NOT validated pre-merge in CS19 v0.2.x. Production validation is performed post-merge on main with explicit user approval before the prod-deploy workflow_dispatch is triggered. A future CS (filed at CS19 close) will add a true shadow-prod environment for pre-merge prod parity in a later harness version. This is documented honestly in the LEARNINGS file at CS19 close-out — not papered over.
Migration-branch divergence controls (per re-review #4):
- CS19 startup check (per re-review #9): asserts
current_date < freshness_calendar.expiryANDmainhas had no changes touchingworkflow/harness/deploy/parity-relevantpaths sincepilot-a-baseline.commit_shaANDmigration/harness-pr1is rebased onto an approvedmainSHA. If any check fails: refuse to proceed; rerun CS18b or rebase as appropriate. - Before PILOT-B (PR-2) starts:
migration/harness-pr1MUST be rebased onto currentmain; re-runharness composed-audit, migration invariant verification, and CI; refreshmigration_base_sha. Any change to migration-touched files onmainbetween rebase and final merge requires another rebase + re-run. - Soft freeze of unrelated changes touching migration-affected files between PR-2 start and final merge (recorded in WORKBOARD; not a hard branch lock). Per re-review #4: the soft freeze is schedule protection, not correctness protection — correctness is enforced by the final-merge SHA-equality gate below. Any emergency change touching migration-affected paths requires explicit user acknowledgement that CS19 parity restarts (rebase + composed-audit + invariant + CI + PILOT-B re-run).
- Final-merge gate: assert
mainHEAD SHA equals the SHA against which PILOT-B parity was validated. Ifmainadvanced since then, rebase + re-run PILOT-B. No exceptions.
Deliverables:
-
Migration branch setup: create
migration/harness-pr1frommain. Recordmigration_base_shainmigration-meta.json. Configure a temporary staging-slot deploy that points at this branch (the existing staging deploy continues pointing atmainfor any unrelated guesswhatisnext work). -
PR-1 (open against
migration/harness-pr1): this PR contains the full harness migration:- Pre-migration project-state manifest (per GPT-5.5 #17) captured: list of historical clickstops, learnings, workboard rows, context content, project-specific architecture sections, app-specific workflows/scripts. Stored as
pre-migration-manifest.json(sanitized per Decision #24). - Run
harness sync --dry-run --report,harness check-migration --from-existing-harness,harness composed-audit --from-existing-harnesswith the approvedlegacy_composed_mapping.json; all reports attached to PR-1 - Add
harness.config.jsonpinningv0.2.x, runharness sync(composed sync uses approved mapping; sync's fail-closed invariant per CS03 enforces no unmapped overwrite) - Audit diff: intended drift documented; unintended drift fixed in harness, re-tagged, re-pinned
- Composed-class blocks: legacy unmarked content migrated into local blocks per
legacy_composed_mapping.json - Retire duplicate
scripts/check-*.js - Swap
.github/workflows/policy checks to the reusable workflow from CS12 - Migration invariant verification: post-sync, compare against
pre-migration-manifest.json— no historical clickstop / learning / workboard / context content was deleted or overwritten; no unmarked composed-doc content lost unless explicitly listed inlegacy_composed_mapping.jsonas discarded; any seeded-file collision was reported and skipped - CI green on
migration/harness-pr1 - PR-1 does not merge yet — held open pending PILOT-B parity
- Pre-migration project-state manifest (per GPT-5.5 #17) captured: list of historical clickstops, learnings, workboard rows, context content, project-specific architecture sections, app-specific workflows/scripts. Stored as
-
PR-2 (PILOT-B execution against the migration branch — VALIDATION-ONLY, per re-review #1):
- Branch
pilot-b/<slug>created frommigration/harness-pr1for PILOT-B work - Execute PILOT-B per CS18a definition under the migrated harness
- Deploy to the temporary migration-branch staging slot
- Run all gates: PR checks, staging deploy, container-validate, CI gates (production gates explicitly out-of-scope per "honest reduced-scope" above)
pilot-b-result.jsonemitted per CS18a manifest (sanitized per Decision #24)parity-comparator.mjsruns; classifies deltas aspredeclared-allowed/newly-proposed/rejected- Allowlist policy (per GPT-5.5 #11): any
newly-proposeddelta requires explicit user approval AND rerunning PILOT-B after the allowlist addition. Emergency waivers explicitly recorded in PR + learning log. Comparator output preserves the classification audit trail. - PR-2 is NOT merged into
migration/harness-pr1ormain. It is a validation-only PR. Its result artifacts (pilot-b-result.{md,json}) are attached to PR-1's check-runs / uploaded as workflow artifacts, not committed to the migration branch (which would contaminate the squash-merge diff per re-review #1). PR-2 is closed as superseded once parity is clean. The pilot artifacts are committed to the harness repo CS archive at close-out (Step 6) — not to guesswhatisnext. - The PILOT-B product change itself is independently re-applied to
mainafter the migration lands, via the standard guesswhatisnext PR flow — fully decoupled from the migration squash-merge. This keeps the migration diff "just migration" and avoids double-merge contamination.
- Branch
-
Final merge gate (per re-review #4):
- Parity comparator zero-rejected, zero-newly-proposed-unapproved
- Migration invariant verified
- Re-assert
mainHEAD SHA equals the SHA against which PILOT-B parity was validated — ifmainadvanced, rebasemigration/harness-pr1, re-run composed-audit + invariant + CI, re-run PILOT-B parity, repeat - User explicit approval to merge
migration/harness-pr1→main - Squash-merge
migration/harness-pr1→main(this is the actual harness migration landing — diff contains only migration mechanics) - Temporary staging-slot deploy decommissioned; staging returns to pointing at
main - Soft freeze on migration-touched files lifted
-
Post-merge production validation (out of pre-merge gate, per honest reduced-scope):
- Deploy migrated
mainto prod via existing approval-gated workflow - Run verify-traces / App Insights soak per existing OPERATIONS procedure
- If anomalies: revert via documented rollback (below)
- File a planned-state guardrail CS for "true shadow-prod environment for pre-merge prod parity" with an explicit trigger (per re-review #5): must be dispositioned before the next mature production-app migration AND before harness
v0.4.0. Tracked as a planned-state CS in the harness repo (not just a learning), with the trigger encoded in its frontmatter so it surfaces in the right harvest cycle.
- Deploy migrated
-
Migration close-out: archive
pilot-a-baseline.{md,json},pilot-b-result.{md,json},pre-migration-manifest.json,composed-migration-manifest.json,legacy_composed_mapping.json,freshness-calendar.md,migration-meta.json(all sanitized) to harnessproject/clickstops/done/. Update guesswhatisnext LEARNINGS. File the future-shadow-prod CS asplanned_csNN_*in the harness repo.
Exit: migration/harness-pr1 merged to main; PILOT-B staging-parity verified pre-merge (production validation explicitly post-merge per documented scope); staging+container-validate green pre-merge, prod green post-merge; in-repo harness duplicates deleted; guesswhatisnext is now a harness consumer; project-state invariant verified; soft freeze lifted; future-shadow-prod CS filed.
Parallelisable: PR-1 sub-tasks (config+sync, workflow swap, duplicate retirement, diff audit, manifest verification, composed-mapping application) → 6 sub-agents. PR-2 (PILOT-B validation) is serial.
Depends on: CS17b, CS18b.
Rollback path: if anything fails post-merge (including production validation), revert migration/harness-pr1 merge commit; guesswhatisnext continues operating with its in-repo harness as before; learnings filed; CS19 retried with adjustments. Documented rollback command + timebox in OPERATIONS.md.
Goal: Run the harvest cycle for real one more time across two consumers; explicit decision on npm publication. Deliverables:
- All
openlearnings from CS16–CS19 dispositioned - Template improvements rolled in
v0.3.0tag- Explicit user decision recorded in
LEARNINGS.md: stay on git-ref, or publish to npm as@henrik-me/agent-harness - If publishing: CI workflow + npm scope provisioned + initial
npm publishfrom tag + Sigstore attestation considered Exit: v0.3.0 tagged; both consumers pin v0.3.0 cleanly; npm decision recorded. Parallelisable: Per-learning disposition can fan out → N sub-tasks. Depends on: CS19
CS01 → CS02 → CS03 → CS04 → CS05 → CS06 ─┐
└── CS07 ─────────┤
├→ CS08 → CS09 → CS10 → CS11 → CS12 → CS13 → CS14 → CS15a → CS15b → CS16 → CS17a → CS17b ─┐
├→ CS19 → CS20
CS18a (start any time after CS01) → CS18b (after CS17b) ┘
| CS | Independent sub-tasks |
|---|---|
| CS02 | 9 (3 schemas / 2 ADRs / 3 examples / 1 CI wiring) |
| CS03 | 5 (sync.mjs / templating.mjs / lock.mjs / composed.mjs / fixtures) |
| CS04 | 9 (one per subcommand incl. whoami) |
| CS05 | 3 (doc-schema lib / linter / fixtures) |
| CS06 | 9 linters incl. workflow-pins + public-artifact |
| CS07 | 4 policy checks (parallel with CS05+CS06) |
| CS08 | 8 (7 docs + SemVer section) |
| CS09 | 6 (5 skeletons + fixture test) |
| CS10 | 8 scaffolds |
| CS12 | 3 (reusable workflow / drift workflow / docs) |
| CS13 | 4 (package.json / CI dry-run / README / schema $id) |
| CS14 | 3 (release tooling / workflow / private smoke test) |
| CS15a | 6 (process-health audit / branch-protection / public-facing files / repo settings / secret+IP review / branch-protection dry-run) |
| CS15b | 4 (final scans / README rework / verification / retrospective) |
| CS16 | 5 (TS skeleton / SWA infra / leaderboard Function / ARCHITECTURE / composed-block customisation) |
| CS17a | 3–5 Sub Invaders CSs |
| CS17b | 5 (sync / lint / check-migration / composed-audit / workflow-dry-run) |
| CS18a | 5 (criteria / manifest / comparator / allowlist / self-test) |
| CS19 | 6 PR-1 sub-tasks incl. composed-mapping application (PR-2/PILOT-B serial) |
| CS20 | N learnings dispositions in parallel |
CS01, CS11, CS18b, CS19/PR-2 (PILOT-B against migration branch) are deliberately serial.
| Phase | CSs | Enforcement |
|---|---|---|
| Spirit phase / discipline-only | CS01–CS14 | Manual discipline + GPT-5.5 review on every PR. Branch protection deferred to CS15b per LRN-001 (private-repo branch protection requires GitHub Pro). CI gates land progressively: linters from CS05+, self-host gate from CS11. |
| Public-readiness phase | CS15a | Ruleset spec authored as docs/ruleset/main-protection.json (committed, not applied — Ruleset POST returns 403 on private free-tier per LRN-001); workboard-auto-approve workflow + GitHub App built and dry-run-tested (not yet the live claim mechanism); secret-scan + IP review complete; all open learnings dispositioned per LRN-003. |
| Public-enforced phase | CS15b+ | Repo public → Ruleset live; signed commits required; full PR policy mechanically enforced; check-public-artifact mandatory. |
- Pre-claim: run
harness harvest(when CS04 lands) — handle any high-priority stale learnings; before that, manualLEARNINGS.mdreview. - Claim (per Decision #23 — tiny-PR + auto-approve-bot model from CS15b onward): rename
planned_csNN_*.md→active_csNN_*.md; updateWORKBOARD.md; commit on aworkboard/cs<NN>-claimbranch; open PR labeledworkboard-only. From CS15b onward: the liveworkboard-auto-approve.ymlworkflow verifies path-restriction + label + actor; bot submits the approval; PR auto-merges once CI passes. CS01–CS14 transitional (post-bootstrap, per LRN-001): the only direct-to-main push in the entire repo is the CS01 bootstrap commit. From commit 2 onward, all changes go through PRs by discipline (mechanical branch protection unavailable on private free-tier repos until CS15b). WORKBOARD claim/closeout PRs are normal small PRs with user review. CS15a transitional: the bot workflow + GitHub App are built and dry-run-tested, but the bot is not yet the live claim mechanism — small PRs with user review continue. The bot becomes live at CS15b when the Ruleset is applied. Setagent: yoga-ah(derived per Decision #20),status: 🟢 Active. - Branch:
cs<NN>/<slug>. - Plan-internal: review CS deliverables; identify parallelisable sub-tasks per the table above; dispatch sub-agents (Haiku for mechanical, Sonnet for non-trivial).
- Implement: execute sub-tasks; merge sub-agent output; iterate.
- Local review (per Decisions #15 + #22 fallback): primary = rubber-duck with GPT-5.5. If GPT-5.5 unavailable >30min or 2 failed attempts → fallback to Claude Sonnet 4.6 rubber-duck (different model family/configuration than the Opus 4.7 implementer — independent-critique invariant preserved) OR explicit user waiver. High-risk CSs (CS03, CS11, CS15a/b, CS18b, CS19): require GPT-5.5 OR explicit user waiver — no Sonnet fallback. PR body records: model, timestamp, fallback reason if applicable.
- Open PR: body follows
pull_request_template.md; commit trailers includeCo-authored-by: Copilot. - CI checks: all required checks pass (linters from CS05+ enforce this mechanically).
- Review:
- Private phase (CS01–CS15a): GPT-5.5 + your review. Copilot review optional.
- Public phase (CS15b+): GPT-5.5 + Copilot review + your review on CODEOWNERS-protected paths.
- Threads resolved, then squash-merge.
- Post-merge (per Decision #23): rename
active_csNN_*.md→done_csNN_*.md; move toproject/clickstops/done/; updateWORKBOARD.md(status removed); updateCONTEXT.mdif the CS changed codebase state. From CS15b onward, all WORKBOARD updates go through the tiny-PR claim mechanism with the bot. - Capture learnings: file every learning surfaced during the CS into
LEARNINGS.mdper the schema (after CS05 lands; before that, hand-authored entries that the future linter will validate). - Harvest reminder: if CS-close triggers the weekly cadence, run harvest now.
- Implementation: Claude Opus 4.7 1M (this me)
- Mechanical sub-tasks: Claude Haiku 4.5 (e.g., 9 parallel linters in CS06)
- Non-trivial sub-tasks: Claude Sonnet 4.6 (e.g., schema design in CS02 sub-tasks)
- Local review: GPT-5.5 via rubber-duck agent (mandatory pre-PR; mandatory pre-template-commit). Fallback: Claude Sonnet 4.6 rubber-duck (different model family from the Opus 4.7 implementer; non-high-risk CSs only) or user waiver.
- PR review: Copilot (optional pre-CS15b, mandatory post-CS15b)
- Final approval: you, on every PR
I do not run harness sync mid-CS unless fixing a harness blocker (per CS04 CLI warning + CS08 SemVer policy). Harness updates land in their own dedicated CS. This protects against process-shape changes mid-flight.
The two pre-CS01 planning artifacts (harness-extraction-plan.md, harness-cs-plan.md) move into the new repo as part of CS01's clickstop body. The C:\src\harness\ working directory becomes superseded by the new repo's local clone path. Probably C:\src\agent-harness\.
| Q | Answer |
|---|---|
| CS06 granularity | One CS, parallelise 8 linters via sub-agents |
| Greenfield project | Sub Invaders (full spec in CS16) |
| License | MIT |
| Harvest cadence | Weekly + bounded before-claim with user prompt |
| CS10 scaffold scope | One CS, parallelise 8 scaffolds |
| Org / public-or-private | henrik-me, private at CS01, hardened at CS15a, public at CS15b with full PR policy enforcement |
| First adopter order | Sub Invaders before guesswhatisnext (so CS17a battle-tests + CS17b shadow-migrates before CS19 migrates) |
| Migration safety | Stacked-PR model: PILOT-A baseline (CS18b, freshness ≤ 7d, freshness-calendar artifact) → PR-1 on migration/harness-pr1 branch → PILOT-B parity on that branch → user approval → squash-merge to main. Parity is a true pre-merge gate, not rollback. |
| Composed file class | Hardened parser (markers outside code fences, strict regex, exact start/end ID match); legacy unmarked content handled fail-closed via composed-audit + legacy_composed_mapping.json; lock file records per-block provenance |
| Public-artifact safety | All post-CS15b artifacts sanitized; check-public-artifact linter blocks tokens, tenant IDs, internal URLs, full logs |
| GPT-5.5 review fallback | Opus rubber-duck for non-high-risk CSs; user waiver otherwise; PR records model/timestamp/reason |
| WORKBOARD claim mechanism | Tiny auto-merged PRs from CS15b onward (bot built + dry-run at CS15a, activated when Ruleset is applied at CS15b); replaces direct-push exception |
| Sub Invaders persistence | Azure Storage Tables v1; follow-ups filed in CS16 |
| Sub Invaders deployment | Azure Static Web Apps v1; follow-up filed in CS16 |
| Sub Invaders frontend stack | Pure TS + Canvas + ES modules + PWA, zero runtime deps |
| PILOT-A candidate | Picked during CS18a |
| File classes | 3-class model: managed / composed / seeded |
| README ownership | Harness repo's root README is project-owned (excluded from sync); template/seeded/README.md is the consumer skeleton |
| Implementation model | Opus 4.7 1M orchestrator; Haiku/Sonnet sub-agents |
| Local review | GPT-5.5 mandatory pre-PR and pre-template-commit |
| Hot-fix policy | Resets stability counter; ≥1 clean Sub Invaders CS post-fix before next harness tag |
| Mid-CS sync | Prohibited; CLI warns; harness updates in own CS |