Skip to content

feat: add tag_session MCP tool for agent-driven session tagging - #3469

Closed
fanhongy wants to merge 1 commit into
kirodotdev:mainfrom
fanhongy:feat/tag-session-tool
Closed

feat: add tag_session MCP tool for agent-driven session tagging#3469
fanhongy wants to merge 1 commit into
kirodotdev:mainfrom
fanhongy:feat/tag-session-tool

Conversation

@fanhongy

@fanhongy fanhongy commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Problem / Motivation

The dashboard has a full kanban board with status tags (Planned, ToDo, Implementation, Review, Done) and sidebar columns, but agents have no way to tag their own sessions. Users must manually drag session cards between columns, which is tedious when running many parallel sessions.

Why it matters

Power users running 10+ concurrent sessions can't keep their kanban board current without hand-curating it. The board goes stale and loses its value as a workflow tracker. An agent that could move its own session between columns as work progresses (implementation → review → done) would keep the board accurate with zero manual effort.

What changed

Adds a tag_session MCP tool to the kirocrew-core server that assigns status/label tags to a session slot via the existing dashboard tag API.

Motivation → approach → change:

  • Goal: let an agent set its session's kanban column programmatically.
  • Approach: a thin MCP tool over the existing PUT /api/chat/slots/{slot}/tags endpoint, resolving the caller's own slot by default and enforcing forward-only lifecycle advancement for status tags.
  • Built:
    • TAG_SESSION_SCHEMA in validation.py (tag, optional slot_key, optional force).
    • tag_session handler in mcp_tools/sessions.py + registration in HANDLERS.
    • Case-insensitive tag-name resolution (agents know names, not internal hex IDs).
    • Status tags advance forward only by default (planned→todo→implementation→review→done); force=true overrides. Non-status tags are added alongside existing tags.
    • Identity resolved via _resolve_session_key_strict() (fail-closed for subagents) with the dashboard: slot-key prefix — matching the sibling session-mutating tools (monitor_start, autonudge_stop).

Tests

test/test_mcp_sessions_tag.py — 10 tests covering:

  • Status advancement (happy path)
  • Regression blocked without force; allowed with force=true
  • Unknown tag name → error listing available tags
  • Case-insensitive matching
  • Non-status tag added alongside existing status tag
  • Non-status tag already present → no-op
  • Slot not found → error
  • Default-to-own-slot resolution (strips dashboard: prefix)
  • Subagent with no identity + no explicit slot_key → fail-closed error

Manual verification

N/A — unit coverage sufficient. The underlying PUT /api/chat/slots/{slot}/tags endpoint is already production-proven (the dashboard UI drag-drop uses the same path), and the handler is fully exercised by mocked-API unit tests.

Related Issues

Fixes #3456

Checklist

  • Single commit with a Conventional Commits title (feat: ...)
  • Existing tests pass and new tests added for new functionality
  • Self-review completed; code follows project style guidelines
  • Documentation updated (if applicable) — N/A, tool is self-documenting via its MCP schema description
  • No secrets, credentials, or internal references in the diff

@fanhongy
fanhongy requested a review from a team as a code owner August 14, 2026 03:12
@github-actions github-actions Bot added fork Pull request from a fork (external contributor) readiness: action required A blocking check or review needs attention labels Aug 14, 2026
@fanhongy
fanhongy force-pushed the feat/tag-session-tool branch from 6f0437a to a18ff62 Compare August 14, 2026 03:17
@fanhongy fanhongy changed the title feat: add tag_session MCP tool for agent-driven session lifecycle tagging feat: add tag_session MCP tool for agent-driven session tagging Aug 14, 2026
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 14, 2026
@fanhongy
fanhongy force-pushed the feat/tag-session-tool branch from 32ef17d to b9e45ad Compare August 14, 2026 09:29
@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Aug 14, 2026
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review (fork) — 🔴 changes requested (blocking)

Reviewed 11c0e6a06a7ed305870b2f48e4be1d6587bf94a8 via the fork AI-review pipeline; updated in place on each push.

BLOCKING -- src/kiro_crew/mcp_tools/sessions.py:471 -- Explicit slot keys bypass caller-session authorization
slot_key = args.get("slot_key") or ""
Unidentified subagent + known parent slot key -> strict identity refusal is skipped -> another session is retagged.
Fix: Reject unresolved identities, require the target to match the verified caller slot, and pass session_key to _get/_put.

BLOCKING -- src/kiro_crew/mcp_tools/sessions.py:550 -- Stale updates can regress or erase concurrent tag changes
put_resp = mcp_core._put(f"/api/chat/slots/{slot_key}/tags", {"tags": new_tag_ids})
Initial status read -> concurrent drag advances the slot -> stale full-list PUT overwrites it, bypassing advancement-only behavior.
Fix: Remove tag_session until resolution, advancement checking, merging, and persistence occur atomically under the gateway tag lock.

[BLOCK-MERGE] 11c0e6a
[GPT-REVIEWED] 11c0e6a

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

First Principles Review (Fable 5, fork) — 🟡 CONCERNS

Advisory premise-level review of 11c0e6a06a7ed305870b2f48e4be1d6587bf94a8 via the fork AI-review pipeline — why this exists and whether the shipped surface is the smallest honest version. Updated in place on each push; does not block merge.

I've reviewed the contract, the intent file, the patch, and the relevant base code (chat_tags.py, mcp_tools/sessions.py, mcp_core.py, dashboard/state.py). Here is the review.

First-Principles-Verdict: CONCERNS

The tool earns its place; the advancement-only/force machinery guards a harm the system's other two tag-write paths deliberately allow, on a field that isn't a lifecycle order.

What this change ships

Intent: let an agent move its own session between kanban columns instead of the user dragging it — an ADDITION.

  1. Agent can tag/move its own session between board columns — justified (stated harm, no existing MCP path; grepped mcp_tools/ for tag: 0 tools).
  2. Agent can retag ANY session via slot_key — declared, but generalized beyond the named harm ("tag their own sessions").
  3. Backward status moves are refused — inherited requirement; no reported defect quoted.
  4. force flag to override item 3 — exists only to unlock item 3.
  5. Non-status tags add without stripping status — justified (mirrors api_chat_slot_drop semantics).
  6. Subagent with no identity fails closed — undeclared, justified (subagent-retags-parent hazard is a named boundary).
  7. Tool description hardcodes the seed lifecycle names — undeclared; vocabulary is user-editable.

Watch

  • "Advancement-only … prevents accidental regression": that invariant exists nowhere else. Grepped the tag-write paths — api_chat_slot_tags (chat_tags.py:380) and api_chat_slot_drop (chat_tags.py:640) both regress freely, so 2 of 3 writers ignore the rule; a user's drag can undo it silently. It also treats tag order as lifecycle order, but order is display order, user-reorderable via PATCH /api/chat/tags/{id} (chat_tags.py:218) and assigned len(state._tags) on create — reordering or creating tags silently rewrites the "lifecycle".
  • Description bullet "planned->todo->implementation->review->done" and the same string in the tool description bake in the default seed vocabulary (state.py:4308) that users can rename or delete — the advertised contract drifts from reality on first edit.
  • Description says "9 tests"; the file ships 10 — the subagent fail-closed test is undeclared (keep it; it pins item 6).

Subtractions

  • Drop the advancement check, the force field (schema + TAG_SESSION_SCHEMA + description text), and the order-comparison block (patch lines 114–136) — the tool becomes lookup + PUT, matching what every other tag writer enforces: nothing.
  • Drop the hardcoded lifecycle example from the tool description; the unknown-tag error already lists the live vocabulary.
  • Shrink slot_key — defer until a caller that must tag a foreign session exists; own-session-only removes the entire cross-session surface the strict-resolver comment worries about.

[FIRST-PRINCIPLES-REVIEWED] 11c0e6a

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review (fork) — ✅ no blocking findings

Reviewed 11c0e6a06a7ed305870b2f48e4be1d6587bf94a8 via the fork AI-review pipeline; updated in place on each push.

Review details

Based on my falsification pass:

  • Candidate 1 (read-modify-write race): The GET-then-PUT-full-replace is the endpoint's own contract (api_chat_slot_tags at chat_tags.py:402 does a full replace, and the frontend does the same GET-modify-PUT). This is a single-user tool; the concurrent-writer condition ("user drags a card while the agent tags") is a "could" — not an input that reliably occurs. No concrete-in-practice trigger + observable loss. Drops at (a).

  • Candidate 2 (workspace scoping): The read siblings scope conversation history by workspace (_caller_workspace filters search_chat_history/list_sessions). Slots are global dashboard/kanban board state, not workspace-partitioned — there is no slot workspace-isolation contract to break, and within the single-OS-user trust boundary cross-project slot access is not a boundary crossing. No observable wrong outcome. Drops at (c).

  • Candidate 3 (t["id"] KeyError): create_tag_definition (chat_tags.py:126) always sets id via uuid; the vocabulary is app-authored. Firing requires assuming externally-corrupted tags.json — code/state not established. Drops at (a).

None survive falsification at 80+.

No findings.

[OPUS-REVIEWED] 11c0e6a

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5, fork) — 🟡 CONCERNS

Advisory design-level review of 11c0e6a06a7ed305870b2f48e4be1d6587bf94a8 via the fork AI-review pipeline — updated in place on each push; does not block merge.

Based on my review of the patch, the base code it integrates with (chat_tags.py, mcp_core.py, session_directive.py, mcp.md), here's my design assessment.

Key facts I verified:

  • Status-tag order is set to len(state._tags) at creation (a global insertion/display index across all tags), and is freely mutable via the PATCH reorder route — it is not a lifecycle field.
  • The dashboard's own equivalent action (dragging a card between columns, api_chat_slot_tags) has no regression guard — it reassigns freely.
  • There is no seeded status-tag vocabulary; users author their own names/order. The tool's hardcoded planned->todo->implementation->review->done is illustrative, not enforced by the data.
  • The direct strict-resolve + PUT shape is actually one of the two documented-correct patterns in mcp.md ("POST to a gateway endpoint that owns the state"), and it correctly uses _resolve_session_key_strict(). So the architecture is within bounds.

Design-Verdict: CONCERNS

The advancement-only guard is built on the tag order field, which is not a lifecycle sequence — so it will block legitimate transitions the human can already do freely, re-creating the staleness this PR sets out to fix.

Watch

  • Advancement blocking keys off order, a global creation/display index (freely reorderable via PATCH), not a lifecycle rank. For any vocabulary not authored in strict lifecycle order — or after a column reorder — new_order < max_current_order misfires and the agent gets "regression blocked" on a valid move. The equivalent human drag (api_chat_slot_tags) has no such guard, so the tool is more restricted than the action it automates; agents only discover force=true after failing, and until they retry the board stays stale.

Suggestions

  • Reconsider whether advancement-only should be the default at all: mirroring the dashboard's guard-free reassignment (set the tag, optionally warn on regression) is simpler and matches the human semantics the tool is meant to replicate.
  • The default-slot branch maps a non-dashboard session_key (e.g. slack:…) straight to slot_key, so channel sessions fail with a confusing "Slot '…' not found" instead of the clear "only works from a dashboard session" message the directive tools give.

[DESIGN-REVIEWED] 11c0e6a

…ging

Adds a new `tag_session` tool to the kirocrew-core MCP server that lets
agents assign status/label tags to dashboard session slots, moving them
between kanban board columns programmatically.

Features:
- Case-insensitive tag name resolution
- Status tags advance forward only (planned->todo->implementation->review->done)
  with optional force override for regression
- Non-status tags can be added alongside status tags
- Defaults to tagging the agent's own session; accepts explicit slot_key
- SEL audit logging

Resolves kirodotdev#3456
@fanhongy
fanhongy force-pushed the feat/tag-session-tool branch from b9e45ad to 11c0e6a Compare August 14, 2026 10:29
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Aug 14, 2026
@fanhongy

Copy link
Copy Markdown
Contributor Author

Review dispositions — 11c0e6a0 (fixes b9e45ada)

GPT 5.6 Review

BLOCKING 1 — lenient resolver on mutating path (sessions.py:467)
Fixed in 11c0e6a0: replaced _resolve_session_key() with _resolve_session_key_strict(). Subagent without KIROCREW_SESSION_KEY now gets empty string → fail-closed error message instead of PID-walking to parent. Matches monitor_start/autonudge_stop pattern.

BLOCKING 2 — stale read-modify-write PUT
Rebutted: the dashboard UI drag-drop uses the same PUT /api/chat/slots/{slot}/tags full-replacement pattern (chat_tags.py:380). Both the UI and this tool are single-user local clients on the same machine — the race window is a user dragging a card at the exact millisecond the agent PUTs. A server-side atomic tag-mutate endpoint would eliminate this, but it is out of scope for this PR and would require changing the existing dashboard API contract. Filed as a note in #3456.

FINDING — dashboard_ vs dashboard: prefix
Fixed in 11c0e6a0: changed to session_key.removeprefix("dashboard:") matching the live colon-spelled key format. Tests updated to use SESSION_KEY = "dashboard:chat-46-1786668000" and mock _resolve_session_key_strict.

Opus 4.8 Review

BLOCKING — lenient resolver subagent→parent hazard (sessions.py:464)
Fixed in 11c0e6a0: same fix as GPT BLOCKING 1 above. Now uses _resolve_session_key_strict() with fail-closed when empty and no explicit slot_key. New test test_tag_session_subagent_no_identity verifies the fail-closed path.

Design Review (Fable 5)

BLOCK — own-slot resolution wrong twice
Fixed in 11c0e6a0: both issues addressed (strict resolver + colon prefix).

Watch — advancement guard keys on reorderable order field
Accepted-and-deferred: valid observation that order is a display-reorderable field shared with non-status tags. For the current use case (5 fixed status tags configured by the user), this is a pragmatic UX guard not a security invariant. If the vocabulary is reordered, lifecycle direction changes — this is acceptable for a single-user desktop app. A server-side lifecycle ordering (separate from display order) would be the proper fix if this tool sees multi-user use. No issue filed — too speculative.

Watch — read-modify-write race
Same disposition as GPT BLOCKING 2 above (rebutted, parity with UI).

First Principles Review (Fable 5)

BLOCK — own-session binding duplicates session_directive
Rebutted: tag_session performs a direct HTTP PUT to a known endpoint, not a session-directive that a downstream consumer applies. The session_directive pattern (encode → chat_runner applies) is for effects that need the session-aware consumer to resolve identity and execute. Tag assignment is a simple REST call the MCP tool can make directly with verified identity — making it a directive would add indirection for no benefit and require a new directive handler in chat_runner. The strict resolver gives the same fail-closed guarantee.

BLOCK — drop force and advancement guard (zero option)
Rebutted: the advancement guard is a UX safety net preventing accidental regression (e.g. a stale cron tagging "planned" on a session that is already "done"). force=true costs nothing when unused and provides a documented escape hatch. Removing both is a false economy — the cost of including them is ~10 lines; the cost of accidentally regressing a board full of sessions is user frustration and manual cleanup.

Watch — drop slot_key
Rebutted: orchestrating agents tag other sessions they spawned work into (e.g. parent marks a worker session "done" after synthesizing results). This is the documented use case in #3456. The explicit slot_key path bypasses the strict resolver entirely (no identity resolution needed when the target is explicit), so it carries no subagent hazard.

@github-actions github-actions Bot removed the readiness: action required A blocking check or review needs attention label Aug 14, 2026
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Aug 14, 2026
@fanhongy

Copy link
Copy Markdown
Contributor Author

GPT 5.6 — disposition for 11c0e6a0 (repeat findings from prior round)

Both findings below are repeats of issues already dispositioned in the prior round on b9e45ada. The code was changed to address the legitimate subset (strict resolver), and the design-level concerns were rebutted. The GPT reviewer re-raised them without acknowledging the prior disposition.

  • BLOCKING 1 — "Explicit slot keys bypass caller-session authorization" (sessions.py:471)
    Rebutted (proportionality): slot_key is an intentional parameter documented in the tool schema and issue Expose session tagging as an MCP tool for agent-driven lifecycle tracking #3456. Its purpose is orchestration: a parent agent tags worker sessions it spawned. The repo trust boundary is single-OS-user (same UID cross-session is in-scope), same as the existing dashboard drag-drop via PUT /api/chat/slots/{slot}/tags. The strict resolver guards the default path; the explicit path is intentionally open. Removing it would break the documented use case. Opus 4.8 Review explicitly cleared this in its analysis: "The repo trust boundary is the single OS user (same-UID cross-session is in-scope), and the schema documents slot_key as an intentional cross-session target. Not a defect. Drop."

  • BLOCKING 2 — "Stale updates can regress or erase concurrent tag changes" (sessions.py:550)
    Rebutted (proportionality): The existing dashboard tag assignment uses the identical PUT /api/chat/slots/{slot}/tags full-replacement pattern (chat_tags.py:380). Both UI drag-drop and this MCP tool are single-user clients on a local desktop app. The race window (user drags a card at the exact millisecond the agent PUTs) is theoretical in this single-user context and cannot be fixed without a new server-side atomic endpoint — which is a separate architectural change, not a fix for this PR. The correct home for this improvement is a server-side PATCH /api/chat/slots/{slot}/tags/add endpoint, filed as a note in Expose session tagging as an MCP tool for agent-driven lifecycle tracking #3456.

Both Opus 4.8 and Design Review passed on this SHA with no blocking findings.

@iamwhatever iamwhatever added the needs-pr-triage PR scanner: awaiting automated triage label Aug 20, 2026
@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## What changed

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

2 similar comments
@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## What changed

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@bolichen97

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## What changed

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@iamwhatever

Copy link
Copy Markdown
Collaborator

🤖 Kiro Crew [operator: iamwhatever]: This PR has been inactive since 2026-08-15. I reviewed the blockers, but they hinge on a decision only a maintainer can make rather than a mechanical fix:

The only blocking gate is GPT 5.6 Review (2 BLOCKING findings). Every other check passes — Opus 4.8 cleared the identical code with no blocking findings, and Design Review / First Principles are advisory CONCERNS (non-blocking). You've already posted thorough dispositions rebutting both GPT findings on proportionality / trust-boundary grounds. So this is a reviewer standoff, not a code defect with an obvious fix:

  • slot_key cross-session tagging (GPT BLOCKING 1): GPT wants explicit slot_key rejected unless it matches the verified caller slot. You (and Opus) argue it's an intentional orchestration parameter, safe under the single-OS-user trust boundary and at parity with the existing dashboard drag-drop. Decision needed: accept the intentional slot_key surface, or narrow it to own-session-only.
  • Read-modify-write PUT race (GPT BLOCKING 2): GPT wants the tool removed until tag mutation is atomic under the gateway lock. You argue it mirrors the existing UI's full-replace PUT and the true fix is a new server-side atomic endpoint (out of scope, noted in Expose session tagging as an MCP tool for agent-driven lifecycle tracking #3456). Decision needed: ship at parity with the current UI contract, or block on the atomic-endpoint work first.

Both of GPT's requested fixes would change this PR's design direction or expand its scope, which the automated pipeline won't do. A maintainer needs to either uphold your rebuttals (and override the GPT gate) or ask you to make one of the design changes above. When that direction is set, the pipeline will re-assess on its next cycle.

@iamwhatever iamwhatever added needs-author-decision PR blocked on author input and removed needs-pr-triage PR scanner: awaiting automated triage labels Aug 20, 2026
@NicholasRBowers

Copy link
Copy Markdown
Contributor

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## What changed

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

1 similar comment
@dwu96

dwu96 commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## What changed

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@github-actions github-actions Bot added the merge conflict Branch has merge conflicts with its base — author must resolve before merge label Aug 23, 2026
@bolichen97
bolichen97 enabled auto-merge (squash) August 24, 2026 07:00
@bolichen97

Copy link
Copy Markdown
Collaborator

Closing — the same capability as #7779, which is the governed implementation

Verified relationship: functional overlap

Both PRs are open (pr/3469 = 11c0e6a, pr/7779 = 194897b) and origin/main 1a765b8 has neither surface: sessions.py HANDLERS still holds exactly three read tools, DIRECTIVE_TOOLS has no chat_tag, and the only 'tag_session' token on main is prose in api_chat_tag_delete's docstring. So both add the same previously-absent capability - an agent-callable MCP surface that sets its own dashboard session's mutually-exclusive kanban workflow tag. On the shipped vocabulary they are behaviourally interchangeable: state.py:6291 _DEFAULT_TAGS seeds five status tags whose ids equal their lowercased names, so tag_session(tag='review') and chat_tag(set_state='review') land the same board state through different plumbing. They are not merely co-located: #7779's whole premise is that agent tag writes pass one policy chokepoint (chat_tags.agent_tag_policy, consulted only inside _apply_chat_tag), while #3469 writes over PUT /api/chat/slots/{slot}/tags - the human/UI endpoint, which #7779 leaves untouched and cannot gate without breaking the human drag path. Ship both and an agent refused 'customer' by chat_tag simply calls tag_session(tag='Customer'); the governance #7779 exists to add is defeated by #3469's presence, so only one can land. #7779 is the right survivor: 11 files / 743 adds including the in-lock atomic write reusing tags_write_lock + validate_folder_tag_ids + save_slot_off_loop with the entry-time expected_history_key pin that main itself just hardened (fef7e36, #7714), SEL chat.self_tag, headless-caller refusal, a read surface, 22+ tests, doc updates, and three answered review rounds dated 2026-09-02; #3469 is 3 files / 307 adds doing an unlocked GET/GET/PUT read-modify-write, has been inactive since 2026-08-15, and its two GPT BLOCKING findings (slot_key bypasses caller-session authorization; stale full-list PUT) were rebutted rather than fixed - the bot itself calls it a reviewer standoff awaiting a maintainer.

Carry this over first

This closure is about redundancy, and these items are the exception: they are not on main and not in the surviving PR, so they need a home before the topic is finished. Please don't let them go with the branch.

Before closing #3469: (1) carry the still-open #3456 ask for a foreign/named-session target (tag_session's optional slot_key, src/kiro_crew/mcp_tools/sessions.py + FieldSpec('slot_key') in validation.py) onto #7774's v2 scope as a GOVERNED target argument on the chat_tag directive - not as a second HTTP writer; the GPT blocking on #3469 is the design constraint to carry with it. (2) Fix #7779's id-only addressing with #3469's name resolution: in _apply_chat_tag's vocab_by_lower, also index (t.get('name') or '').lower() -> t, and have the unknown_tag refusal enumerate the live vocabulary the way tag_session's "No tag named '{x}' found (case-insensitive). Available: ..." does - otherwise a user-created status tag (uuid id, agent-writable by default policy) is unreachable, and relax _TAG_ID_RE enough to carry a spaced label. (3) Record, on #3456 rather than in code, that its 'advancement-only unless forced' ask has no correct implementation yet: #3469's guard compares tag['order'], a user-reorderable display index assigned len(state._tags) at creation, so it needs a real lifecycle rank first. (4) Note #3469's own #3456 finding that a server-side atomic tag-mutate endpoint is the proper fix - #7779's in-lock applier already discharges it for the agent path. Nothing else in #3469 (mutual exclusivity, non-status add, self-slot resolution, SEL audit, its 10 tests) is uncovered by #7779.

Current state

Neither side has merged - the issue/PR reference check lists 3469 and 7779 both as open PRs, both cited issues (#3456, #7774) are open ISSUEs with no code, and the landed-commit index for main contains no landed agent tag-write work (the nearest neighbours are #5432 folders-carry-tags and #7714's expected_history_key pin, which only harden the path #7779 reuses). So no superseded by work already on main question arises: the live question is still which of the two designs survives, and main having neither surface is what makes the pair redundant rather than each filling a different gap.


From a repository-wide duplicate/overlap audit of every pull request open against main (2026-09-02, 330 PRs, one reviewer per PR). Each PR was read as its full merge-base diff plus its description and every comment and review, then compared against each candidate PR's own diff and against origin/main at 1a765b88ceb7. Findings that implied a closure were re-adjudicated independently, including an adversarial pass whose only job was to refute them; the reasoning above is what survived. If it is wrong, reopening costs nothing — please say so, and treat the reasoning rather than the outcome as the thing to correct.

@bolichen97 bolichen97 closed this Sep 2, 2026
auto-merge was automatically disabled September 2, 2026 20:09

Pull request was closed

@github-actions github-actions Bot removed the readiness: action required A blocking check or review needs attention label Sep 2, 2026
@bolichen97

Copy link
Copy Markdown
Collaborator

Open PR relationship audit

This is a consolidated, point-in-time code-level audit note. It compares complete merge-base diffs and current/merged code; it does not treat a shared topic as duplication or partial coverage as completion.

Relationship findings

  • PR #7779 is OVERLAPPING relative to this PR. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #7779: MERGE_DISCUSSION. This PR is the surviving implementation of the closed PR #3469; no further deduplication is needed against it. Files: src/kiro_crew/dashboard/session_directive_apply.py.

No PR, Issue, label, branch, or review state was changed by the relationship-note portion of this audit.

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

Labels

fork Pull request from a fork (external contributor) merge conflict Branch has merge conflicts with its base — author must resolve before merge needs-author-decision PR blocked on author input

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose session tagging as an MCP tool for agent-driven lifecycle tracking

5 participants