V1 Harness Refactor Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Rebuild CodeAlmanac's AI execution path around Build, Absorb, Garden, a provider-neutral harness SDK, and a per-wiki process/job manager.
Architecture: This is a deliberate breaking refactor. Do not preserve the current bootstrap / writer / hardcoded reviewer pipeline unless a piece directly fits the new architecture. Build the correct structure first: operation layer -> AgentRunSpec -> process manager -> harness SDK -> provider adapter -> normalized events -> wiki snapshots/reindex.
Tech Stack: TypeScript, Commander, Vitest, Node child processes, filesystem JSONL logs, existing SQLite indexer, Claude Agent SDK, Codex CLI/app-server/SDK adapter exploration.
Read Before Coding#
Read these files first, in this order:
AGENTS.md/Users/rohan/Desktop/Projects/openalmanac/docs/ideas/codebase-wiki.mddocs/plans/2026-05-08-wiki-agent-operations-and-cli-design.mddocs/plans/2026-05-10-harness-process-architecture.mddocs/research/2026-05-09-claude-harness-capabilities.mddocs/research/2026-05-09-codex-harness-capabilities.md- OpenAlmanac GUI provider references:
/Users/rohan/Desktop/Projects/openalmanac/gui/main/domains/providers/service.js/Users/rohan/Desktop/Projects/openalmanac/gui/main/domains/providers/claude-adapter.js/Users/rohan/Desktop/Projects/openalmanac/gui/main/domains/providers/codex-adapter.js/Users/rohan/Desktop/Projects/openalmanac/gui/shared/providers/runtime-events.d.ts/Users/rohan/Desktop/Projects/openalmanac/gui/src/domains/providers/models.ts
Operating Rules For This Refactor#
- This branch is allowed to break the old architecture.
- Prefer deleting stale abstractions over adapting them awkwardly.
- Do not create a source/evidence pipeline.
- Do not recreate the hardcoded writer/reviewer capture architecture.
- Prompts use a small shared base (
prompts/base/purpose.md,notability.md,syntax.md) plusprompts/operations/build.md,absorb.md,garden.md, and emptyprompts/agents/.gitkeep. - Prompt assembly is simple string joining with
loadPrompt()andjoinPrompts(). - All write-capable AI commands create CodeAlmanac jobs.
initdefaults foreground;capture,ingest, andgardendefault background..almanac/runs/is the only run/log directory and must be gitignored.- Commit and push after each coherent task or phase.
- Keep
npm testgreen at every commit unless a commit message explicitly states a temporary failing checkpoint. Prefer not to make failing commits.
Required Logs#
Maintain these files throughout implementation:
docs/plans/2026-05-10-v1-implementation-log.mddocs/plans/2026-05-10-v1-decision-log.md
Update the implementation log after each task:
YYYY-MM-DD HH:MM PT
- Built:
- Files changed:
- Tests run:
- Result:
- Next:Update the decision log whenever a design choice changes or a tradeoff is made:
YYYY-MM-DD HH:MM PT
Decision:
Context:
Alternatives:
Why:
Consequences:Commit / Push Cadence#
Use small commits:
git add <files>
git commit -m "<type>(v1): <summary>"
git pushRecommended commit types:
docs(v1): ...
feat(v1): ...
refactor(v1): ...
test(v1): ...
fix(v1): ...After each substantial phase, dispatch a review agent. The review should check
for architecture drift against 2026-05-10-harness-process-architecture.md,
not just local code style.
Target Directory Shape#
New or refactored directories:
src/harness/
types.ts
events.ts
tools.ts
prompts.ts
index.ts
providers/
index.ts
claude.ts
codex.ts
cursor.ts
src/process/
types.ts
ids.ts
records.ts
logs.ts
snapshots.ts
manager.ts
src/operations/
build.ts
absorb.ts
garden.ts
prompt-context.ts
src/commands/jobs.ts
src/commands/init.ts
src/commands/capture.ts
src/commands/ingest.ts
src/commands/garden.ts
prompts/
operations/
build.md
absorb.md
garden.md
agents/
.gitkeepThe exact filenames can change if implementation proves a better split, but the boundaries should remain.
Phase 1: Prompt System Reset#
Task 1.1: Replace Flat Prompts With Base And Operation Prompts#
Files:
- Create:
prompts/base/purpose.md - Create:
prompts/base/notability.md - Create:
prompts/base/syntax.md - Create:
prompts/operations/build.md - Create:
prompts/operations/absorb.md - Create:
prompts/operations/garden.md - Create:
prompts/agents/.gitkeep - Keep temporarily if needed:
prompts/bootstrap.md,prompts/writer.md,prompts/reviewer.md - Modify:
package.jsononly if needed;promptsis already included. - Update log:
docs/plans/2026-05-10-v1-implementation-log.md
Steps:
- Create the base and operation prompt files.
purpose.md: cultivated project memory, deep-research cache, project-world map, inputs as raw material, synthesis over logs.notability.md: page existence, entities, dependencies, influences, research/product/market synthesis, topics, clusters, hubs, temporal pages, splitting, merging, archiving, and supersession.syntax.md: frontmatter, source grounding, natural slugs, wikilinks, topic tagging, lead-first page shape, citations, and anti-patterns.build.md: deep first construction pass, corpus exploration, substantial initial wiki, optional bounded helper/subagent investigations.absorb.md: improve wiki from starting context, input is not output, prefer evolving synthesis pages, no-op valid.garden.md: improve whole wiki graph, merge/split/archive/relink/retopic, cultivate clusters and hubs, avoid churn.- Leave
prompts/agents/empty except.gitkeep. - Run targeted operation prompt tests.
- Record result in implementation log.
- Commit and push.
Task 1.2: Add Path-Based Prompt Loader And Join Helper#
Files:
- Modify:
src/agent/prompts.tsor move tosrc/harness/prompts.ts - Test: add/update prompt loader tests near existing prompt tests
- Update logs
Steps:
- Support prompt names with slash paths, e.g.
operations/build. - Reject paths that escape
prompts/. - Add
joinPrompts(parts: Array<string | undefined | null>): string. - Join with clear separators, not a complex manifest.
- Keep compatibility for old prompt names only if needed during transition.
- Add tests for:
loadPrompt("base/purpose")loadPrompt("operations/build")- nested prompt path traversal rejection
joinPromptsskips empty parts
- Run targeted tests.
- Commit and push.
Phase 2: Harness SDK Core#
Task 2.1: Define Provider-Neutral Harness Types#
Files:
- Create:
src/harness/types.ts - Create:
src/harness/events.ts - Create:
src/harness/tools.ts - Modify or retire:
src/agent/types.ts - Tests:
test/harness-types.test.tsif useful for pure helpers - Update logs
Core types:
export interface AgentRunSpec {
provider: {
id: "claude" | "codex" | "cursor";
model?: string;
effort?: string;
};
cwd: string;
systemPrompt?: string;
prompt: string;
tools?: ToolRequest[];
agents?: Record<string, AgentSpec>;
skills?: string[];
mcpServers?: Record<string, unknown>;
limits?: {
maxTurns?: number;
maxCostUsd?: number;
};
output?: {
schemaPath?: string;
};
metadata?: {
operation: "build" | "absorb" | "garden";
targetKind?: string;
targetPaths?: string[];
};
}Steps:
- Define
ToolRequestbase tools:read,write,edit,search,shell,web,mcp. - Define
AgentSpecwithout any reviewer/scout-specific logic. - Define
HarnessEvent:text_delta,text,tool_use,tool_result,tool_summary,context_usage,error,done. - Define
HarnessCapabilities. - Do not import Claude SDK types in provider-neutral files.
- Commit and push.
Task 2.2: Build Harness Provider Registry#
Files:
- Create:
src/harness/providers/index.ts - Create:
src/harness/index.ts - Modify: existing
src/agent/providers/*only as migration path - Tests: provider registry tests
- Update logs
Steps:
- Create an adapter interface:
interface HarnessProvider { metadata: ProviderMetadata; checkStatus(): Promise<ProviderStatus>; run(spec: AgentRunSpec, hooks: HarnessRunHooks): Promise<HarnessResult>; } - Add
getHarnessProvider(id). - Add provider metadata and capabilities.
- Keep provider quirks inside provider adapters.
- Commit and push.
Phase 3: Process Manager#
Task 3.1: Add Run Records And IDs#
Files:
- Create:
src/process/types.ts - Create:
src/process/ids.ts - Create:
src/process/records.ts - Test:
test/process-records.test.ts - Update logs
Steps:
- Generate stable run ids like
run_<timestamp>_<short-random>or equivalent. - Store run records in
.almanac/runs/<run-id>.json. - Store event logs in
.almanac/runs/<run-id>.jsonl. - Implement atomic record writes.
- Implement stale detection by PID.
- Test read/write/list/status transitions.
- Commit and push.
Task 3.2: Add Snapshot And Delta Accounting#
Files:
- Create:
src/process/snapshots.ts - Reuse/refactor from:
src/commands/capture.ts - Test:
test/process-snapshots.test.ts - Update logs
Steps:
- Snapshot
.almanac/pages/*.mdby slug/hash/archive state. - Compute created/updated/archived counts.
- Ignore non-markdown files.
- Keep this deterministic and provider-free.
- Commit and push.
Task 3.3: Implement Process Manager Start Path#
Files:
- Create:
src/process/manager.ts - Create:
src/process/logs.ts - Tests:
test/process-manager.test.ts - Update logs
Steps:
- Implement foreground execution first.
- Manager creates run record, snapshots before, calls harness, records events, snapshots after, reindexes, writes final record.
- Add injectable fake harness for tests.
- Add tests for success, failure, no-op delta, event log writing.
- Commit and push.
Task 3.4: Add Background Job Execution#
Files:
- Modify:
src/process/manager.ts - Create if needed:
src/process/child-entry.ts - Modify:
bin/codealmanac.tsor CLI dispatch to support internal job execution - Tests: focused process/background tests where feasible
- Update logs
Steps:
- Add detached background launch.
- Background child should rehydrate
AgentRunSpecfrom run record or a temp spec file under.almanac/runs/. - Parent exits after writing
startedrecord and printing run id. - Child owns actual harness run.
- Ensure
CODEALMANAC_INTERNAL_SESSION=1to avoid recursive hooks. - Commit and push.
Phase 4: Provider Adapters#
Task 4.1: Port Claude To Harness Adapter#
Files:
- Create:
src/harness/providers/claude.ts - Retire or adapt:
src/agent/providers/claude/index.ts - Tests: Claude adapter tests with fake SDK/query where possible
- Update decision log for permission/tool choices
Steps:
- Map
AgentRunSpecto Claude Agent SDK query options. - Map base tools to Claude native tools.
- Keep
agentsgeneric; do not hardcode reviewer. - Normalize Claude stream to
HarnessEvent. - Capture cost, turns, session id, usage when exposed.
- Add status/auth check equivalent to current behavior.
- Commit and push.
Task 4.2: Choose Codex Transport And Port Adapter#
Files:
- Create:
src/harness/providers/codex.ts - Reference: OpenAlmanac GUI Codex adapter and
docs/research/2026-05-09-codex-harness-capabilities.md - Tests: Codex adapter tests with fake process/app-server
- Update decision log with chosen transport
Steps:
- Decide between
codex exec --json, Codex app-server, or Codex SDK based on current local capability and implementation cost. - Keep the choice adapter-internal.
- Map
AgentRunSpecto chosen Codex transport. - Normalize events to
HarnessEvent. - Preserve usage/context usage when available.
- Do not claim programmatic per-run subagents unless implemented and tested.
- Commit and push.
Task 4.3: Cursor Placeholder Or Adapter#
Files:
- Create/modify:
src/harness/providers/cursor.ts - Tests: status and unsupported behavior
- Update logs
Steps:
- Either port the current Cursor CLI adapter or create an explicit unsupported/low-fidelity adapter behind capabilities.
- Do not block the refactor on Cursor if Claude/Codex are the priority.
- Commit and push.
Phase 5: Operations#
Task 5.1: Build Operation#
Files:
- Create:
src/operations/build.ts - Modify:
src/commands/init.tsif command remains there - Tests:
test/build-operation.test.ts - Update logs
Steps:
- Resolve repo root and
.almanac/. - Init
.almanac/structure if missing. - Build prompt from
prompts/operations/build.mdplus runtime context strings. - Construct
AgentRunSpecwith metadata{ operation: "build", targetKind: "repo" }. - Route through process manager.
- Default foreground.
- Commit and push.
Task 5.2: Absorb Operation#
Files:
- Create:
src/operations/absorb.ts - Modify/create:
src/commands/capture.ts,src/commands/ingest.ts - Tests:
test/absorb-operation.test.ts - Update logs
Steps:
- Implement one internal Absorb operation.
captureprepares transcript/session runtime strings and calls Absorb.ingestprepares file/folder runtime strings and calls Absorb.- Do not create a separate source/evidence layer.
- Default background.
- Commit and push.
Task 5.3: Garden Operation#
Files:
- Create:
src/operations/garden.ts - Create:
src/commands/garden.ts - Tests:
test/garden-operation.test.ts - Update logs
Steps:
- Build prompt from
prompts/operations/garden.md. - Include repo root and
.almanac/path as runtime text. - Construct
AgentRunSpecwith metadata{ operation: "garden", targetKind: "wiki" }. - Route through process manager.
- Default background.
- Commit and push.
Phase 6: CLI Surface#
Task 6.1: Register New Commands And Flags#
Files:
- Modify:
src/cli/register-wiki-lifecycle-commands.ts - Modify:
src/cli/register-commands.ts - Create:
src/commands/jobs.ts - Tests: CLI command tests
- Update logs
Commands:
almanac init [--using <provider[/model]>] [--background] [--json] [--force] [--yes]
almanac capture [session-file...] [--app <app>] [--session <id>] [--since <duration-or-date>] [--limit <n>] [--all] [--all-apps] [--using <provider[/model]>] [--foreground] [--json] [--yes]
almanac ingest <file-or-folder> [--using <provider[/model]>] [--foreground] [--json] [--yes]
almanac garden [--using <provider[/model]>] [--foreground] [--json] [--yes]
almanac jobs [--json]
almanac jobs show <run-id> [--json]
almanac jobs attach <run-id>
almanac jobs logs <run-id>
almanac jobs cancel <run-id>Steps:
- Implement shared
--usingparser. - Replace
--agent/--modelin public docs; keep aliases only if needed during migration. - Enforce
--jsoncannot combine with--foreground. - Ensure command defaults:
init: foregroundcapture: backgroundingest: backgroundgarden: background
- Commit and push.
Task 6.2: Jobs Commands#
Files:
- Create/modify:
src/commands/jobs.ts - Tests:
test/jobs-command.test.ts - Update logs
Steps:
jobslists per-wiki runs from.almanac/runs/.jobs showprints one run record.jobs logsprints JSONL or human-readable log.jobs attachtails the event log.jobs cancelinterrupts/kills if possible and marks record.- Commit and push.
Phase 7: Gitignore And Wiki Init#
Task 7.1: Ensure Generated Ignore Rules#
Files:
- Modify: init/wiki setup code
- Tests: init helper tests
- Update logs
Rules:
.almanac/index.db
.almanac/runs/Steps:
- Ensure new wikis ignore runs and index.
- Do not add
.almanac/logs/. - Add tests for generated ignore behavior.
- Commit and push.
Phase 8: Remove Old Architecture#
Task 8.1: Delete Or Retire Old Capture/Bootstrap Pipeline#
Files:
- Remove/replace old hardcoded reviewer code in
src/commands/capture.ts - Remove/replace old
src/commands/bootstrap.tsusage - Remove old prompt names once tests are migrated
- Update tests
- Update logs and decision log
Steps:
- Delete old writer/reviewer-specific capture flow.
- Replace bootstrap path with Build operation.
- Preserve command compatibility only where explicitly chosen.
- Remove stale tests that assert old architecture details.
- Commit and push.
Phase 9: Full Verification And Review#
Task 9.1: Full Test Pass#
Files:
- Any final fixes
- Update logs
Steps:
- Run
npm test. - Run
npm run lint. - Fix failures.
- Commit and push.
Task 9.2: Review Agent#
Steps:
- Spawn a review agent with this scope:
- read
2026-05-10-harness-process-architecture.md - read this implementation plan
- inspect final diff against
main - look for architecture drift, missing tests, stale old pipeline pieces, prompt over-abstraction, jobs/logs inconsistency
- read
- Apply must-fix findings.
- Commit and push.
Task 9.3: Final Branch State#
Steps:
- Ensure branch is pushed.
- Ensure implementation and decision logs are current.
- Summarize:
- commits
- tests
- remaining risks
- follow-up tasks