Operant Studio
OPER-194

Admission accepts future_feature_id for tickets that add a new FEAT

Suggested
Justin Cooke

Body

---
feature_id: FEAT-studio-planning-validation
---

## Context

Ledger admission enforces that `feature_id:` frontmatter references a FEAT id currently declared in the target product's `products/<slug>/feature-map.md`. This is correct default behavior and it's what surfaced OPER-184 through OPER-191 as `admission-rejected` this session.

However, a legitimate class of tickets is one whose entire scope IS to add a new feature. Per Studio boilerplate, adding a feature requires a mandatory two-PR sequence:

1. PR A: add the FEAT id to `products/<slug>/feature-map.md` and update `products/<slug>/dependency-map.md`
2. PR B: implement the feature under a ticket whose `feature_id:` points at the new FEAT

Today the workflow forces the ticket-filer to either:
- File PR A first, wait for it to merge, THEN file the implementation ticket (blocks parallel dispatcher work)
- Attach the implementation ticket to a parent existing FEAT and put a note in the body naming the future child FEAT (loses the direct FEAT-to-ticket linkage, weakens dispatcher context)

Both are workarounds. The system should accept "this ticket declares intent to add FEAT-X as a new child of parent-FEAT-Y" as a first-class admission input.

## What

Extend admission (`packages/planning-validation` or wherever `assertAdmissible` lives) to accept an additional frontmatter field:

    future_feature_id: FEAT-studio-<new-child-slug>
    future_feature_parent: FEAT-studio-<existing-parent>
    future_feature_group: <feature-map-group-heading>   # e.g. "QA", "Assurance"

Admission accepts a ticket declaring `future_feature_id` if AND ONLY IF:

1. `future_feature_parent` is a declared FEAT id in the target product's feature-map (validated same as `feature_id` is today)
2. `future_feature_group` matches an `## <Group>` heading in the target product's feature-map
3. `future_feature_id` is NOT already declared (must be genuinely new)
4. `future_feature_id` matches the naming convention `FEAT-<product>-<kebab-slug>`

On acceptance:

- The ticket is admitted normally (status READY_FOR_PLANNING)
- A companion "feature-map addition" child ticket is auto-filed with:
   - Title: `feat(feature-map): add {future_feature_id} to products/<slug>/feature-map.md + dependency-map.md`
   - Body: auto-generated diff-ready spec
   - feature_id: FEAT-studio-planning-validation (or FEAT-studio-dependency-map-policy, whichever owns the two-PR flow)
   - Blocks: the original ticket (via a new `blocks:` frontmatter or dependency graph edge)
- Once the feature-map PR merges (detected via existing merge-watcher pattern), the original ticket's `feature_id` is auto-rewritten from the parent to the new child, `future_feature_*` fields stripped, and admission re-runs against the new declaration.

## Acceptance Criteria

- [ ] Admission accepts `future_feature_id` + `future_feature_parent` + `future_feature_group` frontmatter as an alternative to `feature_id`
- [ ] Validates all three inputs against the current feature-map before accepting
- [ ] Auto-files a companion feature-map + depmap addition ticket blocking the original
- [ ] Companion ticket body includes the exact diff needed for the two-PR sequence
- [ ] On feature-map PR merge, original ticket's `feature_id` auto-rewrites from parent to new child and admission re-runs
- [ ] Unit tests covering: happy path (all three fields valid), invalid parent, invalid group, already-declared future_feature_id, malformed naming convention
- [ ] Integration test: file a ticket with future_feature_id, verify companion ticket appears, mock-merge the companion, verify original re-admits with new feature_id

## Effect on this session's tickets

OPER-184 through OPER-191 currently attached to parent FEAT-studio-qa (D-29 tickets) or FEAT-studio-qa-projects (D-30 tickets) with a body note naming the future child FEAT. Once this ticket ships, those eight can be back-migrated to `future_feature_id:` frontmatter and the companion feature-map addition ticket will auto-generate correctly.

## Blocked-by

None (independent design).

## Size / Band

M / assurance (touches admission, adds auto-ticket-filing, adds merge-watcher hook, adds feature-map + depmap diff generator).

## Discovered by

Ticket-filing session 2026.09.10 — 8 tickets all needed workaround because they reference new child FEAT ids not yet in the feature-map.

Attachments

Loading attachments…

Comments

Loading comments…