8000 ROADMAP §4.6, §4.9, §4.10, §4.11: rendered plan views, host swap, context-window share, aladdin entry point by adeelahmad · Pull Request #15 · adeelahmad/aloop · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,24 @@ tag in lockstep. Tag releases as `vMAJOR.MINOR.PATCH`.
- **Usage accuracy is explicit** (ROADMAP §4.9, conformance 12). Each attempt's usage
carries `accuracy: exact` and names any class the host never reports (Codex has no cache
write) instead of a silent zero; stats.md shows it in the Metrics table.
- **`aladdin` entry point** (ROADMAP §4.11). `aladdin "<intent>"` records the Intent Contract
(plus the raw words) and says how to start the run; `aladdin status|resume|report` read the
harness files (sweep, the resume rule, NEXT.md, stats.md); `aladdin target|context|refs|…`
are the semantic queries; every aloop tool answers under the new name. A `/aladdin` skill
defers to `/aloop`; installs link `~/.local/bin/aladdin` and copy the skill. The stray
`bin/aloop-init.orig` left by the rename merge is gone.
- **Context-window share** (ROADMAP §4.10). stats.md divides the context peak by the new
`AGENTIC_CONTEXT_WINDOW` setting (`context.window` in `.aladdin/config.yaml`, default 200000):
hosts do not report the window, so the human states it instead of the harness guessing.
- **Host swap** (ROADMAP §4.9). `aloop host swap --to codex|opencode|claude` hands a sprint to
another host from portable state only: the sprint dir (handoff.json / plan-ready.md),
`.aladdin/config.yaml` and `.agentic/logs`. A missing piece or a live worker worktree blocks;
the target's capability gaps are named; SessionStart on the new host resumes the sprint under
the same resume rule and records the rotation. Test: `scripts/test/host-swap.test.py`.
- **The semantic plan as the execution source** (ROADMAP §4.6). With `tasks` in a story's
`targets.json`, `targets render` writes tasks.md, validate.md and plan.md as deterministic
views over it, and `targets check` (gate-stage2-complete) refuses a hand-edited view, so the
md files cannot fork from the plan. Test: `scripts/test/plan-render.test.py`.
- **Diff scope derived from change targets** (ROADMAP §4.6). When the supervisor gives no
`SCOPE_GLOBS` and the story has `targets.json`, gate-green-verify enforces the task's
target paths (`targets scope`) instead of skipping the scope check.
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ shellcheck: ## Lint gate scripts (skipped with a warning if shellcheck is absent
shellcheck -S error -e SC1091 plugin/bin/_gatelib.sh plugin/bin/_failclosed.sh $$(grep -l "^#!/usr/bin/env bash" plugin/bin/gate-*) plugin/bin/log-execution \
plugin/bin/selfcheck plugin/bin/transcripts plugin/bin/worktree-create plugin/bin/worktree-remove \
plugin/bin/worktree-hygiene plugin/bin/ensure-tools plugin/bin/md-db plugin/bin/ctx-symbols \
plugin/bin/session-start plugin/bin/_paths.sh plugin/bin/aloop plugin/bin/agentic plugin/bin/bind plugin/bin/task-worktree; fi
plugin/bin/session-start plugin/bin/_paths.sh plugin/bin/aloop plugin/bin/aladdin plugin/bin/agentic plugin/bin/bind plugin/bin/task-worktree; fi

.PHONY: pycheck
pycheck: ## Byte-compile the Python hook scripts
Expand Down Expand Up @@ -103,8 +103,11 @@ test-hosts: ## Budget/worktree regression + Codex hooks emulation + OpenCode plu
python3 scripts/test/model-routes.test.py
python3 scripts/test/host-adapter.test.py
python3 scripts/test/portable-config.test.py
python3 scripts/test/host-swap.test.py
python3 scripts/test/aladdin-cli.test.py
plugin/bin/host check
python3 scripts/test/targets-scope.test.py
python3 scripts/test/plan-render.test.py
python3 scripts/check-tracking.py
python3 scripts/test/codex-hooks.test.py
python3 scripts/test/rename-compat.test.py
Expand Down
7 changes: 4 additions & 3 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ These parts already exist but their semantics must change:

### 4.6 Semantic execution map

- 🟡 *Partly done (Unreleased): structured targets, shadow workspace and `targets target|context|shadow` (`bin/targets`, checked by gate-stage2-complete). Test: `scripts/test/semantic-targets.test.py`. The LSP adapter seam is done too (`AGENTIC_LSP_COMMAND`, `_lsp.py`; test: `scripts/test/lsp-adapter.test.py`). GREEN's diff scope is derived from the targets when no SCOPE_GLOBS is given (test: `scripts/test/targets-scope.test.py`). Open: making the rest of the semantic plan the execution source (tasks.md/plan.md as rendered views).*
- ✅ *Done (Unreleased): structured targets, shadow workspace and `targets target|context|shadow` (`bin/targets`, checked by gate-stage2-complete). Test: `scripts/test/semantic-targets.test.py`. The LSP adapter seam is done too (`AGENTIC_LSP_COMMAND`, `_lsp.py`; test: `scripts/test/lsp-adapter.test.py`). GREEN's diff scope is derived from the targets when no SCOPE_GLOBS is given (test: `scripts/test/targets-scope.test.py`). With `tasks` in targets.json the plan is the execution source: `targets render` writes tasks.md, validate.md and plan.md as deterministic views and `targets check` (gate-stage2-complete) refuses a hand-edited view (test: `scripts/test/plan-render.test.py`). Open: `refs`/`callers`/`callees` need a configured LSP server, so the narrow-context CLI is complete only where one exists.*
- **Structured change targets:**
- `change_ref`
- `operation` (create | modify | extend | refactor | replace | delete)
Expand Down Expand Up @@ -242,11 +242,11 @@ Results carry source refs and are attached to planning provenance. An unavailabl
- **A host capability matrix** covering usage, compaction, live messaging (for the time soft-stop), lifecycle and gate blocking.
- ✅ *Done (Unreleased): `enforce_gate` is `native` or `outer`; `host check` fails on anything else.* **Gate equivalence:** if a host cannot block natively, the outer controller enforces it. Never downgrade BLOCK to WARN.
- ✅ *Done (Unreleased): `bin/config` migrate/sync/check/show; config.yaml is authoritative, defaults.md is rendered from it. Test: `scripts/test/portable-config.test.py`.* **A portable project config** in `.aladdin/config.yaml` (budgets, context, semantic, models, provenance, memory), replacing `docs/agents/defaults.md` with a migration path.
- **Host swap:** a sprint started on one host resumes on another from portable state.
- ✅ *Done (Unreleased): `host swap --to H` hands the sprint over from the sprint dir, `.aladdin/config.yaml` and `.agentic/logs` only; live worker worktrees or a missing piece block; SessionStart on the new host resumes with the resume rule and records the rotation. Test: `scripts/test/host-swap.test.py`.* **Host swap:** a sprint started on one host resumes on another from portable state.

### 4.10 Metrics

✅ *Mostly done (Unreleased): the stats.md Metrics table. Test: `scripts/test/metrics.test.py`. Commits, test files added, time soft limits and semantic context served now come from the event stream. Rotations/compactions are counted from SessionStart events. Still open: context-window share (needs each model's window size).*
✅ *Done (Unreleased): the stats.md Metrics table. Test: `scripts/test/metrics.test.py`. Commits, test files added, time soft limits and semantic context served now come from the event stream. Rotations/compactions are counted from SessionStart events. Context-window share divides the context peak by `AGENTIC_CONTEXT_WINDOW` (`context.window` in config.yaml; hosts do not report the window, so the human sets it; default 200000).*

The run report should add:
- time soft preemptions;
Expand All @@ -269,6 +269,7 @@ No extra model calls are made just for telemetry.

### 4.11 Rebrand and product surface (last)

- 🟡 *Partly done (Unreleased): `bin/aladdin` (`"<intent>"`, `run`, `status`, `resume`, `report`, the semantic queries, every aloop tool) and the `/aladdin` skill, linked and copied by the installers beside `aloop` / `agentic`. Test: `scripts/test/aladdin-cli.test.py`. Open: the product-first README, the site, and linking every public claim to a measured run.*
- **New entry points:** `/aladdin` and an `aladdin` CLI (`"<intent>"`, `run`, `status`, `resume`, `report`, plus the semantic queries). Natural-language auto-trigger inside hosts.
- **Compatibility aliases for one migration window:**
- `/agentic-agile:init`
Expand Down
10 changes: 6 additions & 4 deletions docs/TRACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Status of every requirement in [ROADMAP.md](ROADMAP.md), in the four states §8
| 4.6 | Structured change targets, shadow workspace, `target` / `context` | IMPLEMENTED_TESTED | `scripts/test/semantic-targets.test.py` |
| 4.6 | LSP / structural adapter (refs, callers, callees) | IMPLEMENTED_TESTED | `scripts/test/lsp-adapter.test.py` |
| 4.6 | Semantic plan as the execution source: GREEN diff scope derived from targets | IMPLEMENTED_TESTED | `scripts/test/targets-scope.test.py` |
| 4.6 | Semantic plan as the execution source: tasks.md / plan.md rendered from it | NOT_IMPLEMENTED | — |
| 4.6 | Semantic plan as the execution source: tasks.md / validate.md / plan.md rendered from it (`targets render`) | IMPLEMENTED_TESTED | `scripts/test/plan-render.test.py` |
| 4.7 | Event stream `aladdin.event/1` | IMPLEMENTED_TESTED | `scripts/test/events.test.py` |
| 4.7 | Decision rationale + authority record | IMPLEMENTED_TESTED | `scripts/test/events.test.py` |
| 4.7 | Lineage: commit → intent → approver | IMPLEMENTED_TESTED | `scripts/test/commit-trace.test.py` |
Expand All @@ -36,9 +36,11 @@ Status of every requirement in [ROADMAP.md](ROADMAP.md), in the four states §8
| 4.9 | Host capability matrix | IMPLEMENTED_TESTED | `scripts/test/context-boundary.test.py` |
| 4.9 | HostAdapter interface extraction, gate equivalence (outer enforcement) | IMPLEMENTED_TESTED | `scripts/test/host-adapter.test.py` |
| 4.9 | Portable `.aladdin/config.yaml` with migration | IMPLEMENTED_TESTED | `scripts/test/portable-config.test.py` |
| 4.9 | Host swap: resume a sprint on another host from portable state | NOT_IMPLEMENTED | needs a two-host run |
| 4.9 | Host swap: resume a sprint on another host from portable state (`host swap`) | IMPLEMENTED_TESTED | `scripts/test/host-swap.test.py` |
| 4.10 | Metrics table (percentiles, breaches, waste, rates, cache, context peak) | IMPLEMENTED_TESTED | `scripts/test/metrics.test.py` |
| 4.10 | Commits, tests added, time soft limits, semantic context served | IMPLEMENTED_TESTED | `scripts/test/metrics.test.py` |
| 4.10 | Rotations / compactions | IMPLEMENTED_TESTED | `scripts/test/metrics.test.py` |
| 4.10 | Context-window share | NOT_IMPLEMENTED | needs each model's context window size |
| 4.11 | Rebrand and product surface | NOT_IMPLEMENTED | PR #7 starts the rename |
| 4.10 | Context-window share (peak / `AGENTIC_CONTEXT_WINDOW`) | IMPLEMENTED_TESTED | `scripts/test/metrics.test.py` |
| 4.11 | Entry points: `aladdin` CLI (intent, run, status, resume, report, semantic queries) and `/aladdin` | IMPLEMENTED_TESTED | `scripts/test/aladdin-cli.test.py` |
| 4.11 | Compatibility aliases (`agentic`, `/aloop`, `.agentic/` alongside `.aladdin/`) | IMPLEMENTED_TESTED | `scripts/test/rename-compat.test.py` |
| 4.11 | README reordered product-first; site / GitHub Pages; every public claim linked to a measured run | NOT_IMPLEMENTED | after the loop is stable; the measured runs exist (M0.8) |
4 changes: 4 additions & 0 deletions plugin/agents/planner.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ the first write passes (live runs 12–14 hit each of these):
`planned_symbol` — `create` for a new file (the path must not exist yet), `extend` for a new
symbol in an existing file (`"operation": "extend", "path": "src/lib.rs", "planned_symbol": "count_words"`);
- `modify|refactor|replace|delete` need a `symbol` that exists (or `planned_symbol` for `extend`).
Prefer the whole plan in targets.json: add `story` and `tasks` (`id` T1…, `title`, `summary`,
optional `budget`, `tests` [{path, fn, assert}], optional `validate` [{run, expect}]) and run
`targets render <STORY_DIR>` — tasks.md, validate.md and plan.md are then rendered from it,
and a hand edit to any of them is refused by the gate. Edit targets.json and re-render instead.

## Hard limits
- Writes no production code; does not start RED.
Expand Down
5 changes: 3 additions & 2 deletions plugin/bin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ ctx-symbols) → WARN + grep fallback; never a silent pass.
| `log-execution` | `wave-K activity SN-NN transition [detail…] [execution.log]` — append one transition line (default ledger: the latest sprint's); `--help` |
| `ensure-tools` | SessionStart — builds md-db + ctx-symbols into `$CLAUDE_PLUGIN_DATA/bin` on first run / version change (background), tells the model where the tools are. `--sync` build now · `--wait` · `--resolve T` real binary path |
| `md-db`, `ctx-symbols` | PATH shims (this `bin/` is on PATH in every session): exec the real binary, building it once if needed. Gates test presence with `ensure-tools --resolve`, never `command -v` |
| `aladdin` | the product entry point (ROADMAP §4.11): `aladdin "<intent>"` records the contract and prints how to start the run · `run` · `status` (sweep + resume rule + token totals) · `resume` (what SessionStart loads) · `report` (stats.md) · `target\|context\|refs\|callers\|callees\|shadow\|scope` → `targets` · any other aloop tool unchanged. |
| `aloop` | the one entrypoint: `aloop <tool> …` (`aloop --list`); `aloop init` = aloop-init, `aloop install` = install. Linked into `~/.local/bin` for Codex/OpenCode |
| `install` | `aloop install codex\|opencode [--project DIR\|--global] [--uninstall]` — renders agents/skills/commands (+ the OpenCode plugin from `hosts/opencode/`) from this plugin's sources; `status`; `claude` |
| `host` | the `HostAdapter` interface (ROADMAP §4.9, `_host.py`): Claude Code is the reference, Codex and OpenCode are adapters. `describe [--host H] [--json]` prints the contract (capabilities, spawn/wait/send/cancel/subscribe vocabulary, compact/rotate, isolation, gate install/enforcement, tool policy, resolved models) · `check` (every adapter complete; gates `native` or `outer`, never warn; in `make test-hosts`) · `worktree create\|remove\|diff TASK`. A capability a host lacks raises `Unsupported`, never a guess. |
| `host` | `swap --to H [SPRINT_DIR]`: hand the sprint to another host from portable state only (sprint dir, `.aladdin/config.yaml`, `.agentic/logs`); blocks on live worker worktrees or a missing piece, names the target's capability gaps, writes `.agentic/state/host-swap.json` (consumed by SessionStart on the new host) and emits `sprint.context_handoff`. · the `HostAdapter` interface (ROADMAP §4.9, `_host.py`): Claude Code is the reference, Codex and OpenCode are adapters. `describe [--host H] [--json]` prints the contract (capabilities, spawn/wait/send/cancel/subscribe vocabulary, compact/rotate, isolation, gate install/enforcement, tool policy, resolved models) · `check` (every adapter complete; gates `native` or `outer`, never warn; in `make test-hosts`) · `worktree create\|remove\|diff TASK`. A capability a host lacks raises `Unsupported`, never a guess. |
| `host-adapter` | SubagentStart/Stop: register sub-agents (`.agentic/state/agents/`) for the ledger; PreToolUse on Codex: a worker must `aloop bind <worktree>` first, then its commands/patches must stay in it (denied otherwise) |
| `task-worktree` | `add\|path\|remove <TASK_ID>` — per-task worktree at `.agentic/worktrees/<TASK_ID>` (branch `agentic/<TASK_ID>`) for hosts without built-in isolation; `merge <TASK_ID> <BRANCH>` — `--no-ff` merge of a host-made branch that emits `worktree.merged` + `commit.created` (the lineage on Claude Code) |
| `bind` | a worker's first command on Codex/OpenCode: validates its worktree (`aloop bind <path>`) |
Expand All @@ -61,7 +62,7 @@ ctx-symbols) → WARN + grep fallback; never a silent pass.
| `events` | the `aladdin.event/1` stream in `.agentic/logs/events.jsonl` (`_events.py`): `emit EVENT --task … --parent …` · `query --task/--event/--sprint` · `lineage TASK_ID` (worktree → limits → gates → decisions → merged/discarded, from refs, never transcripts) · `trace SHA` (commit → task → gates → plan → intent → approver) · `commit-msg TASK` (title + decisions + ids) · `graph [--format json|dot]` (downstream export). Written by `budget`, every gate verdict (`_gatelib.sh`) and `task-worktree`. |
| `intent` | the internal Intent Contract (ROADMAP §4.1): `new` issues the canonical `intent_id` + skeleton under `docs/agents/intents/`; `check FILE [--mode reviewed\|autonomous]` validates fields and the clarification policy (exit 2 invalid, 3 an `ask` needs the human); `summary FILE` lists defaults/assumptions/spikes for approval. Run by `gate-intake`. |
| `ids` | canonical identity + referential integrity (ROADMAP §4.5): `freeze SPRINT_DIR` checks the structured references (story frontmatter ↔ dir, dirs ↔ stories.md, validate.md ↔ tasks.md headings, `split_from` → a retired task) and issues frozen UUIDv7 ids in `sprintN/ids.json`; a retired alias is never reused · `check` · `resolve ALIAS`. Run by `gate-stage2-complete`; events then carry `story_uid`/`task_uid`. |
| `targets` | semantic execution map, first slice (ROADMAP §4.6): the planner's `<story>/targets.json` change targets. `check STORY_DIR` (run by `gate-stage2-complete`) · `target Tn STORY_DIR` (file:line, or `planned` for the shadow workspace) · `shadow` · `scope Tn STORY_DIR` (the diff scope gate-green-verify derives when SCOPE_GLOBS is unset) · `context Cn --budget N` (just the target's definition) · `refs\|callers\|callees` via the LSP server in `AGENTIC_LSP_COMMAND` (`_lsp.py`: references + call hierarchy); no server or a missing capability → exit 4, never guessed. Backend: ctx-symbols, else a definition regex flagged weaker. |
| `targets` | semantic execution map (ROADMAP §4.6): the planner's `<story>/targets.json` — change targets and, with `tasks`, the whole semantic plan. `render STORY_DIR [--check]` writes tasks.md / validate.md / plan.md as deterministic views over it (the gate refuses a hand-edited view) · `check STORY_DIR` (run by `gate-stage2-complete`) · `target Tn STORY_DIR` (file:line, or `planned` for the shadow workspace) · `shadow` · `scope Tn STORY_DIR` (the diff scope gate-green-verify derives when SCOPE_GLOBS is unset) · `context Cn --budget N` (just the target's definition) · `refs\|callers\|callees` via the LSP server in `AGENTIC_LSP_COMMAND` (`_lsp.py`: references + call hierarchy); no server or a missing capability → exit 4, never guessed. Backend: ctx-symbols, else a definition regex flagged weaker. |
| `impact` | optional cross-project impact provider seam (ROADMAP §4.8): `query consumers\|rationale\|migration\|standards SUBJECT [--task]` runs `AGENTIC_IMPACT_PROVIDER` (defaults.md or env), keeps only results with a `source_ref`, saves them under `docs/agents/impact/` and emits `artifact.created`. No provider or a failing one → WARN, exit 0. Builds no index. |
| `config` | the portable project config `.aladdin/config.yaml` (ROADMAP §4.9; sections budgets · context · semantic · models · provenance · memory · git, plus `budgets.roles.<role>`): `migrate` writes it from the current settings and renders `docs/agents/defaults.md` from it · `sync` re-renders defaults.md (SessionStart, `aloop-init --apply`) so bash readers see the same values · `check` validates (exit 2) · `show [--json]` effective value + source per setting. When it exists it is authoritative. |
| `capabilities` | the host capability matrix (`plugin/hosts/capabilities.json`: usage, compaction, live messaging, lifecycle, gate blocking; `unknown` = not advertised) · `boundary [HOST]` → rotate (default, the host's `/clear` or `/new`) or compact only when `AGENTIC_CONTEXT_BOUNDARY=compact` and advertised · `boundary --keep --reason` records the exception. SessionStart records `context.rotated` / `context.compacted`. |
Expand Down
2 changes: 1 addition & 1 deletion plugin/bin/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"time_hard_min": "TIME_HARD_MIN", "max_replans": "MAX_REPLANS", "token_meter": "TOKEN_METER",
"sprint_tokens_soft": "SPRINT_TOKENS_SOFT", "sprint_tokens_hard": "SPRINT_TOKENS_HARD",
"time_mode": "TIME_MODE"},
"context": {"boundary": "CONTEXT_BOUNDARY"},
"context": {"boundary": "CONTEXT_BOUNDARY", "window": "CONTEXT_WINDOW"},
"semantic": {"lsp_command": "LSP_COMMAND"},
"models": {"planning": "MODEL_PLANNING", "worker": "MODEL_WORKER",
"planning_codex": "MODEL_PLANNING_CODEX", "worker_codex": "MODEL_WORKER_CODEX",
Expand Down
Loading
Loading
0