Skip to content

[Feature]: Stop grep-based spec alignment, structured IDs + context packs #4164

Description

@harsha09

Problem Statement

I'm frustrated when a product change (especially a UI change) has to be folded into an existing feature. Agents find related work by grepping similar wording in spec.md, plan.md, and tasks.md. After a reword “charge on Pay” vs “show a confirm modal” the live AC/FR is often not retrieved, so another /speckit.specify pass or a manual edit adds a new requirement instead of updating the existing one.

The result is two live lines for the same behavior, or two live lines that contradict each other. /speckit.analyze is supposed to catch duplicates and conflicts, but it only reports what the model loaded. If the related line was never in context, the report is clean. I end up rerunning analyze over and over; it is not a reliable alignment step.

There is no script-owned inventory of live IDs (FR-, US/AC, T-xxx) that specify, analyze, and implement all share. Commands dump whole Markdown files (wasted tokens) and still miss the one line that mattered. I need a way to keep the spec set unambiguous no silent duplicates, no contradictory live requirements without another round of hope-and-grep.

Proposed Solution

Keep spec.md / plan.md / tasks.md as the human artifacts. Add a script-owned live inventory so specify, analyze, and implement stop grepping prose to decide what exists.

  1. Structured sidecar for tasks (and later spec/plan records)
    Alongside tasks.md, write tasks.yaml (YAML on disk, JSON on stdout). Each task is a record: id, status, story, files, covers: [US1/AC2, FR-007]. A Python script is the only mutator: parse Markdown once, then list / get / mark-done / coverage. Agents do not regex checkboxes.

  2. Complete live inventory, every command
    The script emits every live FR- / AC / SC / T- for the current feature. That list is the source of “what exists.” Specify consults it before adding a requirement. Analyze builds its report from it. Implement loads one task plus the records it covers. No command should discover the spec by grepping similar text.

  3. Context pack instead of whole files
    specify context --task T014 (or equivalent) prints a small JSON pack: that task, the live ACs/FRs it cites, matching plan bullets, and optional research hits. /speckit.implement and /speckit.analyze drive from the pack/inventory, not from dumping three Markdown files. That removes the missed-line failure and cuts tokens.

  4. Local, per-feature recall only (optional second phase)
    If an ID link is missing, a local embedding index under specs//.index/ can pair paraphrases (“confirm modal” <-> live “charge on Pay”). Not a global or hosted vector store. Default retrieval excludes obsolete lines so old UI copy cannot be treated as live. Embeddings improve recall; they are not the source of truth.

  5. Alignment is classify-on-write, not another analyze loop
    Before adding a requirement, resolve against the full live set (IDs, then local similarity):

  • already true on a live line -> skip (duplicate)
  • same behavior, new words -> edit that ID
  • disagrees with a live line -> conflict; do not add a second live FR
  • genuinely new -> one new ID, set covers on tasks

/speckit.analyze then reports coverage holes, unpaired IDs, and remaining high-score pairs over that structure. It should be a single deterministic pass, not a hunt that has to be rerun until the model gets lucky.

Phase 1 (core-shaped): parser + tasks.yaml + covers + context pack.
Phase 2 (opt-in): local per-feature index for paraphrase pairs.

Alternatives Considered

No response

Component

Other

AI Agent (if applicable)

None

Use Cases

No response

Acceptance Criteria

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions