8000 A goal its sprints did not meet is retired, and the loop moves on (M9.50) by adeelahmad · Pull Request #103 · 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tag in lockstep. Tag releases as `vMAJOR.MINOR.PATCH`.
- Core agent principles and the one-way / two-way door rule (ROADMAP §4.12, M9.30): seven core principles from Amazon's Leadership Principles, the door rule first, go to every aloop agent at session start (`aloop mission principles show --core`). A two-way door (a branch, a local edit, a test, a draft PR) is decided, not asked. A one-way door (`aloop mission doors list`: a push or merge to the default branch, a force-push, a release, a deploy, a message sent outside, a secret, dropped data, …) is stopped by a PreToolUse gate with `ASK[door] <id>` until the human records an authorization in their own terminal (`aloop mission doors authorize ID --by NAME --reason TEXT [--until DATE] [--once DIGEST]`, a hash-chained ledger row); a wall (switching a gate off, forging a human record) is never crossed. While a run is live, a question to the human must name a door the gate stopped and nobody authorized. Reason: Adeel's request that agents decide two-way doors themselves and ask only at a one-way door not already authorized. Test: `mission-doors.test.py`. Hardened by an adversarial review (15 findings, each a test): the gate reads Bash as the shell does (comments, line continuations, heredoc bodies, `xargs`, `find -exec`, `echo … | sh`), a branch condition reads the directory the command acts on (`git -C`, `cd`), settings are guarded wherever they live, dry runs and `command -v` are two-way, the newest decision by time counts and a revoke holds on every branch, a once-grant is crossed once under a lock, a broken ledger is named, and `doors authorize` refuses an agent's shell.
- DeepSeek Harness (dsh) host (ROADMAP §4.9): `aloop install dsh` (alias `deepseek`; `--project P` or `--global`) renders a `dsh --profile aloop` profile in `$DSH_HOME` and installs the skills. Its native plugin (`plugin/hosts/dsh/aloop.mjs`) runs the same gates as Claude Code on dsh's own events: a deny before a tool runs, a block after an invalid artifact write, and a stop gate that steers a role back up to 3 times before the supervisor is told it is BLOCKED (or STUCK, released unverified). Roles are agent presets on two subagent tools, one per model route (`deepseek-v4-pro` for planning, `deepseek-flash` for work by default; `MODEL_PLANNING_DSH` / `MODEL_WORKER_DSH` override). A writer's `aloop bind` moves its working directory into its worktree, and `host-adapter` confines its commands, edits and `working_directory` there. Usage is recorded Claude-shaped per role, so budgets, the ledger and `run-summary` work unchanged. `make e2e-live HOST=dsh` drives it live and exits 2 with the fix when no `DEEPSEEK_API_KEY` is set. Reason: DeepSeek's own harness is the cheapest route to a strong model. The profile records the project it serves (or `--global`), so another project's `aloop-init` never re-renders it, and gates get the worker shell's environment (no API key). The mission layer's six roles run on dsh too: presets on their route group's subagent tool, `gate-mission-scope` on every write and command, and `gate-mission-artifact` at each role's start and stop; the mission skill installs as `aloop-mission`. A second review (3 lenses; 11 confirmed findings, each fixed with a test) closed: a working directory that vanished (dsh's tools move it back to the main tree, so the plugin judges `ensure()`'s directory and `host-adapter` refuses to run from a missing one), gate switches from the project's `.env` (dsh loads it; `SKIP_HOOKS`, `GATE_RUN_TESTS`, `REPO_DIR`, `AGENTIC_*` from it never reach a gate), an interrupted Stop that dropped the sprint-close notice, and the shared profile: its owner is the main tree, an older unrecorded profile is claimed only by the project that installed it, and a project it does not serve is told so by `install status`, `aloop-init` and the session itself. Tests: `dsh-plugin.test.mjs` (40 checks, emulated), `dsh-runtime.test.mjs` (32 checks on the real pinned dsh 0.2.1-rc.2 with a scripted model; the CI hosts job installs it) and `dsh-install.test.py` (9).
- Brand kit and repo front page: `docs/brand/` holds the mark (an **a** whose bowl is a red-to-green loop passing a gold gate, with a 16 px cut), lockups, light and dark README banners, favicons, app icons, the site's OG card and the GitHub social preview, all generated by `docs/brand/gen_brand.py` from one palette with WCAG checks (rules in `docs/brand/README.md`). The README leads with the mission layer, the agent principles and the door rule, the supported hosts and the measured demo runs; the site carries the favicon and Open Graph/Twitter card metadata; `SECURITY.md` and bug/feature issue forms are new.
- A goal its sprints did not meet is retired, and the loop moves on (ROADMAP §4.12, M9.50): `aloop mission goal retire GOAL --eval EVAL` records `goal.retired` in the committed ledger once every intent of the goal was sprinted and its sprints closed, and the newest eval of it, made after those closes from a state measured after them, still lists gaps. A retired goal takes no more intents, sprints or close. `mission evaluate` covers the whole mission again, and the retired goal's own open gaps are held from the next goal until a new baseline version or the human's next approval of the mission, so the loop does not sprint the same gaps again; a regression is never held. When every gap is held, `mission tick` says `BLOCKED` and the human's `aloop mission tick --force --by NAME` lifts it. `mission tick` hands this out as `RETIRE_GOAL` (role `mission-planner`) where it used to stop at `BLOCKED` for the human. It asks the command's own rule first: a stale state or eval becomes `ASSESS` or `EVALUATE`, and any other refusal is `BLOCKED` with its reason. 3 retired goals in a row still go to the human. The planner's stop takes a retired goal as its finding. Tests: `mission-goal` check 13, `mission-tick` checks 28 and 33, `mission-roles`.
- A mission's gap lists count only as `mission evaluate` computed them (ROADMAP §4.12, M9.27): `evaluate` records `eval.completed` in the committed ledger, and `mission tick`, `evaluate check` and `goal` take the newest eval whose content that record covers, with a matching seal, in the ledger's order. An eval file written by hand, or edited (or re-stamped) after it was recorded, no longer sends the loop to `RESEARCH` as "goal met" or makes `goal derive` refuse what tick handed out, a clock that is behind no longer reorders them, and a fresh checkout derives and closes goals from the evals it committed. An eval or state named as journey or baseline evidence needs its record too. Tests: `mission-tick` check 32, `mission-journeys`.
- A mission's stop at a spend cap holds on a fresh checkout (ROADMAP §4.12, M9.24): the first `STOP_BUDGET` tick records a `mission.budget_exhausted` ledger row for the mission's content (once per content), and `mission tick` stops on it whatever the checkout's token ledger says, until a raised cap changes the content.
- Lifting a mission block is the human's own words (ROADMAP §4.12, M9.51): `aloop mission tick --force --by` now asks (exit 3) for the human's typed `lift <mission> <code>` line, the code bound to this occurrence of that block, and records a `mission.lifted` ledger row, so `--by` alone, a lift only the run log has (or a replayed one), an old line or a line typed for an earlier block lift nothing, a lift of 3 failed goals reaches only those goals whatever `--now` says, and a fresh checkout keeps a lifted block lifted. `/aloop:mission` counts a lift among the typed grants it relays. A lift recorded before this (run data only) no longer counts.
Expand Down
Loading
Loading
0