Skip to content

Formalize the context-detection token contract: make detect-context.sh the single source of truth for ACTIVE_CONTEXTS and skill/instruction frontmatter #310

Description

@arndvs

Problem

ADR-002 (four-tier progressive disclosure) defines Tier-2 as context-gated loading: detect-context.sh sets ACTIVE_CONTEXTS from file signatures, and skills/instructions declare the contexts they load under. The whole mechanism works only if the two sides agree on a shared vocabulary of context tokens.

That contract is currently implicit and already broken:

  • bin/detect-context.sh emits 17 hardcoded tokens (nextjs, expo, react-native, react, node, typescript, php, sanity, better-auth, prisma, docker, python, laravel, cmd, ...).
  • skills/mobile-dev/SKILL.md declares contexts: [expo, react-native, mobile] — but mobile is not a token detect-context.sh can ever emit, so that gate is silently inert. A consumer matching ACTIVE_CONTEXTS against the frontmatter never fires on mobile and never fails loudly; the skill's context-gating is dead for one of its three declared contexts.
  • There is no single source of truth. The token list lives inline inside one 200-line bash script (with no test), is re-derived by hand in detect-client.sh, is referenced loosely in instructions/README.md, and is duplicated in skill frontmatter across the repo. Nothing validates that a skill/instruction's declared contexts are members of the detector's emit set, or vice versa.

Because detection is a pure, branching decision function feeding skill-loading, HUD context events, and ACTIVE_CONTEXTS, a misspelled or stale context token is a silent classification failure — exactly the class ADR-002 was written to prevent.

Proposed change

  1. Define one canonical context-token registry (e.g. detect-context-data.sh, mirroring the existing pipeline-label-data.sh pattern: generated from a TS source via render-pipeline-artifacts.ts, or a simple checked-in list owned by the detector). It declares the full emit set of tokens plus the file-signature predicates that produce each.
  2. Make detect-context.sh consume the registry instead of hardcoding tokens inline, so the emit set is derived from one place.
  3. Add a validation pass (extend bin/validate-skills.sh, which already parses frontmatter) that cross-checks every contexts: declaration in skills/ and instructions/ against the registry and fails on unknown tokens — turning the mobile case into an explicit, flagged error rather than silent dead weight.
  4. Add a contract test (shell, in test/) that runs detect-context.sh over a small matrix of fixture directories (nextjs vs. react vs. react-native/expo vs. php vs. none) and asserts the exact ACTIVE_CONTEXTS string, protecting the decision logic and the registry from regressions.

Acceptance criteria

  • detect-context.sh reads its token set from the single registry; no inline context token list remains in the script.
  • bin/validate-skills.sh fails (or warns) on any contexts: entry not present in the registry; the existing mobile breakage is resolved either by adding the token to the detector or by removing it from the frontmatter — decided against the registry.
  • A test/ fixture matrix asserts the emit set per directory type.
  • ADR-002's Tier-2 table and instructions/README.md are updated to reference the registry as canonical.

Why now

The pipeline-label state machine already solved this exact shape of problem — a vocabulary duplicated across shell/TS with drift risk — by generating a single artifact (pipeline-label-data.sh) from one source and enforcing it in CI. Context detection is the same class of boundary, unaddressed, and already showing a concrete drift case. Fixing it now makes adding a context-triggered skill or a new detector signature a one-file, lint-checked change instead of an invisible gamble.

Related: ADR-002 (binding), bin/detect-context.sh, bin/detect-client.sh, bin/validate-skills.sh, bin/pipeline-label-data.sh, shft/engine/lib/render-pipeline-artifacts.ts, instructions/README.md, skills/mobile-dev/SKILL.md.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    source:architecture-reviewPRDs proposed by the automated architecture-review workflow

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions