Repository navigation
feat(workspace): suggestions — what you can do with this agent, and what is waiting (abilityai/trinity-enterprise#465) - #3000
Conversation
…hat is waiting (ent#465) A platform user opening an agent in the Workspace gets a short list computed for them and that agent: questions and decisions waiting on them, the health of the agent's schedules (owner/admin only), dormancy, and exposed playbooks they have not run. Each item shows the signal it came from; Accept prefills the composer, opens a section or deep-links to the operator schedules tab (never sends — ent#138), Dismiss holds until the state changes. - client_portal/suggestions/ (router → service → db): platform door only (uniform 404 for a portal token), pure ranking over an injected now, state-identity fingerprints, bounded feedback writes (recompute + 404) - workspace_suggestion_feedback table on both tracks (SQLite migration + Alembic 0073), CASCADE on the agent - PortalPrincipal.is_admin (role admin AND ADMIN_GATE_SCOPES) for the one configure-visibility decision - PortalSuggestions.vue in the Info tab and above the empty-chat hints; the Info rail tab lights its updated dot with "N suggestions" - requirement core-agent.md §5.39, architecture/workspace.md, flow doc, J13 journey skeleton Related to Abilityai/trinity-enterprise#465 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- streak query ranks only the agent's live schedules, never chat/API runs (schedule_id='__manual__') - runs attributed to the viewer (operator chat, MCP) count as history, so a console-only owner is not told "you haven't talked to this agent yet" - briefing cache bounded (TTL-expired entries first, then the oldest) - store: both placements share the in-flight load; an item dismissed during a reload does not come back with it; a failed dismiss restores only its item into the current list - platform door: a test executes the is_admin wiring line (red with it reverted) - docs: Info is no longer a static tab (architecture/workspace.md, workspace-rail.md); known limits recorded; two learnings Related to Abilityai/trinity-enterprise#465 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nt#465) /review on #3000: - _gather/_compute over a real SQLite file: live schedule ids reach the streak query and a console-only owner has history — red with either change reverted - store: an older load answering after a newer (forced) one no longer overwrites it; pinned by a mounted test, red without the guard Related to Abilityai/trinity-enterprise#465 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
/review report: PR #3000Branch: Execution coverage
Source-text hit: Critical findingsNone. Informational findings (all fixed in
|
…mory/learnings/README.md) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Full backend unit suite, diffed by node id against a clean
No new failures. The 55 failing node ids are identical on both sides. They're local-environment failures, not caused by this PR: DNS/SSRF resolution, IPv6 origin, git-refresh hooks and objective-join container reads, run on a Python 3.12 venv against 3.13 images. The +50 passed are this PR's new tests. |
|
merge-train (2026-09-24): not on this train — Alembic fork, rides the next one once re-parented. Validated at lane B+schema: READY (db→service path executed over real SQLite, portal endpoints gated through |
|
|
Renumbers this branch's Alembic revision to 0075 on top of dev's 0074_role_readiness_rollout_seed so the version-line keeps a single head. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The merge-from-dev commit renamed the revision to 0075 but left its down_revision (and the tests/docs naming it) at the 0072 fork point, so the graph still had two heads. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Resolve by running |
|
Resolve by merging |
… fields; keep-both elsewhere dev (#3023) and this branch each added a third field to PortalPrincipal. dev's is_person stays third, since code on dev already constructs it positionally; is_admin goes last, which is what its own comment asks for. get_portal_principal passes both. The one positional construction that meant is_admin (test_ent465_suggestions.py) now names it. migrations.py tail and tests/registry.json: both sides kept, dev's first; the registry is rebuilt from the merge stages, not spliced. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ions # Conflicts: # src/backend/db/migrations.py
…78 (#3000) 0075_workspace_suggestion_feedback parented on 0074_role_readiness_rollout_seed; dev has since added 0075-0077 on that line. Merged as it was, the version line has two heads and 'alembic upgrade head' applies nothing (#2068). Renamed to 0078_workspace_suggestion_feedback with down_revision 0077_execution_chain_depth. The SQLite entry is keyed by name and is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
merge-train (2026-09-27): three commits pushed to this branch, all mechanical. Validated at lane B + schema on
1,491 tests pass locally on the merged tree (portal, Workspace, ent#611, #2806, and the migration and Alembic guards). Follow-ups, not blocking:
|
vybe
left a comment
There was a problem hiding this comment.
Validated at lane B + schema: READY, no criticals. After the merge-train commits (two dev merges, revision re-parented to 0078), all 24 checks are green on 8670cd0, including pytest (head), e2e, pg-migrations, schema-parity and both CodeQL analyses. Follow-ups are in the comment above.
Summary
A platform user who opens an agent in the Workspace now gets a short list of suggestions computed for them and that agent. Each item names the evidence behind it, and each has two verbs:
/playbookin the composer (it never sends, per ent#138), opens the right section, or deep-links to the operator schedules tab. The deep link follows the engine-bay ruling (decision 15, option 1).Nothing is padded: with nothing to say, the list says so.
📸 Walkthrough (light and dark, local demo stack, seeded data): https://claude.ai/artifact/EHEC68JByxJ8k392CYx2XC
v1 classes
Order is display priority. At most 5 are shown, and the list states the total.
asksdecisions_duereview_byschedule_failing:<id>autonomy_heldschedule_never_fired:<id>schedule_disabled:<id>dormantunused_playbook:<name>Design decisions
Door
OwnedAgent).PortalPrincipal.is_adminrequiresrole == adminAND a scope inADMIN_GATE_SCOPES. It exists for this one decision; elsewhere a non-owner admin stays a viewer (ent#358).Dismissal
Honesty
Cost
Deferred (filed and linked under epic ent#78):
Changes
src/backend/client_portal/suggestions/(router → service → db),portal_auth.py(is_admin),main.py(router registered).workspace_suggestion_feedbackinschema.py,tables.pyandmigrations.py, plus Alembic0073_workspace_suggestion_feedback(single head over0072). CASCADE entry inagent_cleanup.py.PortalSuggestions.vue, placed in the Info tab (full) and between the agent identity and "Things you can ask" on an empty chat (compact).clientPortalstore gets its suggestions slice.portalRail.js: Info lights theupdateddot with anote("Info · 8 suggestions"). This amends ent#547's "static tab".core-agent.md§5.39,architecture/workspace.md,feature-flows/workspace-suggestions.md(plus the rail flow amendment), design-system p27 note, and twolearnings.mdentries.JOURNEYS.mdregenerated.Test Plan
cd tests && pytest unit/test_ent465_suggestions.py: 53 passed. Covers every threshold at its boundary, the SQL on a real SQLite file, the doors, bounded writes, a stopped agent never calling the briefing, and theis_adminwiring (red with the wiring reverted).npm run test:unit: 166 files, 3,575 passed, including the mountedportalSuggestions.spec.jswith 13 tests (accept, dismiss, rollback, the two races, states, compact).check_alembic_heads.py: one head.devbaseline: still running at the time of opening. I'll post the result as a comment.0073_*revision off0072. Whichever lands second re-chains to0074and runscheck_alembic_heads.py.Fixes abilityai/trinity-enterprise#465
🤖 Generated with Claude Code