Repository navigation
v1.0.0
[1.0.0]
This is a structural refactor of dotcontext ahead of 1.0.0. It replaces the monolithic src/services / src/workflow layout with a hexagonal harness core and thin adapters for CLI, MCP, and host hooks.
New: Claude Code hooks, Codex CLI hooks, and Pi.dev
Dotcontext is no longer MCP-only. 1.0.0 introduces first-class support for three major agent hosts — the same harness runtime, wired into each tool's native lifecycle:
| Host | How it connects | What you get |
|---|---|---|
| Claude Code | Shell hooks via settings.json |
Context bootstrap on session start, durable traces after Write/Edit/Bash, PREVC workflow reminders on stop |
| Codex CLI | Shell hooks via hooks.json or inline TOML |
Same harness actions as Claude Code; JSON or TOML install formats |
| Pi.dev | In-process npm extension (@dotcontext/pi) |
Lifecycle hooks without shell dispatch — bootstrap, tracing, and workflow guidance inside Pi |
One runtime, three surfaces. Hooks and Pi call the same harness actions as MCP (context check, harness appendTrace, workflow-guide). No duplicated PREVC logic per host.
Quick start:
# Install hooks (interactive — detects installed hosts)
npx -y @dotcontext/cli@latest hook install
# Or target a host explicitly
npx -y @dotcontext/cli@latest hook install claude-code
npx -y @dotcontext/cli@latest hook install codex --local
npx -y @dotcontext/cli@latest hook install pi --local
# MCP for Pi (optional, alongside the extension)
npx -y @dotcontext/mcp install piInstall docs: Using with Hooks · Using with Pi
The runtime now follows one rule:
cli ──► harness ◄── mcp
▲
└── integrations (Claude Code · Codex CLI · Pi)
Harness owns workflow, execution state, context scaffolding, sensors, and domain rules.
Adapters own transport, installation, and host-specific rendering — they call into the harness; they do not duplicate PREVC logic.
Why
On main, runtime code lived under src/services with workflow, harness, MCP gateway, and semantic tooling mixed together. That made it hard to:
- reuse the runtime outside MCP/CLI
- test domain rules without pulling in transport code
- add new host surfaces (hooks, Pi) without copying workflow behavior
This refactor consolidates reusable logic under src/harness, moves operator and protocol code to src/cli / src/mcp / src/integrations, and enforces the split with architecture boundary tests.
Removed — BREAKING CHANGES
- Legacy
.contextlayout auto-migration removed. Pre-1.0 checkouts using
.context/harness/or.context/workflow/are no longer migrated on access.
The runtime reads only the canonical.context/config/(authored config) and
.context/runtime/(generated state) layout. Migrate old folders manually before
upgrading. (Removedsrc/shared/fs/legacyLayoutMigration.tsand all call sites.) - Legacy workflow
status.yamlmigrator removed..context/workflow/status.yaml
is no longer read or migrated into canonicalruntime/workflows/prevc.json.
(Removedsrc/harness/domain/workflow/legacy/.) - Legacy harness-session binding fallback removed. The old
.context/workflow/harness-session.jsonbinding is no longer read, rewritten,
or archived. Bindings live only inruntime/workflows/prevc.json. - Legacy tool-surface import/export targets removed. Imports and exports now
cover only current-format surfaces. Dropped:.cursorrulesand.cursor/rules/*.md;
older.claude/*.memoryand.claude/settings.json;.github/copilot/*and
.github/.copilot/*;.windsurfrules;.clinerules;.continuerulesand
.continue/config.json;.codex/instructions.md; the Antigravity.agent/*
layout (use.agents/*). - Legacy Cursor
.cursorrulesexport preset removed. Exporting to Cursor writes
.cursor/rules(.mdc) only — the flat.cursorrulesfile is no longer emitted. - Deprecated re-export shims removed:
src/mcp/mcpServer.ts,
src/mcp/mcpInstallService.ts,src/mcp/actionLogger.ts,src/mcp/gatewayTools.ts,
src/cli/services/stateDetector.ts,src/cli/services/state/, and
…/scaffolding/generators/shared/scaffoldStructures.ts. Import from the canonical
modules instead (src/mcp/server,src/mcp/logging,src/mcp/gateway,
src/harness/application/context/stateDetector,…/generators/shared/structures). - Legacy
enterpriseproject scale removed. Uselarge;
getScaleFromName('enterprise')no longer maps toLARGE. - Deprecated role helpers removed:
SPECIALIST_TO_ROLE,getRoleForSpecialist,
andgetSpecialistsForRole(src/harness/domain/workflow/roles.ts). Use the
agent-based orchestration model (ROLE_TO_AGENTS). PrevcStatusManagerconstructor signature changed from
new PrevcStatusManager(contextPath, workflowState)to
new PrevcStatusManager(workflowState)— the legacycontextPathargument
(only used to locate the oldstatus.yaml) is gone.- Stopped gitignoring legacy runtime paths.
.context/harness/**and
.context/workflow/**are no longer added to the generated.gitignore.
Changed
- MCP install: Gemini — merged
gemini-cliinto a singlegeminiregistry id;gemini-cliremains a one-release alias for install commands. - MCP detection paths — Windsurf and Amazon Q detection now checks alternate config directories.
- Documentation — updated architecture, installation, and contributor docs for integrations, hooks, and Pi; MCP client count is now 17.
- Reorganized the on-disk
.contextdata layout into authored config vs generated runtime state. The single.context/harness/folder (which mixed editable config with machine-generated state) and the separate.context/workflow/folder are replaced by:.context/config/— authored, version-controlled config:policy.json,sensors.json(moved from.context/harness/).context/runtime/— all generated state, gitignored as one block:runtime/sessions/<id>/— one folder per session co-locatingsession.json,trace.jsonl, andartifacts/(previously flat underharness/sessions,harness/traces,harness/artifacts)runtime/workflows/— PREVC state (prevc.json), plan tracking (plans.json,plan-tracking/), andcollaboration-sessions.json(previously split acrossharness/workflowsandworkflow/)runtime/contracts/— task and handoff contracts (washarness/contracts)runtime/evaluations/{replays,datasets}/— replay and failure-dataset output (washarness/replays,harness/datasets)
- All paths now resolve through a single source of truth (
resolveRuntimeLayoutinsrc/shared/fs/pathHelpers.ts) instead of hand-built'harness'/'workflow'path segments. - The
src/harnesscode module is unchanged — only the on-disk data folder moved. This release does not migrate pre-1.0 layouts (see Removed, above); move.context/harness/and.context/workflow/to.context/config/and.context/runtime/manually if upgrading an old checkout. - A layering test forbids
src/harness/domaincode from importing the application/adapters layers, and a boundary test forbidssrc/harnessfrom importing thecli/mcpsurfaces, keeping the runtime decoupled and reusable.
Added
-
Hook install CLI —
dotcontext hook install,hook dispatch, andhook uninstallfor Claude Code, Codex CLI, and Pi, with--local,--global,--dry-run, and Codex-specific--format json|toml. -
Host hook runtime — typed event mappers and response adapters for Claude Code, Codex CLI, and Pi (
session_start,PostToolUse,Stop/agent_end), wired through a shared harness hook adapter. -
Adapter-neutral workflow guidance —
workflow-guidenow exposes PREVC next steps, relevant skills, and portable gate decision hints through the harness, MCP, hooks/Pi renderers, anddotcontext admin workflow guide. -
@dotcontext/integrationspackage — publishable host hook adapters and mappers (./claude-code,./codex,./pi-devsubpaths). -
@dotcontext/pipackage — Pi npm extension for in-process lifecycle hooks (bootstrap, tracing, workflow reminders). -
MCP install: Pi —
npx @dotcontext/mcp install piwrites.mcp.json(local) or~/.config/mcp/mcp.json(global). -
Built-in skill catalog — single source of truth for built-in skill slugs, PREVC phase mapping, and generated
dotcontext-workflow-{p,r,e,v,c}meta skills. -
Built-in
tests-passingsensor (src/services/harness/sensors/testsPassing.ts)- Default
kind: 'jest'runsnpm test -- --runInBand --json, parses jest's JSON output, and reports{ numPassedTests, numFailedTests, numTotalTestSuites, failures: [{ name, message }] }; passes iff exit 0 andnumFailedTests === 0 kind: 'exit-code'mode for non-jest runners passes iff the configuredtestCommandargv exits 0- Configurable
testCommand(string[]) andtimeoutMs(default 300s); spawn(..., { shell: false }) with explicit argv — no shell interpolation - Registered by default in
HarnessSessionFacade.registerDefaultSensors
- Default
-
Built-in
typecheck-cleansensor (src/services/harness/sensors/typecheckClean.ts)- Default command
npx tsc --noEmit; passes iff exit 0 - On failure, captures the last
tailLines(default 50) of combined stdout/stderr onoutput.tailplus theoutput.exitCode - Configurable
command(string[]),timeoutMs(default 120s), andtailLines - Registered by default in
HarnessSessionFacade.registerDefaultSensors
- Default command
-
Plan scaffolding auto-detects per-phase requirements (
src/workflow/plans/scaffoldSuggestions.ts)suggestPhaseRequirements(repoPath)probes the working tree and proposes phase-scopedrequired_sensorsso plan authors do not need to know the sensor catalog up front- Detection rules:
locales/*.jsonori18n/*.json→i18n-coveragein E; realscripts.testinpackage.json→tests-passingin V;tsconfig.json→typecheck-cleanin V;.eslintrc*/eslint.config.*/eslintConfiginpackage.json→lintin V mergeSuggestionsIntoPhasesonly fillsrequired_sensors/required_artifactsfor phases that did not already declare them — never overwrites an explicit author choice; existing scaffolds keep working unchanged- Wired into
PlanGeneratorviarenderPlanTemplatesocontext({ action: "scaffoldPlan", ... })emits the suggestions in the YAML frontmatter - Documented on the documentation site under Sensors and Authoring plans guides
-
RequiredArtifactSpec.fromFilesystem: trueforglobandfile-countkinds- When set,
evaluateTaskCompletionalso scans the project working tree (relative torepoPath) and unions filesystem hits with recorded session artifacts, eliminating the false-blocked case where a file exists in the repo butrecordArtifactwas never called - Hard-coded ignore list (
node_modules,.git,dist), 5s scan timeout, refusal to escaperepoPath; I/O failures and timeouts surface asblockingFindingentries (filesystem scan failed for <pattern>: ...) instead of crashing - Recorded artifacts and filesystem hits deduplicated by path so a file never counts twice
- Documented on the documentation site (Authoring plans guide)
- When set,
-
Built-in
i18n-coveragesensor (src/services/harness/sensors/i18nCoverage.ts)- Compares translation keys between a configurable base locale (
baseLocale, default'en') and every other<locale>.jsoninlocalesDir(default'locales'); supports flat (format: 'json') and nested (format: 'json-nested') key extraction - Persists structured output
{ coverage: { locale: ratio }, missingKeys: { locale: string[] } }on thesensor.runtrace; passes only when every non-base locale has zero missing keys - Registered by default in every harness session via
HarnessSessionFacade.registerDefaultSensors; only executes when a plan declaresrequired_sensors: [i18n-coverage] - Clear, non-crashing failure modes for missing
localesDir, malformed JSON (with file name), and missing base locale - Documented on the documentation site (Sensors guide)
- Compares translation keys between a configurable base locale (
-
Structured artifact requirements (
RequiredArtifactSpec)HarnessTaskContract.requiredArtifactsaccepts(string | RequiredArtifactSpec)[]; strings remain backwards-compatible (interpreted as{ kind: 'name', name })- Four spec kinds:
name,path,glob(withminMatches, default1), andfile-count(min) evaluateTaskCompletionmatches glob specs viaminimatchagainst recorded session artifacts;missingArtifactsreports human-readable descriptions likeglob(locales/**/*.json) min=5 (got 2)- Plan frontmatter
required_artifactsaccepts the same shapes (zod discriminated union); specs propagate throughDerivedPlanTaskContractBuilderwithout stringification - MCP
defineTask/createTaskschemas widened to accept structured specs alongside strings - Filesystem-glob (
fromFilesystem: true) is intentionally out of scope; matching is restricted to recorded session artifacts - Documented on the documentation site (Authoring plans guide)
-
checkGatesvalidatesnextPhaseagainstPREVC_PHASE_ORDERandstatus.phases- Throws when
nextPhaseis not a valid PREVC phase, or is missing fromstatus.phases(in addition to the existingskippedguard)
- Throws when
-
Plan frontmatter declares execution evidence per phase
phases[].required_sensorsandphases[].required_artifactsin plan scaffold frontmatter populate the derivedHarnessTaskContract's required fieldsDerivedPlanTaskContractBuildernow honors declared requirements and falls back to conservative defaults when absent (E->['tests'],V->['tests', 'lint']; P/R/C have no default)plan({ action: "link", ... })hard-fails when a plan's Execution phase has norequired_sensors, preventing silent "execution verified" claims at the source- New builder tests under
src/services/workflow/derivedPlanTaskContractBuilder.test.tsand an e2e rejection test undersrc/services/workflow/__tests__/falseCompletion.e2e.test.ts - Documented on the documentation site (Authoring plans guide)
-
execution_evidencephase gate wiresevaluateTaskCompletionintoworkflow-advanceGateCheckResult.gatesnow includesexecution_evidencewithmissingSensors,missingArtifacts, andblockingFindings- E → V transitions fail closed with
WorkflowGateError(gate='execution_evidence')when the active task contract's required sensors/artifacts are not satisfied - End-to-end coverage for "LLM claims completion without evidence" under
src/services/workflow/__tests__/falseCompletion.e2e.test.ts
Changed
autonomous_modeno longer suppresses execution evidence- Autonomous mode now suppresses only the
plan_requiredandapproval_requiredpolicy gates execution_evidenceremains active under autonomous mode; useforce: trueonworkflow-advancefor explicit overrides
- Autonomous mode now suppresses only the
- Silent plan-markdown sync failures now surface as
WorkflowSyncErrororchestrator.completePhaseno longer swallowssyncPlanMarkdownerrors after a phase transition; the error is logged with phase context and propagated so tracking/status/markdown divergence cannot hide
Added
-
Structured plan metadata now supports canonical phase steps and deliverables
- Plan frontmatter can now persist
phases[].summary,phases[].deliverables, andphases[].steps[].deliverables - Plan parsing now prefers canonical frontmatter metadata and falls back to markdown task tables or numbered lists only for legacy plans
- Plan frontmatter can now persist
-
Workflow collaboration sessions are now durable across service and MCP calls
- Collaboration state is now persisted under
.context/workflow/collaboration-sessions.json - Fresh
WorkflowServiceinstances rehydrate active and concluded collaboration sessions from disk - Added dedicated store and tests covering persistence across manager and service recreation
- Collaboration state is now persisted under
-
Workflow architecture now has explicit runtime, migration, and guidance components
- Added dedicated status runtime, transition, execution-history, and legacy-migration services under
src/workflow/status/andsrc/workflow/legacy/ - Added workflow guidance helpers and services outside the PREVC runtime orchestrator
- Added plan execution/index projection helpers so plan document parsing and execution tracking are composed explicitly
- Added dedicated status runtime, transition, execution-history, and legacy-migration services under
Changed
-
Workflow-linked plans now bootstrap and rotate harness task contracts automatically
plan linkcreates a bootstrap task contract for the current PREVC phase when a workflow is activeworkflow-advancecompletes the previous active contract and derives the next phase contract from the linked plan- The harness remains the persistence and evaluation layer for task contracts while workflow owns the phase-driven rotation logic
-
PREVC workflow definitions now come from a shared canonical registry
- Phase, role, agent, skill, and documentation mappings now derive from a central PREVC model instead of being duplicated across workflow modules
- Document guidance now points at real files under
.context/docsinstead of dead placeholder paths
-
Workflow state management is now port-driven and facade-based
PrevcStatusManagernow depends on a workflow state port instead of importing harness persistence directly- Canonical status persistence, runtime mutation, legacy YAML migration, and execution history logic are now separated into smaller units
-
Plan execution tracking is now the canonical workflow-plan runtime state
plan-tracking/*.jsonnow drives linked plan progress, current phase, approval metadata, and step status- Markdown plans are now treated as documentation plus projection targets, not as the source of runtime execution truth
- Workflow plan index refresh is now projected from plan documents plus tracking state
-
Workflow orchestration guidance is now outside the runtime core
- Textual orchestration instructions, recommended actions, and handoff guidance moved out of the PREVC runtime orchestrator into dedicated guidance services
- Internal consumers now import workflow submodules directly more often, reducing pressure on the public workflow barrel
-
The workflow public barrel is narrower and more intentional
src/workflow/index.tsnow favors a stable surface over re-exporting broad internal implementation details- Internal services were rewired toward direct module imports where that avoided keeping internals public by accident
-
Gate evaluation now follows the same executable phase progression as workflow state
- Gate checks now use the next non-skipped PREVC phase instead of an independent hardcoded phase order
- Blocking hints were updated to current MCP/workflow commands
Fixed
-
Linked plan execution state no longer drifts from tracking data
getLinkedPlan()now reflects tracked phase and step execution state instead of synthetic markdown defaults- Progress calculation now uses planned document steps as the denominator when available, avoiding false
100%progress from partially tracked phases
-
Workflow collaboration no longer resets between calls
- Collaboration sessions now survive new service instances and MCP request boundaries instead of living only in an in-memory
Map
- Collaboration sessions now survive new service instances and MCP request boundaries instead of living only in an in-memory
-
Workflow document and gate guidance no longer point at stale behavior
- Agent and phase documentation links now resolve to actual repository docs
- Gate remediation messages now reference current
plan(...)andworkflow-manage(...)calls instead of removed legacy command names