Local control plane for agentic project development loops
Project description
Project Loop Harness
Project Loop Harness is a local control plane for coding agents.
It is not just an Agent Skill. The core product is pcl, a small local CLI/runtime that gives Codex, Claude Code, and similar agents a guarded project-scoped loop: durable state in SQLite, append-only audit events in JSONL, generated prompts and evidence, strict validation, human-readable reports, and a deterministic dashboard.
Quick Start
Install the published pcl CLI/runtime from PyPI with pipx:
pipx install project-loop-harness
pcl --version
pcl --help
Use python -m pip install project-loop-harness when installing inside a
project-specific virtual environment or CI job instead of exposing the command
globally.
For unreleased changes, install from a pinned GitHub tag or commit:
pipx install "git+https://github.com/mocchalera/project-loop-harness.git@<commit-or-tag>"
Initialize a target project:
cd target-project
pcl init --dry-run --json
pcl init
pcl doctor
pcl validate --strict
pcl render --json
Check whether a newer PyPI release is available:
pcl update check
pcl update command
pcl update check is explicit and advisory. It uses PyPI project metadata, keeps
a short local cache, performs no telemetry collection, and never upgrades the
environment by itself. Use pcl doctor --check-updates when you want the same
advisory warning alongside normal harness health checks. Set
PCL_NO_VERSION_CHECK=1 to disable version checks.
Then ask your coding agent to read AGENTS.md, CLAUDE.md if present, and
pcl.yaml, run pcl next --json, and follow the next safe harness action.
Mental Model
Goal -> Harness -> Workflow -> Agent Jobs -> Evidence -> Verification -> State -> Dashboard -> Stop/Retry/Escalate
The important separation is:
Skill = instructions for agents
pcl CLI = runtime that mutates state, validates, renders, and routes work
project.db = current normalized loop memory
events.jsonl = append-only audit log
dashboard.html = generated human-readable view, not agent context
Plugin = Codex distribution wrapper
MCP = optional read/local-render bridge
Agents should never edit .project-loop/project.db or read, parse, or edit generated dashboard HTML as project state. State changes go through pcl commands or internal service functions, and every state mutation appends an event. For machine context, use pcl JSON commands, reports, evidence paths, or .project-loop/dashboard/dashboard-data.json.
Repository Layout
project-loop-harness/
|- src/pcl/ # Python CLI/runtime
|- skills/project-control-loop/ # Standalone Agent Skill template
|- plugins/codex-project-loop/ # Codex plugin packaging scaffold and inventory
|- docs/ # Architecture and operational docs
|- agent-tasks/ # Numbered implementation tasks
|- examples/ # Example project configs
`- tests/ # CLI/runtime tests
Local Development
python -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[dev]'
pytest
pcl --help
Distribution Smoke Test
Before releasing a new version or handing the runtime to another project, verify a wheel install rather than only editable install:
python -m pip wheel . --no-deps --no-build-isolation -w /tmp/pcl-wheelhouse
python -m venv /tmp/pcl-wheel-venv
/tmp/pcl-wheel-venv/bin/python -m pip install --no-deps /tmp/pcl-wheelhouse/project_loop_harness-*.whl
/tmp/pcl-wheel-venv/bin/pcl --help
/tmp/pcl-wheel-venv/bin/pcl-mcp --help
The automated version is covered by:
pytest tests/test_distribution.py
Adoption Guide
For practical rollout into another repository, use
docs/adoption-guide.md. It covers target-project
setup, optional Git and local wheel handoff paths, what pcl init adds to a
target project, which files to commit, and starter prompts for the first agent
session.
Golden Path
This path runs a complete feature-coverage loop in a temporary project:
rm -rf /tmp/pcl-demo
mkdir -p /tmp/pcl-demo
pcl init --target /tmp/pcl-demo --dry-run --json
pcl init --target /tmp/pcl-demo
pcl doctor --root /tmp/pcl-demo
pcl goal create --root /tmp/pcl-demo --title "Reach basic feature coverage"
pcl loop run --root /tmp/pcl-demo feature_coverage --goal G-0001
pcl next --root /tmp/pcl-demo --json
pcl jobs read --root /tmp/pcl-demo J-0001
pcl jobs complete --root /tmp/pcl-demo J-0001 --summary "Mapped project surfaces"
pcl jobs complete --root /tmp/pcl-demo J-0002 --summary "Wrote user stories"
pcl jobs complete --root /tmp/pcl-demo J-0003 --summary "Designed test cases"
pcl next --root /tmp/pcl-demo --explain
pcl verification record --root /tmp/pcl-demo --run WR-0001 --result approved --reason "Reviewed generated coverage"
pcl loop complete --root /tmp/pcl-demo WR-0001 --summary "Feature coverage complete"
pcl goal close --root /tmp/pcl-demo G-0001 --summary "Coverage goal done" --verification V-0001
pcl validate --root /tmp/pcl-demo --strict
pcl report goal --root /tmp/pcl-demo G-0001
pcl report run --root /tmp/pcl-demo WR-0001
pcl feature list --root /tmp/pcl-demo --json
pcl render --root /tmp/pcl-demo
Humans can open /tmp/pcl-demo/.project-loop/dashboard/dashboard.html after rendering.
See docs/golden-path.md for the same path with expected checkpoints and a human-decision branch.
For approved workflows that pass the executor preflight, the guarded automatic path is:
pcl workflow verify --root /tmp/pcl-demo --template executor_smoke
pcl workflow sandbox --root /tmp/pcl-demo --template executor_smoke --json
pcl loop execute --root /tmp/pcl-demo executor_smoke --json
Failed or interrupted executor runs are recovered explicitly:
pcl loop execute workflow_id --retry WR-0001
pcl loop execute workflow_id --resume WR-0001
Agent steps are not launched unless explicitly enabled:
pcl loop execute workflow_id --agent-adapter generic_shell --allow-agent-exec
Context Packs
Use context packs to hand focused, budget-aware loop context to another agent without making generated dashboard HTML a machine context source:
pcl context pack --job J-0001
pcl context pack --job J-0001 --role verifier --max-tokens 12000 --json
pcl context pack --task T-0001 --json
The JSON contract is context-pack/v1. It includes included/omitted section
metadata, role profile selection, source commands, source paths, and the
generated Markdown package. Job packs include lease fields and rubric-aware
verification columns for rubric/v1; task packs include dependencies,
dependents, linked goal/feature/defect context, sibling tasks, and recent
events.
See docs/context-pack.md for the contract shape and
boundaries.
Guided Next Actions
pcl next is the loop router. The JSON output keeps the original fields and adds stable guidance fields:
{
"type": "continue_workflow",
"command": "pcl jobs read J-0001",
"reason": "A workflow run is already active and has queued or running jobs.",
"target": {"id": "WR-0001"},
"priority": 40,
"blocking": false,
"requires_human": false,
"safe_to_run": true,
"run_policy": "agent_safe",
"human_guidance": "An agent or automation may run this command in the current project context.",
"expected_after": "The agent job prompt is reviewed and the job can be executed or completed."
}
Use:
pcl next --json
pcl next --explain
pcl next --strict --json
Priority order is fixed:
- strict validation failure
- open escalation
- open decision
needs_humanverification requiring escalation- unfinished executor resume routing
- expired job lease reaping
- active workflow lifecycle
- executor retry routing
- open defect lifecycle
- workflow proposal review
- checkpoint review after several done features
- task backlog item under an open goal
- open goal continuation
- uncovered feature coverage
- create goal
Task routing only considers tasks linked to an open or active goal through
related_goal_id. Unlinked tasks stay visible in backlog surfaces, but pcl next intentionally does not route them in v1.
Agent Registry And Leases
Register local agents before leasing jobs:
pcl agent register --name codex-worker --role implementer --adapter codex_exec --max-concurrency 1
pcl agent list --json
pcl jobs assign J-0001 --agent A-0001
pcl jobs lease J-0001 --agent A-0001 --ttl-seconds 1800 --json
pcl jobs heartbeat J-0001 --json
pcl jobs release J-0001 --reason "Pausing for handoff"
Lease expiry is lazy. No daemon or timer mutates job state. When pcl next
reports reap_expired_leases, run:
pcl jobs reap --json
loop.lease_ttl_seconds defaults to 1800. loop.max_lease_attempts defaults
to 2, meaning the first expired lease is requeued and the second expired lease
blocks the job and opens a high-severity escalation for human review.
Checkpoint Reviews
Dogfooding showed that Project Loop is effective at small verified improvements, but large UX goals still need periodic human prioritization. Use checkpoint reviews to pause after several done features, organize commit/package boundaries, refresh UX or interaction checklists, and choose the next feature by product impact:
pcl checkpoint status --json
pcl checkpoint record \
--review-type integration \
--summary "Reviewed commit boundary, UX checklist, and next priority" \
--evidence "Reviewed validation output, git diff, UX checklist, and next feature priority"
When five features are marked done after the latest checkpoint, pcl next
returns checkpoint_review before recommending another feature-coverage run.
Human Decision Flow
When verification needs human judgment, keep ambiguity and the decision as durable state:
pcl verification record --root /tmp/pcl-demo --run WR-0001 --result needs_human --reason "Product decision required"
pcl next --root /tmp/pcl-demo --json
pcl escalation open --root /tmp/pcl-demo --run WR-0001 --severity high --question "What should ship?" --recommendation "Choose the safest reversible path"
pcl decision open --root /tmp/pcl-demo --escalation ESC-0001 --question "Which path should we take?" --recommendation "Choose the safest reversible path"
pcl decision resolve --root /tmp/pcl-demo DEC-0001 --selected-option "Ship locally first" --reason "Risk stays local"
pcl escalation resolve --root /tmp/pcl-demo ESC-0001 --decision DEC-0001 --summary "Human decision recorded"
Escalations and decisions are linked through decisions.blocks_json and event payloads. Dashboard rows and reports show linked_escalation_ids and linked_decision_ids.
Reports And Dashboard
Generated artifacts are review surfaces, not sources of truth:
pcl report goal --root /tmp/pcl-demo G-0001
pcl report run --root /tmp/pcl-demo WR-0001
pcl report feature --root /tmp/pcl-demo F-0001
pcl report defect --root /tmp/pcl-demo D-0001
pcl report validation --root /tmp/pcl-demo --strict
pcl render --root /tmp/pcl-demo
Reports are written to .project-loop/reports/. The dashboard writes:
.project-loop/dashboard/dashboard-data.json
.project-loop/dashboard/dashboard.html
Run pcl validate before rendering whenever possible. pcl render already performs normal validation and refuses to render on errors.
Agents should use .project-loop/dashboard/dashboard-data.json or pcl JSON commands for rendered machine context; dashboard.html is human-only.
Use pcl render --locale ja to render Japanese dashboard chrome. Without the
flag, pcl render reads dashboard.locale from pcl.yaml and then falls back
to English. The locale affects only dashboard.html; dashboard-data.json
keys and values stay English for agents and integrations.
If validation fails or generated artifacts look stale, use docs/recovery-playbook.md before continuing normal work.
Example Projects
Seed configs live under examples/. Copy one to a scratch directory, run pcl init --target ..., then follow the golden path without committing generated .project-loop/ state back into the example.
Current Runtime Surface
The current local runtime supports:
pcl init, inspect-firstpcl init --dry-run,doctor,validate,migrate, migration status,render;- feature creation, inspection, and evidence-backed status changes;
- user story and test case lifecycle commands for behavior-facing TDD/BDD loops;
- task/backlog CRUD, reasoned status changes, and guarded dependency links;
- workflow run creation from static templates;
- agent job prompts, filtered inspection, adapter commands, completion/failure/cancellation;
- local agent registry plus explicit job assignment, lease, heartbeat, release, and reap commands;
- documented agent adapter command contract;
- hardened Codex CLI adapter command template;
- hardened Claude Code manual adapter instructions;
- generic shell adapter command template;
- read-only context packs for focused agent handoff;
- validated agent output ingestion as evidence;
- job-centric evidence linkage for ingested agent output;
- verification recording;
- structured
rubric/v1verification metadata with inline/file recording and read-only inspection; - workflow run, goal, defect, escalation, and decision lifecycle commands;
- escalation/decision linkage;
- checkpoint review commands for commit/package, UX checklist, and next-priority pauses;
- task-aware
pcl nextrouting for goal-linked backlog items with satisfied dependencies; - strict validation invariants and audit-log integrity checks;
- evidence-backed Markdown reports;
- deterministic dashboard data and HTML with JSON artifact paths, a versioned data contract, evidence navigation, and risk/blocker summary;
- consolidated
human_decisionsdashboard data plus localized English/Japanese dashboard HTML chrome; - guided
pcl nextactions with uncovered-feature routing; - complete CSV export for reviewable loop state;
- optional local stdio MCP server;
- Codex plugin packaging scaffold with package inventory and reusable GitHub Action for local validation;
- workflow proposal mode, guarded human approval, static verifier checks, limited sandbox planning/execution, guarded automatic workflow execution with explicit retry/resume, and a bundled
executor_smokeworkflow for dogfooding the executor.
Implementation Task Order
Give tasks to coding agents in numeric order:
agent-tasks/0001-hardening-cli.md
...
agent-tasks/0017-next-action-guided-loop.md
agent-tasks/0018-readme-golden-path.md
agent-tasks/0019-recovery-playbook.md
agent-tasks/0020-example-project-refresh.md
agent-tasks/0021-agent-adapter-contract.md
agent-tasks/0022-agent-output-validation.md
agent-tasks/0023-codex-exec-adapter-hardening.md
agent-tasks/0024-claude-manual-adapter-hardening.md
agent-tasks/0025-generic-shell-adapter.md
agent-tasks/0026-agent-job-evidence-ingestion.md
agent-tasks/0027-dashboard-data-contract.md
agent-tasks/0028-dashboard-evidence-navigation.md
agent-tasks/0029-dashboard-risk-and-blockers.md
agent-tasks/0030-distribution-readiness.md
agent-tasks/0031-workflow-proposal-mode.md
agent-tasks/0032-workflow-proposal-review.md
agent-tasks/0033-workflow-verifier.md
agent-tasks/0034-limited-execution-sandbox.md
agent-tasks/0035-automatic-workflow-executor.md
agent-tasks/0036-executor-dogfood-workflow.md
agent-tasks/0037-executor-retry-resume.md
...
agent-tasks/0062-task-backlog-entity.md
agent-tasks/0063-structured-verification-rubric.md
agent-tasks/0064-task-loop-integration.md
agent-tasks/0065-dashboard-human-decisions.md
agent-tasks/0066-agent-registry-lease.md
Do not skip directly to MCP, plugin distribution, hosted services, or dynamic workflow generation before the CLI/runtime and project state layer are solid.
Non-Goals For The First Production Milestone
- No cloud backend.
- No hosted dashboard.
- No production database access.
- No autonomous destructive operations.
- No automatic external notifications.
- No fully dynamic workflow generation before static workflow templates are stable.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file project_loop_harness-0.1.8.tar.gz.
File metadata
- Download URL: project_loop_harness-0.1.8.tar.gz
- Upload date:
- Size: 194.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6be8f7df2d8e29b62607a9aefad910d002a3dd7aad79b75e3a891ca5485b428
|
|
| MD5 |
4d7803d8b8ffcce1a010c9322765877b
|
|
| BLAKE2b-256 |
aab6c19c0cef88c3eebe575f9216183f260205415dd48745e1d293980e5d0d8b
|
Provenance
The following attestation bundles were made for project_loop_harness-0.1.8.tar.gz:
Publisher:
publish-pypi.yml on mocchalera/project-loop-harness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
project_loop_harness-0.1.8.tar.gz -
Subject digest:
b6be8f7df2d8e29b62607a9aefad910d002a3dd7aad79b75e3a891ca5485b428 - Sigstore transparency entry: 2052940187
- Sigstore integration time:
-
Permalink:
mocchalera/project-loop-harness@041085a5cf7a27a7ae21affe47ddda90d73006fd -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/mocchalera
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@041085a5cf7a27a7ae21affe47ddda90d73006fd -
Trigger Event:
release
-
Statement type:
File details
Details for the file project_loop_harness-0.1.8-py3-none-any.whl.
File metadata
- Download URL: project_loop_harness-0.1.8-py3-none-any.whl
- Upload date:
- Size: 155.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39fe6ed06fa10416b344349d680ab02e8357d920bb2af4ecf7ab3f4aa3f8d10e
|
|
| MD5 |
be5055e0738c2a3ad7edc8bda1d7909b
|
|
| BLAKE2b-256 |
7ba5c960a633f6e5a060e38e1a432b4c229e4c6b387a25456d714f289d750b10
|
Provenance
The following attestation bundles were made for project_loop_harness-0.1.8-py3-none-any.whl:
Publisher:
publish-pypi.yml on mocchalera/project-loop-harness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
project_loop_harness-0.1.8-py3-none-any.whl -
Subject digest:
39fe6ed06fa10416b344349d680ab02e8357d920bb2af4ecf7ab3f4aa3f8d10e - Sigstore transparency entry: 2052940658
- Sigstore integration time:
-
Permalink:
mocchalera/project-loop-harness@041085a5cf7a27a7ae21affe47ddda90d73006fd -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/mocchalera
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@041085a5cf7a27a7ae21affe47ddda90d73006fd -
Trigger Event:
release
-
Statement type: