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
79 changes: 79 additions & 0 deletions .agents/skills/workplan-task-ops/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: workplan-task-ops
description: Manage SPECS/Workplan.md task operations for this repository. Use when you need to add a new task entry with the canonical template, pick the next actionable task, or mark a task as completed while keeping selector state in sync.
---

# Workplan Task Ops

Manage task lifecycle operations in `SPECS/Workplan.md` using the repository conventions.

## Required Inputs

Collect these before running any operation:
- Target task ID (or task type and parent context if creating a new task)
- Target phase/backlog section in `SPECS/Workplan.md`
- Current status marker (`⬜️` open or `✅` completed)

Use these sources of truth:
- `SPECS/TASK_TEMPLATE.md` for task entry format and markers
- `SPECS/Workplan.md` for the actual task list
- `scripts/pick_next_task.py` for next-task selection and completion state updates

## Operation 1: Add Task

1. Determine task ID convention before editing:
- Phase task: `P{phase}-T{n}`
- Follow-up task: `FU-{parent/topic}-{n}`
- Bug task: `BUG-T{n}`

2. Place the task in the correct section of `SPECS/Workplan.md`.

3. Copy the open-task block from `SPECS/TASK_TEMPLATE.md` and fill all fields:
- Header with `⬜️` marker
- `Description`, `Priority`, `Dependencies`, `Parallelizable`
- `Outputs/Artifacts`
- `Acceptance Criteria` with unchecked boxes

4. Validate task entry quality:
- ID is unique in workplan
- Dependencies reference existing tasks or `none`
- Acceptance criteria are testable

## Operation 2: Pick Next Task

1. Run:
```bash
python3 scripts/pick_next_task.py
```

2. Read the suggested task and dependency statuses.

3. Confirm the suggestion is still open in `SPECS/Workplan.md` (`⬜️`) and not archived.

4. Update `SPECS/INPROGRESS/next.md` using the output template in `SPECS/COMMANDS/SELECT.md`.

## Operation 3: Mark Task Completed

1. Confirm completion evidence exists (implementation done, validation/review state consistent).

2. Update the task block in `SPECS/Workplan.md`:
- Change header marker from `⬜️` to `✅`
- Add or update `Status` line with date when applicable
- Check completed acceptance criteria (`[x]`)

3. Persist completion for selector state:
```bash
python3 scripts/pick_next_task.py --done <TASK_ID>
```

4. Verify follow-up selection:
```bash
python3 scripts/pick_next_task.py
```

## Guardrails

- Do not invent IDs that break existing conventions.
- Do not mark a task complete without matching acceptance evidence.
- Keep task formatting aligned with `SPECS/TASK_TEMPLATE.md`.
- Keep edits scoped to task-tracking files unless explicitly requested otherwise.
4 changes: 4 additions & 0 deletions .agents/skills/workplan-task-ops/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Workplan Task Ops"
short_description: "Add, pick, and complete Workplan tasks"
default_prompt: "Use $workplan-task-ops to add a new task entry, pick the next task, or mark a task as completed in SPECS/Workplan.md."
1 change: 1 addition & 0 deletions SPECS/COMMANDS/ARCHIVE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Scan for completed tasks and archive them from `SPECS/INPROGRESS/` to `SPECS/ARC
- Clear current task block
- Add entry to "Recently Archived" section
- Suggest next tasks from workplan
- Ensure the archived task status in `SPECS/Workplan.md` follows [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md) (`✅` marker)

4. **For non-task artifacts** (code reviews, reports):
```bash
Expand Down
5 changes: 3 additions & 2 deletions SPECS/COMMANDS/FLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Choose the next task from the workplan.

**Actions:**
- Read `SPECS/Workplan.md` for available tasks
- Use [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md) as the canonical status/entry format reference
- Run `python scripts/pick_next_task.py` or manually select
- Update `SPECS/INPROGRESS/next.md` with chosen task metadata

Expand Down Expand Up @@ -101,7 +102,7 @@ Move completed task to archive (run periodically or at milestones).
- Execute [`ARCHIVE`](ARCHIVE.md) command
- Verify task moved to `SPECS/ARCHIVE/{TASK_ID}_{TASK_NAME}/`
- Confirm `next.md` updated
- Mark task as ✅ in `SPECS/Workplan.md`
- Mark task as ✅ in `SPECS/Workplan.md` using [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md) conventions

**Commit via [`COMMIT`](PRIMITIVES/COMMIT.md):**
```
Expand Down Expand Up @@ -131,7 +132,7 @@ Create subtasks for issues discovered during review.

**Actions:**
- Execute [`FOLLOW_UP`](PRIMITIVES/FOLLOW_UP.md) command
- Add new tasks to `SPECS/Workplan.md` for actionable items
- Add new tasks to `SPECS/Workplan.md` for actionable items using [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md)

**Commit via [`COMMIT`](PRIMITIVES/COMMIT.md):**
```
Expand Down
2 changes: 1 addition & 1 deletion SPECS/COMMANDS/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ PLAN turns the selected task into a self-contained, implementation-ready PRD ins
2. Each subtask must have inputs, outputs, and verification steps. Use tables, bullet lists, or numbered steps for clarity.
3. Include a "Notes" section for docs to update once the task is complete.
4. Keep the PRD concise (200–400 words per major section) but detailed enough that someone following it never needs additional clarification.
5. Save the PRD and update `SPECS/Workplan.md` if the task status or references need a note.
5. Save the PRD and update `SPECS/Workplan.md` if the task status or references need a note, using [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md) conventions.

## Output

Expand Down
7 changes: 5 additions & 2 deletions SPECS/COMMANDS/PRIMITIVES/FOLLOW_UP.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ For each new task, assign an appropriate ID following the workplan convention:

### 3. Add Tasks to Workplan

Update `SPECS/Workplan.md` with new task entries following the existing format:
Update `SPECS/Workplan.md` with new task entries using the canonical template in
[`SPECS/TASK_TEMPLATE.md`](../../TASK_TEMPLATE.md):

```markdown
#### P2-T5: New Task Description
#### ⬜️ P2-T5: New Task Description
- **Description:** Brief description
- **Priority:** P1
- **Dependencies:** P2-T1
- **Parallelizable:** yes/no
- **Outputs/Artifacts:**
- Updated file(s) or artifact(s)
- **Acceptance Criteria:** What needs to be true
```

Expand Down
5 changes: 3 additions & 2 deletions SPECS/COMMANDS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This folder holds the command prompts that orchestrate the mcpbridge-wrapper doc

Additional helpers live in `PRIMITIVES/` (toolchain, commits, doc updates, archive maintenance).
Main tasks tracker: `SPECS/Workplan.md`.
Task entry format: [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md).

## Workflow

Expand Down Expand Up @@ -58,13 +59,13 @@ SPECS/

## Quick Start

1. Run `SELECT` to choose the highest-priority task from `SPECS/Workplan.md` and write `SPECS/INPROGRESS/next.md`.
1. Run `SELECT` to choose the highest-priority task from `SPECS/Workplan.md` and write `SPECS/INPROGRESS/next.md` (task status/format in [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md)).
2. Run `PLAN` to produce the PRD in `SPECS/INPROGRESS/{TASK_ID}_{TASK_NAME}.md`.
3. Run `EXECUTE` to follow the PRD, run tests/linting, and commit.
4. Repeat. When a task finishes, move it to `SPECS/ARCHIVE/` via ARCHIVE.

## Notes

- Keep `SPECS/INPROGRESS/` slim—only one task should be active at a time.
- Document completed work in `SPECS/ARCHIVE/` (PRDs stay for reference) and update `SPECS/Workplan.md` when needed.
- Document completed work in `SPECS/ARCHIVE/` (PRDs stay for reference) and update `SPECS/Workplan.md` when needed, using [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md).
- This is a Python project (not Swift). Use pytest, ruff, and mypy for quality gates.
1 change: 1 addition & 0 deletions SPECS/COMMANDS/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Apply a structured code review to any set of commits or staged changes. This com

6. **Create backlog tasks** for actionable findings (if any):
- Extract items from the review report and add them to `SPECS/Workplan.md`.
- Format new or updated task entries per [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md).
- Assign new IDs consistent with the workflow (follow `PRIMITIVES/FOLLOW_UP.md` conventions).
- If no actionable issues exist, explicitly note that FOLLOW-UP is skipped.

Expand Down
5 changes: 3 additions & 2 deletions SPECS/COMMANDS/SELECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ Choose the next mcpbridge-wrapper task to work on without re-planning. SELECT ke
## Inputs

- `SPECS/Workplan.md` as the main tasks tracker (phases, priorities, status).
- [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md) as the canonical task status/entry format.
- `SPECS/INPROGRESS/next.md` (if it exists) to round out what is already active.
- Notes in `AGENTS.md` for related constraints.

## Algorithm

1. Gather outstanding items from `SPECS/Workplan.md`. Assign each a priority tag (P0, P1, P2) and note dependencies.
1. Gather outstanding items from `SPECS/Workplan.md` using status markers defined in [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md). Assign each a priority tag (P0, P1, P2) and note dependencies.
2. Filter candidates to those:
- Not marked complete in the workplan.
- Dependencies already satisfied or documented with blocking tasks.
Expand Down Expand Up @@ -52,4 +53,4 @@ Run the PLAN command to generate the implementation-ready PRD.

- Keep `next.md` slim; no checklists, acceptance criteria, or code samples.
- Always reference the workplan entry so reviewers understand why this task was chosen.
- If no candidates exist, report that the workplan is empty (and consider adding new entries in `SPECS/Workplan.md`).
- If no candidates exist, report that the workplan is empty (and consider adding new entries in `SPECS/Workplan.md` using [`SPECS/TASK_TEMPLATE.md`](../TASK_TEMPLATE.md)).
62 changes: 62 additions & 0 deletions SPECS/TASK_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Workplan Task Template

Canonical template for adding tasks to `/Users/egor/Development/GitHub/XcodeMCPWrapper/SPECS/Workplan.md`.

## Status Markers

- `⬜️` = open task (not completed)
- `✅` = completed task

Use the marker at the start of the task header (preferred), for example:

```markdown
#### ⬜️ P12-T4: Implement example task
```

## Task ID Conventions

- Phase task: `P{PHASE}-T{N}` (example: `P12-T4`)
- Follow-up task: `FU-{PARENT_OR_TOPIC}-{N}` (example: `FU-P12-T1-5`)
- Bug task: `BUG-T{N}` (example: `BUG-T8`)
- Rebuild task: `REBUILD-{TOPIC}` (example: `REBUILD-P10-T1`)

## Open Task Template

```markdown
#### ⬜️ {TASK_ID}: {TASK_NAME}
- **Description:** {What must be done and why}
- **Priority:** P0|P1|P2|P3
- **Dependencies:** none|{TASK_ID_1}, {TASK_ID_2}
- **Parallelizable:** yes|no
- **Outputs/Artifacts:**
- {File/path/output 1}
- {File/path/output 2}
- **Acceptance Criteria:**
- [ ] {Verifiable outcome 1}
- [ ] {Verifiable outcome 2}
```

## Completed Task Template

Use this when archiving/marking a task complete:

```markdown
#### ✅ {TASK_ID}: {TASK_NAME}
- **Status:** ✅ Completed ({YYYY-MM-DD})
- **Description:** {What was implemented}
- **Priority:** P0|P1|P2|P3
- **Dependencies:** none|{TASK_ID_1}, {TASK_ID_2}
- **Parallelizable:** yes|no
- **Outputs/Artifacts:**
- {Delivered artifact 1}
- {Delivered artifact 2}
- **Acceptance Criteria:**
- [x] {Satisfied criterion 1}
- [x] {Satisfied criterion 2}
```

## Notes

- Keep task headers unique by ID.
- Prefer explicit dependencies (`none` or comma-separated IDs).
- Use checklist items in acceptance criteria so verification is unambiguous.
12 changes: 6 additions & 6 deletions SPECS/Workplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -1972,7 +1972,7 @@ Phase 9 Follow-up Backlog

**Intent:** Introduce a long-lived broker process that owns the Xcode bridge connection and multiplexes multiple MCP clients through one upstream session.

#### P13-T1: Design persistent broker architecture and protocol contract
#### P13-T1: Design persistent broker architecture and protocol contract
- **Status:** ✅ Completed (2026-02-16)
- **Description:** Define daemon lifecycle, client transport choice (Unix domain socket first), request/response correlation strategy, reconnect behavior, and failure boundaries between broker, upstream bridge, and client proxies.
- **Priority:** P0
Expand Down Expand Up @@ -2033,7 +2033,7 @@ Phase 9 Follow-up Backlog

---

#### P13-T3: Implement multi-client transport and JSON-RPC multiplexing
#### P13-T3: Implement multi-client transport and JSON-RPC multiplexing
- **Description:** Add local transport server (Unix socket) that accepts multiple clients and multiplexes JSON-RPC traffic to/from the single upstream bridge while preserving per-client response routing.
- **Priority:** P0
- **Dependencies:** P13-T2
Expand All @@ -2051,7 +2051,7 @@ Phase 9 Follow-up Backlog

---

#### P13-T4: Add stdio proxy mode for compatibility with existing MCP clients
#### P13-T4: Add stdio proxy mode for compatibility with existing MCP clients
- **Description:** Implement a proxy mode where standard MCP clients still use stdio, but the wrapper process forwards traffic to the persistent local broker instead of spawning a new upstream bridge.
- **Priority:** P1
- **Dependencies:** P13-T3
Expand Down Expand Up @@ -2250,7 +2250,7 @@ Phase 9 Follow-up Backlog

---

#### FU-P12-T1-5: Cap `_clients` dict and prune `client_identities` to prevent unbounded growth
#### ⬜️ FU-P12-T1-5: Cap `_clients` dict and prune `client_identities` to prevent unbounded growth
- **Description:** The in-memory `_clients` dict in `MetricsCollector` and the `client_identities` SQLite table in `SharedMetricsStore` grow without limit — every unique `(name, version)` pair adds an entry that is never evicted. Add a soft cap (e.g. 50 entries, evict oldest by `last_seen`) to `_clients`, and add a `WHERE last_seen > ?` pruning clause for `client_identities` on write. This aligns with the project pattern established by FU-BUG-T7-1 (`pending_methods` cap).
- **Priority:** P2
- **Dependencies:** FU-P12-T1-3
Expand All @@ -2267,7 +2267,7 @@ Phase 9 Follow-up Backlog

---

#### FU-P12-T1-6: Uniform HTML escaping in `renderClientWidgets`
#### ⬜️ FU-P12-T1-6: Uniform HTML escaping in `renderClientWidgets`
- **Description:** In `dashboard.js` `renderClientWidgets`, the `count` integer and `lastSeen` string are interpolated into innerHTML without `escapeHtml()`, while `name` and `version` are escaped. Although `count` is always a number and `lastSeen` already passes through `escapeHtml` inside `formatRelativeAge`, the asymmetric pattern makes security auditing harder. Apply `escapeHtml()` uniformly to all interpolated values for consistency.
- **Priority:** P3
- **Dependencies:** FU-P12-T1-3
Expand Down Expand Up @@ -2300,7 +2300,7 @@ Phase 9 Follow-up Backlog

---

#### FU-P12-T3-1: Document unused `error_message` parameter in `MetricsCollector.record_response`
#### ⬜️ FU-P12-T3-1: Document unused `error_message` parameter in `MetricsCollector.record_response`
- **Description:** `MetricsCollector.record_response()` accepts `error_message: Optional[str]` for API symmetry with `SharedMetricsStore`, but never stores or uses it. Add a docstring note clarifying this parameter is accepted for interface compatibility but not persisted in the in-memory collector.
- **Priority:** P3
- **Dependencies:** P12-T3
Expand Down
10 changes: 8 additions & 2 deletions scripts/pick_next_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ def parse_workplan(workplan_path: Path) -> list[Task]:
task_id_pattern = r'(?:P\d+-T\d+(?:\.\d+)?|BUG-T\d+|FU-[A-Z0-9-]+|REBUILD-[A-Z0-9-]+)'
# Keep canonical phase labels (e.g., "Phase 1") and ignore descriptive suffixes.
phase_re = re.compile(r'^###\s+(Phase \d+)(?::[^\n]+)?$')
header_task_re = re.compile(rf'^####\s+(✅\s+)?({task_id_pattern}):\s+(.+)$')
marker_pattern = r'(?:✅|⬜(?:\ufe0f)?)'
header_task_re = re.compile(
rf'^####\s+(?:({marker_pattern})\s+)?({task_id_pattern}):\s+(.+?)(?:\s+({marker_pattern}))?$'
)
checklist_task_re = re.compile(rf'^-\s+\[(x|X| )\]\s+({task_id_pattern}):\s+(.+)$')

current_phase = "Uncategorized"
Expand All @@ -71,9 +74,12 @@ def parse_workplan(workplan_path: Path) -> list[Task]:
continue

if header_match:
completed_in_workplan = bool(header_match.group(1))
leading_marker = header_match.group(1)
task_id = header_match.group(2)
title = header_match.group(3).strip()
trailing_marker = header_match.group(4)
marker = leading_marker or trailing_marker
completed_in_workplan = marker == '✅'
raw_text = line.strip()
else:
completed_in_workplan = checklist_match.group(1).lower() == 'x'
Expand Down
37 changes: 37 additions & 0 deletions tests/unit/test_pick_next_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,43 @@ def test_extracts_priorities(self, temp_workplan):
assert priorities["P2-T2"] == "P1"
assert priorities["P3-T1"] == "P2"

def test_supports_explicit_completed_and_uncompleted_markers(self, tmp_path):
"""Task headers marked with ✅/⬜️ should parse and set completion state."""
workplan_path = tmp_path / "Workplan.md"
workplan_path.write_text(
"""### Phase 1: Test
#### ✅ P1-T1: Completed task
- **Priority:** P0
- **Dependencies:** none

#### ⬜️ P1-T2: Uncompleted task
- **Priority:** P1
- **Dependencies:** P1-T1
"""
)

tasks = parse_workplan(workplan_path)
by_id = {task.id: task for task in tasks}

assert by_id["P1-T1"].completed_in_workplan is True
assert by_id["P1-T2"].completed_in_workplan is False

def test_supports_legacy_trailing_completion_marker(self, tmp_path):
"""Legacy trailing ✅ markers should still be treated as completed."""
workplan_path = tmp_path / "Workplan.md"
workplan_path.write_text(
"""### Phase 1: Test
#### P1-T1: Completed task ✅
- **Priority:** P0
- **Dependencies:** none
"""
)

tasks = parse_workplan(workplan_path)
assert len(tasks) == 1
assert tasks[0].id == "P1-T1"
assert tasks[0].completed_in_workplan is True

def test_empty_workplan(self, tmp_path):
"""Test parsing empty workplan returns empty list."""
workplan_path = tmp_path / "Empty.md"
Expand Down