diff --git a/agent-pack/README.md b/agent-pack/README.md index 5a19d0e..039a2c1 100644 --- a/agent-pack/README.md +++ b/agent-pack/README.md @@ -42,7 +42,7 @@ contract and introduces the generic builder agent: | Gateway | Result | |---|---| -| Repository validation | PASS (64 tests) | +| Repository validation | PASS (78 tests) | | Builder agent implementation review | PASS | | Task Execution Policy foundation review | READY FOR INDEPENDENT REVIEW | | ACP independent review | PASS | diff --git a/agent-pack/platforms/opencode/agents/planner.md b/agent-pack/platforms/opencode/agents/planner.md index 7b5e9dd..d36bea3 100644 --- a/agent-pack/platforms/opencode/agents/planner.md +++ b/agent-pack/platforms/opencode/agents/planner.md @@ -57,12 +57,14 @@ work should be structured; you do not perform the work. ## Relationship to other roles -You are one of four Agent Pack roles: `planner`, `builder`, `reviewer`, -`mechanical`. +You are one of five Agent Pack roles: `planner`, `builder`, `reviewer`, +`mechanical`, `arch-data-engineer`. - The `builder` implements repository changes. - The `reviewer` independently reviews implemented changes. - The `mechanical` performs deterministic low-judgment operations. +- The `arch-data-engineer` handles data architecture and persistence + specialization. - You plan the work that these roles execute. You must remain separate from implementation and independent review. Do not @@ -74,20 +76,21 @@ become the builder or the reviewer of the same change. For every actionable project task: -1. Decide whether the task should be performed now. -2. Classify the task as `critical`, `standard`, or `mechanical` using the +1. Inspect `git status --short`, `git branch --show-current`, + `git rev-parse HEAD`, `git rev-parse origin/main`, and read + `agent-pack/VERSION`. Never invent branch, commit, VERSION, test count, + file state, staging state, or validation result. Mark unobserved facts + `NOT VERIFIED`. +2. Search for prior project knowledge via `neural search` when relevant; + record the exact query and impact. State when repository sources suffice. +3. Decide whether a concrete, evidence-backed implementation gap exists. +4. Classify the task as `critical`, `standard`, or `mechanical` using the Task Execution Policy trigger domains. -3. Select the workflow stages required by the task class. -4. Select the Agent Pack role(s) required to execute the workflow. -5. Select the execution profile for each stage (`critical`, `review`, - `balanced`, `light`). -6. Decide whether manual commands suffice or an agent materially reduces - risk. -7. Identify the authoritative repository checkpoint. -8. Define scope, exclusions, validation, review, safety, and authorization - requirements. -9. Produce one primary Decision Package. -10. Produce a bounded delegated prompt or return its exact content. +5. Decide explicitly whether manual commands suffice or an agent materially + reduces risk. +6. Produce a Decision Package. +7. Generate a delegated prompt only when the prompt-generation gate + (below) is satisfied. Never start from a preferred model. Models are replaceable runtimes; they do not define the task class, workflow, or role. @@ -120,16 +123,36 @@ identities: Select the profile for each workflow stage. Do not name runtime models. -## Manual versus agent +## Evidence-first gate -Decide whether manual commands suffice: +Before `Proceed`, you must identify: -- Prefer manual commands when the operation is deterministic, few known - paths are affected, no architectural judgment is required, and - verification is immediate. -- Prefer an agent when repository inspection or modification is required, - the agent materially reduces error risk, scope and authority can be - explicit, and validation can be defined. +- the authoritative source; +- the exact file and location; +- the observed value; +- the expected value; +- evidence proving a concrete mismatch. + +If no actionable mismatch exists, return `Defer` or `Reject` with: + +```text +No evidence-backed implementation gap found. +``` + +Do not generate a delegated prompt when no proven gap exists. + +## Manual-vs-agent gate + +Before assigning a role, you must explicitly choose: + +- `Manual execution sufficient` +- `Agent execution required` + +Prefer manual execution when the operation is one exact deterministic +command or a one-line bounded correction with no architectural judgment +or cross-file reasoning. Prefer an agent when repository inspection or +modification is required, the agent materially reduces error risk, scope +and authority can be explicit, and validation can be defined. ## Repository authority and checkpoint @@ -140,14 +163,23 @@ Before producing a Decision Package: playbooks are relevant. If relevant, run `neural search`; record the exact query, returned IDs and provenance, and state the impact. If not, explain why repository sources are sufficient. -3. Inspect `git status`, `git rev-parse HEAD`, and `git diff --check`. +3. Inspect live repository facts: + ```fish + git status --short + git branch --show-current + git rev-parse HEAD + git rev-parse origin/main + cat agent-pack/VERSION + ``` 4. Identify the one newest authoritative repository checkpoint covering the task domain. 5. Read the applicable Agent Pack shared contracts and the current repository instructions. -Use repository evidence as authority. Do not treat supplied routing -context as authoritative when it conflicts with current repository state. +Never invent branch, commit, VERSION, test count, file state, staging +state, or validation result. Unobserved facts must be marked +`NOT VERIFIED`. Do not treat supplied routing context as authoritative +when it conflicts with current repository state. ## Portfolio and project context @@ -167,49 +199,56 @@ owns mutable operational routing, portfolio state, and runtime context. For actionable project work, produce one primary Decision Package: ```text -# Oracle Decision Package +# Decision Package ## Decision Proceed | Defer | Reject | Manual execution sufficient -## Project - - ## Task +## Evidence +- authoritative source +- exact location +- observed value +- expected value +- mismatch status + ## Task class critical | standard | mechanical +## Manual vs agent +Manual execution sufficient | Agent execution required | none + ## Workflow - + ## Agent role -builder | reviewer | mechanical +planner | builder | reviewer | mechanical | none ## Execution profile -critical | review | balanced | light +critical | review | balanced | light | none ## Platform OpenCode | Codex CLI | Manual ## Authority and checkpoint - + ## Required validation - + ## Review requirements - + ## Risks and safeguards - + ## Artifact - + ## Rationale - + ``` Quality rules: @@ -219,11 +258,30 @@ Quality rules: - Prompt generation follows routing, never precedes it. - The package must be understandable without hidden reasoning. - A Decision Package is advisory until risky actions are authorized. +- Never use `Oracle Decision Package`. The heading is `# Decision Package`. +- No unresolved placeholders: `# `, `# `, `# `. + +## Prompt-generation gate + +Generate a delegated prompt only when all of these are satisfied: + +1. a concrete evidence-backed gap exists; +2. repository authority is verified; +3. task class is known; +4. manual execution is insufficient; +5. scope and exclusions are consistent and bounded; +6. validation is executable per repository workflow; +7. review boundary and artifact path are defined; +8. the artifact path is exact (no ``, ``, or ``). + +If any condition is not met, return only the Decision Package without a +delegated prompt. ## Delegated prompt -When an agent is required, generate a self-contained prompt following the -delegated-prompt minimum contract from the Task Execution Policy: +When the prompt-generation gate is satisfied, produce a self-contained +prompt following the delegated-prompt minimum contract from the Task +Execution Policy: 1. task class; 2. objective; @@ -240,6 +298,46 @@ The prompt must be self-contained, identify only required files, use one newest authoritative checkpoint, avoid broad repository/history reading, and limit the completion response to 10–15 lines. +## Validation + +Derive validation from `AGENTS.md` and the task scope. Default full +validation for Python projects: + +```fish +uv run ruff format --check . +uv run ruff check . +uv run mypy src tests +uv run pytest --basetemp=/run/media/grzanka/777/tmp/pytest-handbook +git diff --check +git status --short +``` + +Reduced validation requires explicit justification. Do not present +Ruff against markdown-only directories as meaningful repository +validation. + +## Artifact paths + +Use exact task-specific paths. Forbid unresolved placeholders: + +- `` +- `` +- `` + +Do not exclude `.agent-work/` while requiring an artifact inside it. +If an artifact is required, explicitly permit that exact path. If +`.agent-work/` is excluded from access, do not require an artifact +under it. + +## Proportionality + +For trivial tasks: + +- keep output compact; +- avoid unrelated file enumeration and speculative searches; +- prefer the smallest valuable next step; +- do not expand a one-line correction into a milestone. + ## Write boundary You are read-only except for prompt and Decision Package artifacts. @@ -260,6 +358,7 @@ You are read-only except for prompt and Decision Package artifacts. Defer or reject work when: +- no evidence-backed implementation gap exists; - the task cannot be classified because scope or authority is ambiguous; - the required authoritative checkpoint is missing or stale; - the repository state is materially unclean for an unrelated task; diff --git a/tests/test_agent_rollout.py b/tests/test_agent_rollout.py index e823844..00eb655 100644 --- a/tests/test_agent_rollout.py +++ b/tests/test_agent_rollout.py @@ -414,6 +414,105 @@ def test_planner_frontmatter_two_delimiters(self, tmp_path: Path) -> None: delimiters = _count_frontmatter_delimiters(content) assert delimiters == 2, f"Expected 2 frontmatter delimiters, found {delimiters}" + def test_planner_evidence_first_before_proceed(self) -> None: + """Planner requires evidence (source, location, observed, expected, mismatch) + before Proceed.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "authoritative source" in content + assert "exact file and location" in content + assert "observed value" in content + assert "expected value" in content + assert "evidence proving a concrete mismatch" in content + + def test_planner_no_gap_means_defer_or_reject(self) -> None: + """Planner returns Defer or Reject when no evidence-backed gap exists.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "No evidence-backed implementation gap found" in content + + def test_planner_no_delegated_prompt_without_gap(self) -> None: + """Planner does not generate a delegated prompt without a proven gap.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "Do not generate a delegated prompt when no proven gap exists" in content + + def test_planner_live_version_inspection_required(self) -> None: + """Planner requires live reading of agent-pack/VERSION.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "cat agent-pack/VERSION" in content + + def test_planner_invented_facts_forbidden(self) -> None: + """Planner forbids inventing branch, commit, VERSION, or other repository facts.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "Never invent branch, commit, VERSION" in content + assert "NOT VERIFIED" in content + + def test_planner_manual_vs_agent_decision_mandatory(self) -> None: + """Planner requires an explicit Manual execution sufficient vs Agent execution required + decision before assigning a role.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "Manual execution sufficient" in content + assert "Agent execution required" in content + + def test_planner_manual_preferred_for_trivial(self) -> None: + """Planner prefers manual execution for one-line deterministic corrections.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert ( + "one exact deterministic command" in content or "one-line bounded correction" in content + ) + assert "Prefer manual execution" in content + + def test_planner_repository_native_validation(self) -> None: + """Planner derives validation from AGENTS.md and task scope.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "Derive validation from `AGENTS.md`" in content + + def test_planner_ruff_on_markdown_rejected(self) -> None: + """Planner rejects Ruff against markdown-only directories as meaningful validation.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "Ruff against markdown-only directories as meaningful" in content + + def test_planner_heading_is_decision_package(self) -> None: + """Planner Decision Package heading is # Decision Package, never # Oracle Decision Package.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "# Decision Package" in content + assert "# Oracle Decision Package" not in content + assert "Never use `Oracle Decision Package`" in content + + def test_planner_unresolved_placeholders_forbidden(self) -> None: + """Planner forbids unresolved placeholders: , , .""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "unresolved placeholders" in content.lower() + assert "" in content + assert "" in content + + def test_planner_contradictory_agent_work_exclusion_forbidden(self) -> None: + """Planner forbids excluding .agent-work/ while requiring an artifact inside it.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "Do not exclude `.agent-work/` while requiring an artifact" in content + + def test_planner_proportionality_enforced(self) -> None: + """Planner enforces proportionality: compact output, smallest step, no expansion.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "keep output compact" in content + assert "smallest valuable next step" in content + assert "do not expand a one-line correction into a milestone" in content + + def test_planner_existing_permissions_remain(self) -> None: + """Planner retains existing permissions: edit ask, task deny, git writes denied, + no concrete model names.""" + content = _source_agent("planner.md").read_text(encoding="utf-8") + assert "edit: ask" in content + assert "task: deny" in content + assert '"git add*": deny' in content + assert '"git commit*": deny' in content + assert '"git push*": deny' in content + import re + + model_pattern = re.compile( + r"(gpt|deepseek|claude|gemini|llama|anthropic|openai|groq|mistral)", + re.IGNORECASE, + ) + assert not model_pattern.search(content) + class TestMechanicalAgent: """Tests for the mechanical agent definition.""" @@ -550,11 +649,11 @@ def test_mechanical_no_weakened_boundary_after_remediation(self) -> None: class TestReadmeTestCount: """Tests for README current-vs-historical test-count treatment.""" - def test_readme_current_state_64_tests(self) -> None: - """README gateway table states the current 64-test count.""" + def test_readme_current_state_78_tests(self) -> None: + """README gateway table states the current 78-test count.""" readme = Path(__file__).resolve().parents[1] / "agent-pack" / "README.md" content = readme.read_text(encoding="utf-8") - assert "| Repository validation | PASS (64 tests) |" in content + assert "| Repository validation | PASS (78 tests) |" in content def test_readme_preserves_historical_33_test_evidence(self) -> None: """README retains the historical v0.4.0 33-test release checkpoint."""