Tasks: per-work-item collaborators
Phase 3 of 3. Small, verifiable tasks; each
_Test:_names a row oftesting-plan.md.
Task list
[x] 1. The roster, and its place in the portable record
cli/the_loop/collaborators.py:normalize_login,parse_logins,CollaboratorRecord,CollaboratorStore(list/add/remove/is_collaborator/permits/clear).cli/the_loop/workitem.py:COLLABORATORSjoinsSECTIONS(no legacy fallback — the section did not exist before this work item).- Security-relevant (A3, A4):
normalize_loginis the injection mitigation, andpermitsasking only about the refs it is given is the scoping one. - Depends on: none
- Requirements: R1.1–R1.5, R1.7, R3.7, R4.2
- Test:
T1, T2 — uv run pytest tests/test_collaborators.py
[x] 2. Two more words in the vocabulary
cli/the_loop/control.py:ADD_COLLABORATOR/REMOVE_COLLABORATOR,COMMANDS,COLLABORATOR_COMMANDS,DEFAULT_KEYWORDS;ControlResult.subjectsand the login scan inparse_command;command_comment(subject=…, invocation=…).- Depends on: 1
- Requirements: R4.1, R4.3–R4.6, R5.2
- Test:
T3 — uv run pytest tests/test_control.py
[x] 3. Both schema copies, the template and this repo's own config
.the-loop/cli-config.schema.jsonandcli/the_loop/schemas/cli-config.schema.json(kept byte-identical),skills/the-loop/templates/cli-config.yaml,.the-loop/cli-config.yaml.- Depends on: 2
- Requirements: R4.1, R4.6
- Test:
T11 — uv run pytest tests/test_configschema.py tests/test_config_schema_parity.py
[x] 4. The webhook ingress seam
cli/the_loop/webhook/router.py:Router(collaborators=…); a comment from a granted login falls through the authorization guard and emitsrouting.collaborator.cli/the_loop/webhook/daemon.py: inject the dispatcher's store, and keep it injected across a hot reload.- Depends on: 1
- Requirements: R3.1
- Test:
T6 — uv run pytest tests/test_routing.py tests/test_webhook_routing_integration.py
[x] 5. The dispatcher: execute the two verbs, and refuse everything else
cli/the_loop/webhook/dispatcher.py: own aCollaboratorStore; branchCOLLABORATOR_COMMANDSinhandle();_apply_collaborator;collaborator-no-spawnin_spawn_refusal+SETTLED_SUPPRESSED; clear the roster where the control record is cleared on closure.- Security-relevant (A1, A2, A6): the control seam's named-actor re-check becomes load-bearing, and the spawn seam gains the same one.
- Depends on: 2, 4
- Requirements: R2.1–R2.3, R3.2–R3.4, R4.4, R4.7, R1.6, R6.1, R6.2
- Test:
T4, T5, T6, T13 — uv run pytest tests/test_control_integration.py tests/test_webhook_routing_integration.py
[x] 6. The poll ingress seam
cli/the_loop/poller/poller.py: a granted author's comment is a candidate;spawn_authorizedand_pending_control_idsunchanged, and asserted so.- Depends on: 5
- Requirements: R3.1, R3.3, R3.4
- Test:
T7 — uv run pytest tests/test_poller.py tests/test_poller_integration.py
[x] 7. Forgetting a roster
cli/the_loop/reset.py: the section joinsPIECESsosessions resetdrops it.- Depends on: 1
- Requirements: R1.6
- Test:
T9 — uv run pytest tests/test_reset.py
[x] 8. The two CLI verbs
cli/the_loop/core/collaborators.py:manage_collaborators— local effect, then the ticket comment as a report.cli/the_loop/commands/collaborators_cmd.py+ registration incommands/__init__.py.- Depends on: 2
- Requirements: R5.1–R5.5, R2.4
- Test:
T10 — uv run pytest tests/test_collaborators_cli.py
[x] 9. Tests
- New:
tests/test_collaborators.py,tests/test_collaborators_cli.py. - Extended:
test_control.py,test_routing.py,test_control_integration.py,test_webhook_routing_integration.py,test_poller.py,test_reset.py, and a gates-unchanged regression (A5). - Every new test is run against the unfixed tree first and seen to fail.
- Depends on: 1–8
- Requirements: all
- Test:
T1–T13
- New:
[x] 10. Documentation of record, in this PR
docs/capabilities/webhook-triggers.md(the second allow-list),docs/capabilities/cli.md,docs/cli/commands/{add,remove}-collaborator.md+docs/.vitepress/config.mtsnav,docs/config/cli/routing-options.md,docs/reference/commands.md,docs/cli/state.md,skills/the-loop/reference/collaboration.md,docs/decisions/decision-102.mdand the decisions index.- Depends on: 8
- Requirements: —
- Test:
T14 — uv run pytest tests/test_docs_parity.py; markdownlint
[x] 11. Verification and evidence
- Lint, types, the full suite; results in
evidence/verification.md, security verdict against the abuse-case table inevidence/security-review.md. - Depends on: 9, 10
- Requirements: all
- Test:
T13, T14
- Lint, types, the full suite; results in