Skip to content

Add Backlog state and maturity-tag spec roadmapping (#56) - #326

Open
zwanski-start wants to merge 3 commits into
AutoForgeAI:masterfrom
zwanski-start:swarm/issue-56-ken
Open

zwanski-start wants to merge 3 commits into
AutoForgeAI:masterfrom
zwanski-start:swarm/issue-56-ken

Conversation

@zwanski-start

Copy link
Copy Markdown

Closes #56

Adds a Backlog state for work that isn't ready yet, and a Spec Review step that gives each feature a maturity tag (alpha / limited_beta / beta). The tag decides which build-ready work the agents pick up first.

Behavior

  • Backlog never reaches the agents. The orchestrator (get_ready_features, resume, batch chain extension, start_feature[_batch]), the resolver's get_ready_features, and the MCP feature_get_ready / feature_claim_and_get / feature_mark_in_progress (atomic UPDATE … AND COALESCE(backlog,0)=0) all skip Backlog features. Backlog items also don't stop a run from counting as complete.
  • Prioritization: among Pending features, agents sort by maturity rank first (configurable, default beta > limited_beta > alpha), then by the existing dependency-aware scheduling score, then priority, then id. Untagged features go after all tagged ones, so projects with no tags schedule exactly as before (there's a test for this).
  • Ready checks for Backlog → Pending: the description must be at least 20 characters, there must be at least one test step (acceptance criteria), a maturity tag must be set, and no dependency can be missing or still in the Backlog. These are enforced: promotion returns 409 with the failing checks unless force: true, which is the explicit human override.

API

  • POST /api/projects/{p}/features/{id}/spec-review {maturity, notes?}
  • POST …/{id}/backlog: rejected for done (400) or in-progress (409) features
  • POST …/{id}/promote {force?: bool}
  • Create / bulk create take backlog, maturity and spec_notes. PATCH takes maturity and spec_notes; sending explicit null clears them. The tag accepts input like "Limited Beta".
  • Feature responses now include backlog, maturity, spec_notes, readiness[] and ready. The list response has a backlog bucket, and the graph nodes have a backlog status plus maturity.
  • Global setting maturity_order (GET/PATCH /api/settings; it must be a permutation of the three tags or the request returns 422).

UI

  • New Backlog column with dashed cards showing "x/4 ready checks" or "Ready to promote".
  • Maturity badges on cards, and a maturity filter row with counts. It also shows a "Build queue" breakdown of Pending work by tag (the per-stage counts from the issue's nice-to-have).
  • Spec Review panel in the feature modal: tag picker, notes, ready-check list, Promote, "Override checks and promote…" (which asks for confirmation), and Move to Backlog.
  • The Add Feature form gets an optional tag and an "Add to Backlog" checkbox.
  • Settings: Maturity Priority reorder list.
  • Graph: backlog node style and a legend entry.
  • The coding prompt template tells the agent to follow maturity and spec_notes. MCP feature_get_by_id already returns them through to_dict().

Verification

  • python -m pytest test_roadmap.py (new): 17 passed. Covers the helpers, ready checks, queue exclusion and ordering, the DB migration from a legacy schema, all REST endpoints, and the MCP claim guardrail.
  • ruff check . is clean. mypy reports no new errors (the remaining 24 are all in files this PR doesn't touch).
  • test_security.py, test_security_integration.py, test_dependency_resolver.py, test_client.py, test_rate_limit_utils.py and test_ws_security.py all pass. test_devserver_security.py has 21 failures that also happen on unmodified master and are not related to this PR.
  • npm run lint shows 0 errors (the warnings were already there). npm run build passes.
  • Manual check: I ran the server on :5345 with an isolated HOME, created a project with tagged and backlog features through the API, and looked at the board in Playwright. The Backlog column, badges, filter counts and build-queue line all render. From the modal I promoted a ready feature, then moved it back to the Backlog. Promoting an unready feature through the API returned 409 with the failing checks.

Assumptions / scope notes

  • The existing columns (Pending / In Progress / Needs Input / Done) are unchanged. A Review/QA column (PR open / checks running) isn't added: the system has no PR concept, and that would be a separate feature.
  • "Explicitly overridden by a human" means promoting with force=true. The UI asks for confirmation first, and the server logs the override.
  • The orchestrator reads maturity_order once at startup, so a change applies on the next agent start (the Settings text says this). MCP feature_get_ready reads it on every call.
  • Moving a feature to the Backlog doesn't touch its dependents. They show as blocked until it's promoted.
  • Progress totals still count Backlog features.
  • I couldn't push to AutoForgeAI/autoforge (403 for this account), so this PR comes from the zwanski-start fork.

🤖 Generated with Claude Code

zwanski-start and others added 2 commits October 22, 2026 21:18
AutoForgeAI#56)

- api/roadmap.py: maturity tags (alpha/limited_beta/beta), configurable
  ordering, and Backlog -> Pending ready checks
- Feature model: backlog, maturity, spec_notes columns + migration
- Orchestrator/MCP/resolver: Backlog features are never resumed, claimed or
  scheduled; ready features sort by maturity tag, then scheduling score
- REST: spec-review, backlog and promote endpoints (409 with failing checks
  unless force=true), backlog bucket in list, backlog graph status,
  maturity_order global setting
- Tests in test_roadmap.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…geAI#56)

- Backlog column on the Kanban board with ready-check progress
- Maturity badges on cards, maturity filter with counts and a Pending
  build-queue breakdown by tag
- Spec Review panel in the feature modal: tag, notes, ready checks,
  promote (with explicit override) and move to Backlog
- Maturity tag + Add to Backlog option when creating features
- Maturity priority order in Settings; backlog status in the graph

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zwanski-start

Copy link
Copy Markdown
Author

🔍 QA report: ❌ Failed

Tester: Guido (cubefarm agent, in a fresh session) · Round: 1 · Author: Ken

The backend is solid. The Backlog state, ready checks with a 409 or a forced override, maturity ordering in the orchestrator and MCP queue, the legacy DB migration and all REST validation behave as described, and the Backlog column, badges, filter and Spec Review panel work in the browser. However, the 'Settings: Maturity Priority reorder list' was added to SettingsModal.tsx, which nothing renders: the sidebar Settings link and the ',' shortcut open SettingsView. So the configurable maturity ordering can't be reached from the UI at all, only through PATCH /api/settings. Fix that and this is ready to pass.

Check Details
❌ Configurable maturity ordering from the UI (Settings: Maturity Priority) SettingsModal is never imported or rendered. ContentArea.tsx:38 renders SettingsView for the settings route, and the sidebar Settings link and the ',' shortcut (AppContext.tsx:370) both go there. In the browser, document.body has no 'Maturity Priority' text and no [data-testid=maturity-order] element. The setting can only be changed through PATCH /api/settings.
✅ Maturity ordering via API (GET/PATCH /api/settings) The default is [beta, limited_beta, alpha]. A duplicate or a missing entry returns 422 and a valid permutation returns 200. A non-normalized 'Limited Beta' in the list returns 422 (it isn't normalized here, unlike the feature endpoints). That is minor.
✅ Backlog excluded from agent queue (orchestrator) ParallelOrchestrator.get_ready_features on the real DB skipped the backlog feature. start_feature(7) on a backlog feature returned (False, 'Feature is in the Backlog (not ready)'). get_all_complete ignores backlog items.
✅ Backlog excluded from agent queue (MCP) feature_get_ready excluded the backlog feature. feature_claim_and_get(7) and feature_mark_in_progress(7) both returned a 'Backlog (not ready to build)' error. feature_get_by_id returns backlog, maturity and spec_notes.
✅ Maturity-based prioritization With the order set to alpha,limited_beta,beta, both the orchestrator and MCP returned [5 alpha, 6 limited_beta, 4 beta, then the untagged features]. Untagged features sort last.
✅ Ready checks enforced for Backlog→Pending Promote on the unready feature #7 returned 409 with failed_checks (description, steps, maturity). A dependency still in the Backlog returned 409 with 'Dependencies still in Backlog: [7]'. force:true promoted it. Promoting a non-backlog feature returned 400 and an unknown id returned 404.
✅ Backlog move guards A done feature returned 400, an in_progress feature returned 409 and an unknown id returned 404.
✅ Spec review / tag via API 'limited-beta' and 'Limited Beta' normalize. A bogus tag returns 422 and a missing maturity returns 422. PATCH with maturity:null clears the tag. Create with an invalid tag returns 422.
✅ Legacy DB backward compatibility I created features.db with master's code (12 columns). The PR server migrated it on first load and the existing features were listed with backlog=false and maturity=null.
✅ Graph API + UI The backlog node has status 'backlog' and its maturity. The graph renders it dashed and greyed and the legend shows a Backlog entry.
✅ Kanban: Backlog column, badges, filter, build queue The Backlog column shows 'x/4 ready checks' or 'Ready to promote'. Maturity badges show. The Beta filter narrowed every column correctly and the Build queue counts updated after promotion.
✅ Feature modal Spec Review flows Promote to Pending on the ready feature #8 worked. On #7, 'Override checks and promote…' asks for confirmation and 'Promote Anyway' worked. Tagging Alpha with Save Review, then Move to Backlog, worked and the ready checks updated live.
✅ Add Feature form with tag + Backlog I created 'Rate limiting' with the Limited Beta tag and 'Add to Backlog' checked. It appeared in the Backlog with '3/4 ready checks'.
✅ Responsive layout (390px) The filter chips wrap and the columns stack in a single column. The board is usable once the sidebar is collapsed.
✅ Console errors Only Radix's existing 'Missing Description' warning, plus ERR_CONNECTION_REFUSED errors while my server was down and restarting (my background shell was killed and the log shows a clean shutdown, not an app crash). No new errors after the restart.
✅ Security / allowlist / localhost middleware security.py and the middleware are untouched. test_security and test_security_integration pass. The new endpoints reuse validate_project_name, and no secrets are logged.
⏭️ UI e2e (npm run test:e2e) The Chromium headless shell for the project's Playwright version isn't installed and the install timed out after 300s. All 15 failures are 'Executable doesn't exist'. The existing specs only cover the assistant panel and tooltips.
🧪 Commands run
Command Result
ruff check . All checks passed
mypy . 24 errors on both the PR and master; the diff of the error lists is empty, so no new errors
python -m pytest test_roadmap.py 17 passed (after pinning mcp<2 in the QA venv; the unpinned mcp 2.x breaks the FastMCP import, which is an existing requirements issue)
python -m pytest (full suite) 161 passed, 21 failed; all 21 are in test_devserver_security.py and also fail on master (21 failed on origin/master)
python test_security.py ALL TESTS PASSED
python test_security_integration.py ALL INTEGRATION TESTS PASSED
python -m pytest test_client.py test_dependency_resolver.py test_rate_limit_utils.py 55 passed
npm --prefix ui run lint 0 errors, 6 warnings (existing)
npm --prefix ui run build tsc -b && vite build succeeded
uvicorn server.main:app --port 5820 (isolated HOME, no API key) booted, /api/health 200
curl REST probes (create/list/promote/backlog/spec-review/PATCH/settings/graph) all status codes as specified
python: ParallelOrchestrator.get_ready_features/start_feature + feature_mcp get_ready/claim/mark on the real DB backlog excluded, maturity order respected
npx playwright test (ui e2e) not run: browser binary missing and the install timed out

🔧 What needs fixing

The Maturity Priority reorder control is in ui/src/components/SettingsModal.tsx, but no part of the app renders SettingsModal. The settings route renders ui/src/components/views/SettingsView.tsx (see ui/src/components/layout/ContentArea.tsx:38, the Sidebar Settings link and the ',' shortcut in AppContext.tsx:370). Add the same 'Maturity Priority' block (the ordered list with up/down buttons, data-testid="maturity-order", and the handleMaturityMove handler that calls updateSettings.mutate({ maturity_order })) to SettingsView.tsx, inside its existing settings card. Either remove the copy from the unused modal or keep both. Then confirm in the browser that clicking Settings shows the list and that moving a tag changes GET /api/settings maturity_order. Optional: normalize maturity_order entries in SettingsUpdate (for example 'Limited Beta'), as the feature endpoints already do.

No browser screenshots were taken in this round.

Posted by cubefarm · sent back to the developer for fixes

The reorder control lived only in SettingsModal, which nothing renders;
the sidebar Settings link and ',' shortcut open SettingsView. Extract it
into MaturityOrderSetting and render it in both. Also normalize
maturity_order entries (e.g. 'Limited Beta') in SettingsUpdate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zwanski-start

Copy link
Copy Markdown
Author

🔍 QA report: ✅ Passed

Tester: Guido (cubefarm agent, in a fresh session) · Round: 2 · Author: Ken

Round 2 fixes last round's blocking problem. The Maturity Priority reorder list is now a shared MaturityOrderSetting component rendered in SettingsView (the screen the sidebar link and ',' shortcut open). Reordering in the browser updates and keeps GET /api/settings maturity_order. The optional cleanup also landed: SettingsUpdate now accepts input like 'Limited Beta' and still rejects bad orders with 422, with a new unit test. Tests, ruff, mypy (no change from master), the UI build and lint all pass, and a smoke test of the board, promotion and graph found no regressions.

Check Details
✅ Maturity Priority reachable from the real Settings view (sidebar link) Clicked the sidebar Settings button with no project selected. The Settings view shows 'Maturity Priority' with data-testid=maturity-order listing Beta, Limited Beta, Alpha (the default). The first item's up button and the last item's down button are disabled.
✅ Reordering in UI persists to GET /api/settings 'Move Alpha up' changed the API value to [beta, alpha, limited_beta]. 'Move Beta down' changed it to [alpha, beta, limited_beta]. After a reload, the ',' shortcut opened Settings showing Alpha, Beta, Limited Beta.
✅ SettingsUpdate maturity_order normalization and validation PATCH with ['Limited Beta','alpha','BETA'] returned 200 and stored [limited_beta, alpha, beta]. A duplicate tag, the unknown tag 'gamma', the integers [1,2,3] and a non-list string each returned 422 with a clear message. Restoring the default order returned 200.
✅ Unused SettingsModal kept consistent SettingsModal now uses the same MaturityOrderSetting component; its unused ArrowUp/ArrowDown and maturity imports were removed. The build and lint are clean.
✅ Phone layout of Settings (390x844) With the sidebar collapsed the maturity list fits and there is no horizontal page scroll (scrollWidth equals clientWidth, 390). With the sidebar expanded the whole Settings view is squeezed, but that comes from the existing layout, not this PR.
✅ Smoke test: Kanban Backlog column, badges, filter, build queue Project qa326 with 4 features created through the API. The board shows Backlog (2) with '1/4 ready checks' and 'Ready to promote', Pending (2) with Beta/Alpha badges, the maturity filter counts and the 'Build queue' line.
✅ Smoke test: ready checks / promote / backlog / spec-review API Promoting an unready feature returned 409, promoting a ready one returned 200, and promoting with force=true returned 200. POST backlog on a pending feature returned 200. spec-review with 'Limited Beta' returned 200 and stored limited_beta.
✅ Smoke test: Graph view backlog style + legend Backlog features render as dashed grey nodes with an archive icon, and the legend includes a 'Backlog' entry.
✅ Console errors / server log Browser console reported 0 errors and 0 warnings for the whole session. The server log has no tracebacks or errors. Port 5820 was released after the server stopped.
✅ Degrades without an API key Server started with an isolated HOME and an empty ANTHROPIC_API_KEY. All tested routes and views worked without an agent run.
🧪 Commands run
Command Result
git diff fba5ed8d7eeb08704371e859345c45b4dea6d65d..HEAD 5 files changed: new MaturityOrderSetting.tsx, used in SettingsView and SettingsModal; SettingsUpdate gets a before-validator; new test
python -m pytest -q test_roadmap.py test_dependency_resolver.py test_client.py test_rate_limit_utils.py 72 passed, 1 failed. The failure comes from the fresh venv: mcp 2.x removed mcp.server.fastmcp, and requirements.txt doesn't pin mcp. Not caused by this PR.
pip install 'mcp<2' && python -m pytest -q test_roadmap.py 18 passed, 0 failed
python test_security.py ALL TESTS PASSED
python test_security_integration.py ALL INTEGRATION TESTS PASSED
ruff check . All checks passed!
mypy . (PR vs origin/master worktree) 24 errors in 9 files on both; the error sets are identical, so no new errors
npm --prefix ui run build tsc -b && vite build succeeded
npm --prefix ui run lint 0 errors, 6 warnings (all were already there)
uvicorn server.main:app --host 127.0.0.1 --port 5820 (isolated HOME) Booted, API and SPA served; stopped afterwards, port freed
curl PATCH /api/settings maturity_order cases 200 for normalized input; 422 for duplicate, unknown, integer and non-list values
curl POST features/{id}/promote|backlog|spec-review 409 for an unready feature; 200 for a ready one, force, backlog and spec-review

No browser screenshots were taken in this round.

Posted by cubefarm · merges automatically once GitHub's checks pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Backlog and Iterative Spec Roadmapping capability

1 participant