Tasks: Profile Invocation Runtime and Audit Trail

Mission: profile-invocation-runtime-audit-trail-01KPQRX2 Release target: 3.2.0 Branch: mainmain Generated: 2026-04-21


Subtask Index

IDDescriptionWPParallel
T001Package scaffold: invocation/__init__.py, fixture profiles, errors.pyWP01
T002record.py — InvocationRecord Pydantic v2 model + MinimalViableTrailPolicy stubWP01
T003registry.py — ProfileRegistry wrapping AgentProfileRepositoryWP01[D]
T004writer.py — InvocationWriter (write_started, write_completed, append-only)WP01[D]
T005executor.py — ProfileInvocationExecutor (invoke + governance context assembly)WP01
T006profiles_cmd.pyspec-kitty profiles list [--json] + main.py registrationWP01[D]
T007Tests: test_record, test_registry, test_writer, test_executor, test_profiles CLIWP01
T008router.py — ActionRouter with CANONICAL_VERB_MAP, token normalization, domain_keyword matchWP02
T009Wire router into executor.py invoke() (no-hint path); add ActionRouterPlugin stubWP02
T010test_router.py — 7 table-driven cases; confirm ADR-3 doc as review gateWP02[D]
T011advise.pyspec-kitty advise <request> [--profile <name>] [--json]WP03
T012Add spec-kitty ask <profile> <request> shim in advise.pyWP03[D]
T013Add spec-kitty profile-invocation complete --invocation-id <id> in advise.pyWP03[D]
T014Register advise / ask / profile-invocation groups in main.pyWP03
T015Integration tests: cli/test_advise.py (happy path, profile missing, no charter, --json)WP03[D]
T016do_cmd.pyspec-kitty do <request> [--json] (router always invoked)WP04
T017Register do command in main.pyWP04
T018Integration tests: cli/test_do.py (happy path, ambiguity error, no-match error)WP04[D]
T019Finalize MinimalViableTrailPolicy frozen dataclass (all 3 tiers fully specified)WP05
T020Implement tier_eligible(record) and promote_to_evidence(record, dir, content)WP05
T021Export MinimalViableTrailPolicy from __init__.py; extend test_record.pyWP05[D]
T022invocations_cmd.pyinvocations list [--profile] [--limit N] [--json]WP06
T023Register invocations group in main.pyWP06
T024Benchmark list perf at 10K entries; implement invocation-index if > 200msWP06
T025Integration tests: cli/test_invocations.py (query, filter, empty log, limit)WP06[D]
T026Skill pack: .agents/skills/spec-kitty.advise/SKILL.mdWP06[D]
T027Entry gate: verify CLI-SaaS contract field coverage for InvocationRecord v1WP07
T028propagator.py — InvocationSaaSPropagator (background thread, atexit, error log)WP07
T029Wire propagator into executor.py post write_completedWP07
T030test_propagator.py — mock SaaS client, non-blocking, error log, idempotency, no-opWP07[D]

Work Package Summary

WP01 — Executor Core: Package Foundation + profiles list

Goal: Stand up the new src/specify_cli/invocation/ package with its core primitives: ProfileInvocationExecutor, InvocationRecord, ProfileRegistry, InvocationWriter, error types, and the spec-kitty profiles list command. This WP is the dependency root for all other WPs.

Priority: P1 — blocks everything Estimated prompt size: ~460 lines Entry gate: ADR-3 doc (adr-3-deterministic-action-router.md) already committed Prompt file: tasks/WP01-executor-core-profiles-list.md

Included subtasks:

  • ✅ T001 Package scaffold: invocation/__init__.py, fixture profiles, errors.py (WP01)
  • ✅ T002 record.py — InvocationRecord Pydantic v2 model + MinimalViableTrailPolicy stub (WP01)
  • ✅ T003 registry.py — ProfileRegistry wrapping AgentProfileRepository (WP01)
  • ✅ T004 writer.py — InvocationWriter (write_started, write_completed, append-only) (WP01)
  • ✅ T005 executor.py — ProfileInvocationExecutor (invoke + governance context assembly) (WP01)
  • ✅ T006 profiles_cmd.pyspec-kitty profiles list [--json] + main.py registration (WP01)
  • ✅ T007 Tests: test_record, test_registry, test_writer, test_executor, test_profiles CLI (WP01)

Dependencies: none (root WP) Blocks: WP02, WP03, WP04, WP05, WP06, WP07


WP02 — Deterministic Action Router

Goal: Implement the ActionRouter (ADR-3, Option A — deterministic, no LLM). Wire it into the executor's no-hint path. The ADR-3 document must be reviewed and accepted before this WP merges.

Priority: P1 — blocks WP03 (advise router path), WP04 (do command) Estimated prompt size: ~280 lines Entry gate: ADR-3 doc reviewed and accepted (exists at adr-3-deterministic-action-router.md) Prompt file: tasks/WP02-deterministic-action-router.md

Included subtasks:

  • ✅ T008 router.py — ActionRouter with CANONICAL_VERB_MAP, token normalization, domain_keyword match (WP02)
  • ✅ T009 Wire router into executor.py invoke() (no-hint path); add ActionRouterPlugin stub (WP02)
  • ✅ T010 test_router.py — 7 table-driven cases; confirm ADR-3 doc as review gate (WP02)

Dependencies: WP01 Blocks: WP03, WP04


WP03 — advise + ask + profile-invocation complete CLI

Goal: Implement the three primary CLI surfaces for profile-governed invocations: advise, ask (thin shim), and profile-invocation complete. These are the surfaces host-LLM agents use to open and close invocation records.

Priority: P1 — primary user-facing CLI Estimated prompt size: ~350 lines Prompt file: tasks/WP03-advise-ask-complete-cli.md

Included subtasks:

  • ✅ T011 advise.pyspec-kitty advise <request> [--profile <name>] [--json] (WP03)
  • ✅ T012 Add spec-kitty ask <profile> <request> shim in advise.py (WP03)
  • ✅ T013 Add spec-kitty profile-invocation complete --invocation-id <id> in advise.py (WP03)
  • ✅ T014 Register advise / ask / profile-invocation groups in main.py (WP03)
  • ✅ T015 Integration tests: cli/test_advise.py (WP03)

Dependencies: WP02 Blocks: none (parallel with WP04–WP07)


WP04 — do Command

Goal: Implement spec-kitty do <request> — the anonymous dispatch surface that always routes through the ActionRouter (no explicit profile hint from caller). This is the simplest entry point for operators who don't know which profile to use.

Priority: P2 — depends on router (WP02) Estimated prompt size: ~220 lines Prompt file: tasks/WP04-do-command.md

Included subtasks:

  • ✅ T016 do_cmd.pyspec-kitty do <request> [--json] (WP04)
  • ✅ T017 Register do command in main.py (WP04)
  • ✅ T018 Integration tests: cli/test_do.py (WP04)

Dependencies: WP02 Blocks: none


WP05 — MinimalViableTrailPolicy + Tier Promotion API

Goal: Finalize the MinimalViableTrailPolicy as a frozen dataclass with all three tiers fully specified, implement tier_eligible() and promote_to_evidence() helpers, and export them from the package's public API.

Priority: P2 — can run in parallel with WP02–WP04 Estimated prompt size: ~240 lines Prompt file: tasks/WP05-minimal-viable-trail-policy.md

Included subtasks:

  • ✅ T019 Finalize MinimalViableTrailPolicy frozen dataclass (all 3 tiers fully specified) (WP05)
  • ✅ T020 Implement tier_eligible(record) and promote_to_evidence(record, dir, content) (WP05)
  • ✅ T021 Export from __init__.py; extend test_record.py (WP05)

Dependencies: WP01 Blocks: none


WP06 — invocations list + Skill Pack Updates

Goal: Implement spec-kitty invocations list — the operator's view into the local JSONL audit log — and update agent skill packs to document the new advise/ask/do/profiles surfaces.

Priority: P2 — can run in parallel with WP02–WP05 Estimated prompt size: ~320 lines Prompt file: tasks/WP06-invocations-list-skill-packs.md

Included subtasks:

  • ✅ T022 invocations_cmd.pyinvocations list [--profile] [--limit N] [--json] (WP06)
  • ✅ T023 Register invocations group in main.py (WP06)
  • ✅ T024 Benchmark list perf at 10K entries; implement index if > 200ms (WP06)
  • ✅ T025 Integration tests: cli/test_invocations.py (WP06)
  • ✅ T026 Skill pack: .agents/skills/spec-kitty.advise/SKILL.md (WP06)

Dependencies: WP01 Blocks: WP07 (propagation relies on writer being stable)


WP07 — SaaS Propagation

Goal: Implement InvocationSaaSPropagator — background-thread, non-blocking SaaS event propagation using the existing CLI-SaaS contract. The entry gate for this WP is a mandatory contract field coverage check.

Priority: P3 — last WP; depends on stable record + writer Estimated prompt size: ~290 lines Prompt file: tasks/WP07-saas-propagation.md

Included subtasks:

  • ✅ T027 Entry gate: verify CLI-SaaS contract field coverage for InvocationRecord v1 (WP07)
  • ✅ T028 propagator.py — InvocationSaaSPropagator (background thread, atexit, error log) (WP07)
  • ✅ T029 Wire propagator into executor.py post write_completed (WP07)
  • ✅ T030 test_propagator.py — mock SaaS, non-blocking, error log, idempotency, no-op (WP07)

Dependencies: WP01 (executor), WP06 (stable writer) Blocks: none


Dependency Graph

WP01 (root)
 ├─→ WP02 ─→ WP03
 │    └─→ WP04
 ├─→ WP05   (parallel with WP02)
 └─→ WP06 ─→ WP07

Parallelization Opportunities

After WP01 lands:

  • WP02 ∥ WP05 ∥ WP06: All three are independent after WP01
  • WP03 ∥ WP04: Both depend on WP02 but are independent of each other
  • WP07: Starts after WP06 (and WP01)

Expected critical path: WP01 → WP02 → WP03 (5 subtasks on the sequential path)