Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: processkit.projectious.work/v2
kind: LogEntry
metadata:
id: LOG-20260509_2142-SteadyField-workitem-transitioned
created: '2026-05-09T21:42:45+00:00'
spec:
event_type: workitem.transitioned
timestamp: '2026-05-09T21:42:45+00:00'
summary: Transitioned WorkItem 'BACK-20260509_1836-TidyAsh-roleslot-primitive-identity-axis-decoupling'
from 'in-progress' to 'review'
subject: BACK-20260509_1836-TidyAsh-roleslot-primitive-identity-axis-decoupling
subject_kind: WorkItem
actor: BACK-20260509_1836-TidyAsh-roleslot-primitive-identity-axis-decoupling
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: processkit.projectious.work/v2
kind: LogEntry
metadata:
id: LOG-20260509_2146-BrightGrove-workitem-transitioned
created: '2026-05-09T21:46:11+00:00'
spec:
event_type: workitem.transitioned
timestamp: '2026-05-09T21:46:11+00:00'
summary: Transitioned WorkItem 'BACK-20260509_1837-LuckyWren-catalog-driven-pk-team-create'
from 'backlog' to 'in-progress'
subject: BACK-20260509_1837-LuckyWren-catalog-driven-pk-team-create
subject_kind: WorkItem
actor: BACK-20260509_1837-LuckyWren-catalog-driven-pk-team-create
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: processkit.projectious.work/v2
kind: LogEntry
metadata:
id: LOG-20260509_2204-KeenLynx-workitem-transitioned
created: '2026-05-09T22:04:55+00:00'
spec:
event_type: workitem.transitioned
timestamp: '2026-05-09T22:04:55+00:00'
summary: Transitioned WorkItem 'BACK-20260509_1837-LuckyWren-catalog-driven-pk-team-create'
from 'in-progress' to 'review'
subject: BACK-20260509_1837-LuckyWren-catalog-driven-pk-team-create
subject_kind: WorkItem
actor: BACK-20260509_1837-LuckyWren-catalog-driven-pk-team-create
---
186 changes: 186 additions & 0 deletions context/migrations/20260509_2139_0.25.8-to-0.26.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
---
apiVersion: processkit.projectious.work/v2
kind: Migration
metadata:
id: MIG-20260509T213904-roleslot-phase-a
created: 2026-05-09T21:39:04+00:00
labels:
cluster: team-model-v2
epic_sub: SUB-1
design_artifact_ref: ART-20260509_1836-SmartPanda-team-creator-v2-design
spec:
source: processkit
source_url: https://github.com/projectious-work/processkit.git
kind: schema-extension
from_version: v0.25.8
to_version: v0.26.0
source_api_version: processkit.projectious.work/v2
target_api_version: processkit.projectious.work/v2
source_processkit_version: v0.25.8
target_processkit_version: v0.26.0
apply_mode: resumable
state: pending
generated_by: TEAMMEMBER-finn (ROLE-software-engineer/senior)
generated_at: 2026-05-09T21:39:04+00:00
summary: >
Phase A team-creator v2 — additive RoleSlot primitive + role-slot-fill
binding type. Backfill RoleSlots from existing Role.clone_cap and
parallel role-slot-fill Bindings from existing role-assignment
Bindings. Both old and new resolution paths remain valid after apply.
affected_groups:
- context/schemas
- context/skills/processkit/team-manager
- context/skills/_lib/processkit
- context/roleslots
- context/bindings
affected_files:
- path: src/context/schemas/roleslot.yaml
classification: new-upstream
group: context/schemas
- path: context/schemas/roleslot.yaml
classification: new-upstream
group: context/schemas
- path: src/context/schemas/binding.yaml
classification: changed-upstream-only
group: context/schemas
- path: context/schemas/binding.yaml
classification: changed-upstream-only
group: context/schemas
- path: src/context/skills/_lib/processkit/__init__.py
classification: changed-upstream-only
group: context/skills/_lib/processkit
- path: context/skills/_lib/processkit/__init__.py
classification: changed-upstream-only
group: context/skills/_lib/processkit
- path: src/context/skills/processkit/team-manager/mcp/server.py
classification: changed-upstream-only
group: context/skills/processkit/team-manager
- path: context/skills/processkit/team-manager/mcp/server.py
classification: changed-upstream-only
group: context/skills/processkit/team-manager
- path: src/context/skills/processkit/team-manager/scripts/test_team_manager.py
classification: changed-upstream-only
group: context/skills/processkit/team-manager
- path: context/skills/processkit/team-manager/scripts/test_team_manager.py
classification: changed-upstream-only
group: context/skills/processkit/team-manager
plan: >
Apply Phase A in three steps. (1) Land the schema + binding-type
additions (already shipped by this branch). (2) For each Role in
context/roles/ carrying clone_cap=N>0, emit N RoleSlots under the
team's chartering Scope (parent = active project Scope), rank=1..N,
state=open, default_model_profile copied through when present.
(3) For each Binding(type=role-assignment) currently active, write a
parallel Binding(type=role-slot-fill) with subject=TeamMember,
target=SLOT-<scope>-<role>-1 (rank-1 by convention; multi-clone
teams that were not yet differentiated all collapse onto rank-1
until pk-team-rebalance redistributes). v1 role-assignment Bindings
remain readable for one minor version (deprecation window).
Phase A must NOT delete v0.16.0 fields, must NOT remove the 8
archetype Roles, and must NOT modify pk-team-create. Both old and
new resolution paths must work after apply
(DEC-20260509_1906-CoolBadger Q2).
rollback:
feasibility: full
steps:
- >
Delete every entity under context/roleslots/ written by this
migration (filename matches SLOT-*-rank-* and frontmatter
labels.migration == MIG-20260509T213904-roleslot-phase-a). The
schema file roleslot.yaml stays — it is unreferenced once the
slot files are gone.
- >
Delete every Binding under context/bindings/ where spec.type ==
'role-slot-fill' and labels.migration ==
MIG-20260509T213904-roleslot-phase-a. v1 role-assignment Bindings
remain untouched.
- >
Reverse-edit binding.yaml known_types to remove
'role-slot-fill'. Reverse-edit
src/context/skills/_lib/processkit/__init__.py to remove the
RoleSlot KIND_PREFIXES + DEFAULT_DIRS entries. Reverse-edit
team-manager/mcp/server.py to remove the five RoleSlot tools and
the resolver pre-step hook. Existing 8-layer resolver behaviour
is restored bit-identical because the pre-step only adds a
``binding.roleslot_pre_step`` key — it never mutates the
existing fields.
- >
After rollback the project is at v0.25.8 — the same code path
as before this migration, with no orphan entities.
risk_window: >
Phase A only. Phase B (the destructive cutover that stops writing
archetype Roles) ships in a later minor version. Phase C
(resolver fold-in) ships after Phase B has been live for one
minor version. This migration is fully reversible.
progress_notes: []
---

# Migration MIG-20260509T213904-roleslot-phase-a

Phase A team-creator v2 — RoleSlot primitive + identity-axis decoupling.

Companion to:
- Architectural design: ART-20260509_1836-SmartPanda-team-creator-v2-design
- Architectural decisions: DEC-20260509_1906-CoolBadger
- Implementation WorkItem: BACK-20260509_1836-TidyAsh

## What this migration adds

1. **New entity kind: RoleSlot** (SCHEMA-roleslot v1.0.0). Scope-bounded
capacity reservation, registered in
`_lib/processkit/__init__.py`'s `KIND_PREFIXES` (`SLOT`) and
`DEFAULT_DIRS` (`roleslots`).
2. **New binding type: `role-slot-fill`** (subject=TeamMember,
target=SLOT-*). Added to `binding.yaml` `known_types` with a
conditional schema branch.
3. **Five new MCP tools on team-manager**: `create_role_slot`,
`get_role_slot`, `list_role_slots`, `fill_role_slot`,
`close_role_slot`.
4. **Resolver pre-step** in `get_interlocutor_runtime_binding` that
surfaces a filled RoleSlot ahead of the existing 8-layer
model-assignment resolver. The 8 layers are unchanged
(DEC-20260509_1906-CoolBadger Q1).

## Phase A backfill rules

For every Role in `context/roles/` with `clone_cap=N>0`, emit `N`
RoleSlots:

```
SLOT-<chartering-scope-slug>-<role-slug>-1
SLOT-<chartering-scope-slug>-<role-slug>-2
...
SLOT-<chartering-scope-slug>-<role-slug>-N
```

For every active `Binding(type=role-assignment)` whose subject is a
TeamMember, write a parallel `Binding(type=role-slot-fill)` pointing
TeamMember → `SLOT-...-1`. Multi-clone v1 teams collapse onto rank-1
until `pk-team-rebalance` redistributes — this is intentional for
Phase A.

## Compatibility commitments

- v1 `role-assignment` Bindings remain readable.
- The 8 archetype Roles stay in `context/roles/` and are NOT renamed.
- `pk-team-create`'s archetype-Role write step is unchanged (that is
SUB-2 / `LuckyWren`).
- v0.16.0 fields (`clone_cap`, `cap_escalation`, `is_template`,
`templated_from`, `primary_contact`) are NOT removed in Phase A
(DEC-20260509_1906-CoolBadger Q2). They are not currently present
in the live `role.yaml` / `team-member.yaml` schemas — see "Open
questions / scope risks" in the SUB-1 dispatch report.

## Rollback shape

See `spec.rollback`. Fully reversible: delete the new SLOT-* and
`role-slot-fill` Binding entities, revert the three changed source
files (`__init__.py`, `binding.yaml`, `team-manager/mcp/server.py`),
and the project returns to its pre-migration state.

## Status

This migration represents the additive Phase A surface. The actual
backfill apply happens when an operator runs the Phase A apply script
against the project's Roles + Bindings — out of scope for the
SUB-1 PR per BACK-20260509_1836-TidyAsh.
25 changes: 25 additions & 0 deletions context/schemas/binding.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ spec:
default_directory: context/bindings
known_types:
- role-assignment
- role-slot-fill
- model-assignment
- work-assignment
- process-gate
Expand Down Expand Up @@ -286,3 +287,27 @@ spec:
recurrence_rule:
type: string
pattern: "^ART-[a-zA-Z0-9_-]+$"
- if:
properties:
type:
const: role-slot-fill
required: [type]
then:
properties:
subject:
type: string
pattern: "^TEAMMEMBER-[a-z][a-z0-9-]*$"
description: "TeamMember filling the slot."
target:
type: string
pattern: "^SLOT-[a-z0-9][a-z0-9-]*-[1-9][0-9]*$"
description: "RoleSlot being filled."
target_kind:
const: RoleSlot
conditions:
type: object
additionalProperties: true
properties:
rationale:
type: string
description: "Why this TeamMember was placed in this slot."
Loading