Skip to content

feat(plan): agent-first T5 leaves + parity (CLI_HANDOFF) - #129

Merged
xergioalex merged 4 commits into
mainfrom
plan__next
Oct 5, 2026
Merged

xergioalex merged 4 commits into
mainfrom
plan__next

Conversation

@xergioalex

@xergioalex xergioalex commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Summary

Fifteen agent-first Plan leaves + skill coverage aligned with API OpenAPI x-cli-command (CLI_HANDOFF / plan__next).

Code release: WC-37 · response 17878edd

Companion: DailybotHQ/agent-skill PR (T5 skill docs) — linked when opened.

Leaves

Command API
plan project reorder POST /v1/plan/projects/{id}/reorder/
plan board reorder POST /v1/plan/boards/{id}/reorder/
plan board move-preview GET .../move-preview/?project=
plan board view create POST .../views/ + Idempotency-Key
plan views workspace GET /v1/plan/views/workspace/
plan views workspace save PUT + If-Match
plan tasks board GET /v1/plan/tasks/board/
plan task brief GET .../brief/ (existing)
plan board member update PATCH .../members/{user}/
plan label list|create|update|delete /v1/plan/labels/
plan project view create POST + Idempotency-Key
plan project member update PATCH members

Test plan

  • pytest tests/plan_agent_first_t5_leaves_test.py (19 passed)
  • CI green on this PR

Notes

  • Do not merge without Sergio.
  • Phase2 honesty: delegation 501; no fake goals-review; author_kind=agent never from org agent key.
  • Related API: DailyBot-Inc/api-services#8130

## Summary
Implement the 15 OpenAPI x-cli-command Plan leaves for agent-first parity
(project/board reorder, move-preview, view create, workspace views, tasks board,
member update, org label CRUD). task brief already existed.

## Change Log
- Client methods for reorder, move-preview, workspace views, plan labels, tasks board
- Click commands under board, project, tasks, plan label, plan views
- 19 wire+CLI tests; skill intent notes for T5 leaves

## Risks
- Workspace views group uses invoke_without_command for GET + save subcommand
- Live API must match schema annotations on plan__next
@xergioalex

Copy link
Copy Markdown
Member Author

## Summary
Code Check failed on ruff format --check for the five T5 leaf files.
## Summary
mypy failed CI: member update, move-preview, and tasks board human
renderers omitted the required fields list.
@xergioalexpro

Copy link
Copy Markdown
Contributor

Loop review / CI fix

CI was red on Code Check — not pytest failures:

  1. ruff format — 5 T5 leaf files reformatted (34a8dd6)
  2. mypy — print_tasks_detail_panel required fields on member update / move-preview / tasks board fallback (f42d037)

Local: pytest tests/plan_agent_first_t5_leaves_test.py → 19 passed; mypy dailybot_cli clean; ruff format --check clean.

HEAD: f42d037 — Code Check 3.10/3.12 + build smoke pass. Do not merge without Sergio.

## Summary
Keep vendored skill pack aligned with DailybotHQ/agent-skill#66 after loop review.
@xergioalex xergioalex added the Ready Trigger AI code review label Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

AI review for 7854b48 — ✅ done

View review →

Highest severity: warning

Verifier: 4 checked · 2 verified · 0 downgraded · 0 refuted · 2 unverified · 3 skipped — grok-4.5 (economy), 100s

Strictness gate: ✅ highest severity warning ≤ critical threshold

7 inline comment(s) attached.

Usage: 1286.6k in (91% cached) · 14.7k out · est. $0.66 · 17 turns · 414s

Iteration-Aware Review: gen 1, round 1, policy=first-pass-exhaustive (first_review) — 7 surfaced.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review — 7 finding(s): 0 critical · 4 warning · 3 info

Verification: 2 verified · 0 downgraded · 0 refuted · 2 unverified · 3 skipped — grok-4.5

Check: ✅ passing — strictness block-on-critical: highest severity warning ≤ critical threshold

Findings

Severity Location Title Verification Agreement
⚠️ warning dailybot_cli/api_client.py:3047 Member inspect PATCH is not empty when agent_name is set unverified —
⚠️ warning dailybot_cli/api_client.py:4357 Project member inspect also stamps agent_name into empty PATCH unverified —
⚠️ warning dailybot_cli/commands/plan_views.py:84 Workspace --etag uses click.echo instead of print_raw_value verified —
⚠️ warning .agents/skills/dailybot/tasks/SKILL.md:1200 SKILL points at missing commands.md § Agent-first T5 leaves verified —
ℹ️ info dailybot_cli/commands/board.py:221 Member detail panel lists Role while help says membership has no role skipped —
ℹ️ info dailybot_cli/commands/tasks.py:431 Redundant local imports already present at module top skipped —
ℹ️ info tests/plan_agent_first_t5_leaves_test.py:151 No CLI coverage for reorder --before/--after mutual exclusion skipped —

Summary

Verdict

Solid agent-first T5 surface: client paths, thin Click wiring, Idempotency-Key / If-Match patterns, destructive label delete, and mocked tests all track existing Plan conventions. A few agent-path and docs-contract gaps should be fixed before merge.

What matters

  1. Member inspect + agent stamp (warning). update_board_member / update_project_member document an empty PATCH body, but _tasks_write injects agent_name into every dict JSON body. With DAILYBOT_AGENT_NAME set (normal for these leaves), the wire body is no longer {}. Prefer stamp_agent=False like update_view, and extend the empty-PATCH tests to a client that has agent_name.

  2. Workspace --etag output (warning, Rule 9). plan_views.py uses raw click.echo(etag); board views / project views already use print_raw_value. Align so shell capture stays on the shared helper.

  3. Skill ↔ commands.md gap (warning). The new SKILL section points at commands.md § “Agent-first T5 leaves”, which is absent, and the inventory tables still omit the new leaves. Agents will not find flag contracts. Ship that section here or in the companion skill PR before merge.

Secondary

  • Member detail panel still lists Role while help says membership has no role column (info).
  • Redundant display imports inside tasks_board (info).
  • No CLI test for --before + --after on reorder (info / test-gap).

What looks good

  • Workspace views save mirrors board/project If-Match + --fetch-etag mutual exclusion.
  • View create doors take Idempotency-Key through _tasks_write(idempotent=True).
  • Label CRUD reuses update_tasks_label / delete_tasks_label and confirm_without_preview.
  • Tests mock require_auth per module and never touch the real API.
  • No new dependencies, secrets, or auth-resolution changes.

Note to verify with API (not filed)

create_board_view / create_project_view stamp agent_name into the POST body. Single-view update_view already uses stamp_agent=False because the door rejects agent_name. Confirm the nested create serializers accept the stamp; if they reject unknown_field, disable stamping there too.

Recommendation: request-changes


Check status: ✅ passing — strictness block-on-critical, highest severity in effect warning: highest severity warning ≤ critical threshold.

This line is written by the reviewer runtime after the gate ran and matches the check conclusion and the tracking comment. Any recommendation above is the model's advisory opinion, not the gate.

Comment on lines +3044 to +3047
return self._tasks_write(
"PATCH",
f"boards/{_path_segment(board_uuid)}/members/{_path_segment(user_uuid)}/",
json={},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGENTS.md Rule (Tasks agent stamp): _tasks_write stamps agent_name into every JSON dict body on POST/PUT/PATCH. These inspect doors document an empty body (json={}), but with DAILYBOT_AGENT_NAME / --agent-name (the agent-first path) the wire body becomes {"agent_name": "…"}.

Failure mode: agents calling plan board member update / project member update no longer send the empty PATCH the API contract describes; if the membership serializer treats non-empty bodies strictly (or rejects agent_name as unknown_field), the leaf fails exactly for the audience these T5 leaves target. The unit test only covers a client with no agent_name.

Fix: pass stamp_agent=False (same posture as update_view) so the body stays {}:

Suggested change
return self._tasks_write(
"PATCH",
f"boards/{_path_segment(board_uuid)}/members/{_path_segment(user_uuid)}/",
json={},
return self._tasks_write(
"PATCH",
f"boards/{_path_segment(board_uuid)}/members/{_path_segment(user_uuid)}/",
json={},
stamp_agent=False,
)

Comment on lines +4354 to +4357
return self._tasks_write(
"PATCH",
f"projects/{_path_segment(project_uuid)}/members/{_path_segment(user_uuid)}/",
json={},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same failure mode as update_board_member: update_project_member sends json={} but _tasks_write injects agent_name whenever the client has one, so agent-first calls are not an empty inspect PATCH.

Apply the same fix:

Suggested change
return self._tasks_write(
"PATCH",
f"projects/{_path_segment(project_uuid)}/members/{_path_segment(user_uuid)}/",
json={},
return self._tasks_write(
"PATCH",
f"projects/{_path_segment(project_uuid)}/members/{_path_segment(user_uuid)}/",
json={},
stamp_agent=False,
)

Add a client wire test with agent_name="…" asserting the JSON body stays {} for both member inspect methods.

Comment on lines +78 to +84
if etag_only:
if etag is None:
raise click.ClickException(
"The server returned no ETag for workspace views, so a save cannot be "
"made safely from this response."
)
click.echo(etag)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGENTS.md Rule 9: user-facing output goes through display.py; raw click.echo is only allowed for _print_org_list and the hook group. Board and project views already print the pipeable ETag via print_raw_value(etag or "") (board.py / project.py).

This leaf uses click.echo(etag) instead, so workspace ETag capture drifts from the established helper (and from the SECURITY.md note that views --etag values are entity tags printed for shell capture).

Suggested change
if etag_only:
if etag is None:
raise click.ClickException(
"The server returned no ETag for workspace views, so a save cannot be "
"made safely from this response."
)
click.echo(etag)
print_raw_value(etag)

Import print_raw_value from dailybot_cli.display next to the other helpers.

Comment on lines +1196 to +1200
### Agent-first T5 leaves (OpenAPI `x-cli-command`)

**CLI requirement.** These leaves need a CLI build that ships them (DailybotHQ/cli#129 on `plan__next`, or a release **after** `3.26.2` that includes that PR). The pack floor for the rest of Plan remains `dailybot-cli >= 3.25.0`. If a leaf is missing, run `dailybot upgrade` (or install from that branch) before inventing alternate command names.

Contract strings — prefer these exact invocations (full flags in [commands.md](commands.md) § Agent-first T5 leaves):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new section tells agents to use “full flags in commands.md § Agent-first T5 leaves”, but that section does not exist in .agents/skills/dailybot/tasks/commands.md (grep count 0). The command inventory tables there still omit board reorder, board move-preview, board view create, project reorder, project view create, member update, tasks board, plan label *, and plan views *.

Failure mode: agents following the skill will open commands.md for flag contracts, find nothing, and invent alternate invocations — the opposite of the “prefer these exact invocations” goal. Either land the T5 commands.md section in this PR (or the linked companion skill PR before merge), or drop the cross-reference until that section exists.

Comment on lines +217 to +221
_MEMBER_DETAIL_FIELDS: list[tuple[str, str]] = [
("UUID", "uuid"),
("User UUID", "user_uuid"),
("Team UUID", "team_uuid"),
("Role", "role"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

board_member_update help states board membership has no role column (org roles + visibility are the access model), yet _MEMBER_DETAIL_FIELDS always renders a Role row. Human non-JSON output will show a blank Role line on every inspect.

Drop ("Role", "role") from _MEMBER_DETAIL_FIELDS here (and the twin in project.py) unless the grant row actually returns a meaningful role.

Comment on lines +429 to +431
# Reuse board snapshot renderer when shape matches; otherwise detail panel.
if isinstance(data, dict) and (data.get("groups") is not None or data.get("board") is not None):
from dailybot_cli.display import print_board_snapshot

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

print_board_snapshot and print_tasks_detail_panel are already imported at the top of tasks.py (lines 58 and 65). The deferred imports inside tasks_board add noise without avoiding a cycle. Use the module-level names directly.

Comment on lines +150 to +151
class TestCommandWiring:
def test_board_reorder_json(self, runner: CliRunner, auth_client: MagicMock) -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both board reorder and project reorder raise UsageError when both anchors are passed, but TestCommandWiring only exercises the happy JSON path. A single runner.invoke(..., "--before", …, "--after", …) asserting non-zero exit would lock the local guard that mirrors reorder_anchor_invalid.

@github-actions github-actions Bot added the pr-reviewed Passed AI code review label Oct 5, 2026
@xergioalex
xergioalex merged commit edcf7e3 into main Oct 5, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-reviewed Passed AI code review Ready Trigger AI code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants