Fleet Agent-to-Node Affinity Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan.
Goal: Persist an active-Organization Agent-to-user-owned-node binding, snapshot it onto future agent-task Fleet jobs, and enforce it during lease selection.
Architecture: A new agent-package affinity entity/repository/service owns validation and lookup. The authenticated API controller supplies the active Organization boundary. FleetJobService resolves a binding only while enqueueing agent-task work and stores a nullable immutable target snapshot; lease filtering rejects other nodes before capability checks and the existing CAS claim.
Tech Stack: TypeScript, NestJS 11, TypeORM 0.3, Jest, pnpm, PostgreSQL/SQLite-compatible schema.
Spec: docs/specs/fleet-agent-node-affinity/design.md
Global Constraints
- Work only in
codex/fleet-agent-node-affinityfrom currentorigin/develop. - Do not edit the shared dirty checkout or the credential-passthrough files owned by the overlapping Fleet stream.
- Additive code/migration only; do not deploy, enroll nodes, execute repository jobs, merge, or cascade.
- Keep nodes user-owned and bindings scoped to the authenticated user plus active Organization.
- Preserve existing Fleet data and scheduling for unbound jobs.
- Write and observe each focused failing test before its implementation.
Task 1: Capture the scheduling contract in failing service tests
- Extend
packages/agent/src/fleet/__tests__/fleet-job.service.spec.tswith literal fixtures proving target snapshot and strict lease behavior. - Add a failing test showing an
agent-taskenqueue snapshots the current scoped binding. - Add a failing test showing the wrong owner node is skipped even when capabilities match.
- Add a failing test showing the target node wins through the existing CAS.
- Retain explicit coverage for unbound/non-agent jobs.
- Run the focused Jest file and confirm failures are due to missing affinity/target behavior.
Task 2: Add the additive persistence model
- Add
FleetAgentNodeAffinityand nullableFleetJob.targetNodeIdentities. - Register the new entity in the entity barrel, Fleet module, and concrete DataSource inventory.
- Add the affinity repository with owner + Organization + Agent lookup/upsert.
- Add one additive API migration creating the affinity table, indexes, and Fleet job target column/index.
- Add/extend schema inventory tests where the repository already asserts registered entities.
- Run the focused entity/database tests and type check.
Task 3: Implement snapshot and lease enforcement
- Inject the affinity repository into
FleetJobService. - Resolve only
agent-taskpayloads with a non-empty stringagentIdand a non-null job Organization. - Pass the resolved node id into
FleetJobRepository.createastargetNodeId. - Include
targetNodeIdinFleetJobViewmapping and the Fleet job contract. - Skip candidates targeted at a different node before capability filtering.
- Run the focused Fleet job tests to GREEN, then refactor without changing behavior.
Task 4: Add owner/Organization-validated binding operations
- Add affinity service tests for owned scoped success, unknown/foreign Agent, foreign node, and personal scope.
- Observe RED before implementing validation.
- Implement the service using real Agent/Fleet node repository lookups and one non-enumerating not-found path.
- Add the API DTO and dedicated Fleet Agent affinity controller.
- Add controller tests proving active-Organization propagation and personal-scope refusal.
- Register the controller in
apps/api/src/fleet/fleet.module.tswithout touching the overlapping run router. - Run focused service/controller tests to GREEN.
Task 5: Verify the complete code-only slice
- Run Prettier on changed TypeScript/Markdown files.
- Run focused agent Fleet tests and API controller tests.
- Run
@ever-works/contracts,@ever-works/agent, and API type checks/builds proportionate to the change. - Inspect
git diff --check, the complete branch diff, and confirm the shared dirty checkout is untouched. - Commit in reviewable TDD-sized commits and push
codex/fleet-agent-node-affinity. - Open a PR targeting
develop; do not merge or cascade. - Read check conclusions and AI/bot review feedback, addressing only verified issues within the claimed slice.
Task 6: Handoff and release coordination claim
- Record exact remaining Windows pilot gates: repository/worktree provisioning, model loop, reconciliation, cancellation, dedicated-account installer/service, and signed/private distribution.
- Move the MAINTENANCE ACTIVE row to CHANGE LOG with commit/PR, verification, no-data statement, and rollback.
- Commit and push the board release.
- Report the outcome and whether work continues to task
01a02977-83d2-7fe3-b504-d0351a4cf6f8on hostlocal.