mcpField
N
ns-requirements-enricher

ns-requirements-enricher

github.com/nextstage-brasilDevelopment0143 installsUpdated 1w ago
Repository

About ns-requirements-enricher

ns-requirements-enricher turns an issue or pasted scope into an implementation brief for a coding agent. It checks existing behavior, identifies blocking product questions, and distinguishes chat drafts from GitLab issue previews.

Key features

  1. 01Creates an implementation brief from an issue or scope
  2. 02Checks existing behavior and relevant product decisions
  3. 03Asks only blocking product questions
  4. 04Separates chat briefs from issue comment previews
  5. 05Posts issue comments only after human approval

Use cases

  1. 01Clarifying incomplete acceptance criteria before coding
  2. 02Preparing a brief from a GitLab issue and its comments
  3. 03Turning a pasted feature description into implementation requirements

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/nextstage-brasil/skills --skill ns-requirements-enricher

After installing, type/ns-requirements-enricherin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
evals.json
references/
comment-template.md
question-checklist.md

Details

From the project README

Requirements Enricher

One issue or one pasted description. Output = implementation brief for coding agent. Questions only when they unblock implementation. No branch, code, status, or version artifacts.

Not PM clarification. Not SDD Specify / version Clarify. See Relationship.

Mode detection

ModeTriggerDelivery
IssueISSUE_URL or user points at GitLab issueChat preview of comment body. add_issue_comment internal only after human validates that draft
ChatPasted/described scope — no issue URLBrief on screen. Never offer to post. Never ask "want me to post?"

Phases 2–4 shared. Phase 1 (MCP load) = issue only.

MCP fallback (SSoT): GitLab MCP missing or unusable → treat as chat mode (same brief; no post). Do not stop. Phase 1 skipped.

Session boot

See ../../ns-harness/references/session-boot.md. Complete Session boot (blocking) before MCP or codebase investigation.

GitLab MCP after boot: follow mcp-gitlab-usage (get_mcp_gitlab_skill version check on first access). Absent → MCP fallback.

Objective

Issue mode — questions stay in chat. They produce the comment. They never go to GitLab. After answers, show the closed brief. Post that body only on explicit human yes.

Posted comment (when allowed):

  1. First line ✅ — requirements already closed. No @mention.
  2. Full implementation brief (decisions already folded in). No Questions section. No Recommended list. No reply-by-number footer.

Chat mode — same question batch, then closed brief inline. No GitLab offer. Not a PRD.

Do not implement, commit, change issue status, create files, write requirements.md, or call start_execution_planning.

When to use

  • ISSUE_URL + brief before coding (issue)
  • Pasted brief/scope/AC in chat, no GitLab (chat)
  • Grill-me when implementing agent would otherwise guess product intent
  • ns-autonomous / human flags underspecified
  • Pre-step before ns-execution-gitlab-issue when acceptance incomplete

Prerequisites

  1. Obey AGENTS.md in host context — Docker/runtime if investigation hits tests/services. Never tool-Read it.
  2. agents.local.md present → only GitLab MCP named there.
  3. MCP tool contracts when MCP available; else MCP fallback.

Inputs

VariableRequiredDescription
ISSUE_URLIssue mode onlyFull GitLab issue / work item link
Requirements textChat mode onlyUser message, pasted brief, or attached scope

No auto-post. DRY_RUN obsolete — preview always; post only after human validates.

Phase 1 — Load issue context (issue mode only)

Skip in chat mode. Chat source = user message + pasted context.

Parse URL for project_id (or project_name for discovery) + issue_iid.

Mandatory reads:

  1. read_issue — title, description, labels, milestone, assignees, related links.
  2. list_issue_comments — full thread; comment bodies = requirements source.

Do not @mention anyone in the comment. Not the opener, not an assignee, not a login copied from an existing bot comment. Missing author.username is not a stop.

Synthesize (internal; not posted yet):

  • Goal — one sentence: what exists when done?
  • Acceptance — list from description; each clear / partial / missing
  • Constraints — labels/milestone/due for your context; do not turn missing labels into questions
  • Already answered — comment facts that remove ambiguity; do not re-ask
  • Upstream decisions — see Upstream product decisions below

User claimed issue mode but no ISSUE_URL: stop one line — URL missing. Do not invent issue content. MCP unavailable is not this stop — MCP fallback.

Chat mode: same Goal / AC / Constraints / Already answered from conversation text.

Upstream product decisions

When the workspace has PM artifacts for the scope this issue belongs to, read them before asking anything:

  • docs/versions/*/pm/decision-register.md: decisions (Q-NN), conflicts (C-NN), readiness
  • docs/versions/*/pm/prd.md: business rules and acceptance per requirement, open questions

Match by milestone, title or the requirement the issue implements. When it is unclear, use the closest match and say which one in one line of internal notes. Do not ask about it.

Upstream stateEnricher action
Decision answeredAlready answered. Do not re-ask. Write it into the brief as a requirement
Decision open / assumed that this issue touchesMust be in the question batch, using the upstream recommended answer
Issue text contradicts an upstream decisionContradiction detector. Ask which outcome wins
No PM artifactsContinue. Run the business decision scan yourself (Phase 3)

Pasted PRD or decision list in chat counts the same as files.

Phase 2 — Codebase check first

Determine whether requested behavior already exists in application code, extends existing screens/flows/modules, or is new.

Scope to what issue/scope touches. Code is internal evidence only. Paths, classes, files, SQL, controllers stay in your notes. The brief states requirements: screens, columns, what the user sees, what must change.

Read when relevant:

  • docs/context/brownfield-map.md
  • docs/context/system-reverse-spec.agent.md (prefer) else system-reverse-spec.md
  • .nextstage-harness/rules/architecture-rules.md
  • docs/context/gitlab-sync-config.md (context only)

Investigation: grep symbols/routes/modules; read controllers/services/views/API/integrations; check tests; note current behavior, extension points, permissions, events/queues, env.

Output (feeds brief):

FindingBrief use
Behavior already in codeSay what the screen does today. No path. Questions only if the request changes that behavior and product intent is still ambiguous
Extension of existing screen/flowName the screen the user opens. Brief says what stays vs what changes
Not foundBrief says the behavior is new on that screen. Still no version framing

Do not run version Clarify. Do not write requirements.md, clarify-contract.md, unknowns-register.md, source/, task files, PO, milestone-as-version, Gate 0 version scope.

Phase 3 — Scarce questions (grill technique)

Borrow technique from ns-spec-driven Clarify (references/clarify-requirements.md, clarify-strict.md): numbered batch; observable product language; blocking vs assumed vs omit; detectors for unresolved value + contradiction.

Do not run version Clarify workflow (no brownfield Step 0.4 halt, no Gate 0, no version artifacts, no skip clarify).

Cross issue/chat text + comments + upstream decisions + code. Each gap: would implementing agent guess product intent? If no guess needed → no question.

Business decision scan (mandatory). Text-only ambiguity scans miss what nobody wrote. For each business rule this issue adds or changes, walk the business dimensions and the ten rule probes in references/question-checklist.md (empty, tie, partial, duplicate, who may, default for existing, undo, user ignores it, which date, where else). Scope the scan to what the issue touches. A one-line UI fix does not get the full list.

Zero blocking gaps: say ready. Do not invent filler.

Developer-lens check before "ready". Reread the draft brief as the coding agent, with no access to this chat. Every business question it would still ask goes into the batch. Every decision made in chat but missing from the brief goes into the brief. Technical questions (algorithm, schema, library) stay out.

Audience

Questions for the human in this chat — product language, not developer/tech lead/ops. Do not @ them.

  • Language: common product/UX (screen, button, filter, what appears, when)
  • Schema, SQL, class, branch, labels, file paths → internal notes only. Never the question list. Never the brief.
Promote vs assume vs drop
CaseAction
Agent cannot verify done without this product factNumbered question plus Recommended
Business decision: plan or consumption, who may do it, default for existing customers, money or rounding, export content, irreversible action, change to behavior customers already validated, personal data or third partiesNumbered question plus Recommended, never a silent assumption, even when the default looks obvious
Safe default (layout, wording, UI pattern already on the screen), and the agent can ship without askingAssumptions — not a question
Already in description/comments/codeDrop
Nice-to-have / engineering tasteDrop or assumption
Question quality
  • Requester-facing, specific screen/flow, answerable in one line or closed choices
  • Blocking only. Numbered 1. 2. … by user journey
  • Cap 15. Merge micro-questions
  • One round of all blockers — not drip Q&A (except missing context in issue mode)
Question shape (mandatory when N ≥ 1)

Chat first. Not a PRD. Each question carries the default the coding agent will apply if accepted.

Order:

  1. Relevant facts — what the screen shows today vs the request, before the list. Columns and behavior the user sees. No paths, classes, or files. No version / PO.
  2. Each question:
Q{n} — {short title}
{What the screen does vs what the request says. One or two sentences.}

➡️ Recommended: {concrete default. Name what changes and what stays.}

Hard stop. Three blocks: title line, body line, then a blank line, then ➡️ on the next line. ➡️ after a period on the same line is invalid. Do not ship a question until the arrow is on its own line.

Invalid: Q1 — Title The screen hides lines. ➡️ Recommended: show them again.

Translate the label with the rest of the reply (Portuguese user: ➡️ Recomendado:).

  1. Closer, same language as the human: reply by number (1: …, 2: …). Yes/no items accept "all yes" or "all recommended". Then close the requirements in this chat. Do not say PRD, version, or PO.

Chat only. This batch is input for the brief. Forbidden inside add_issue_comment body: the questions, Recommended: lines, the reply-by-number closer.

Recommended = safe product default from code. Once accepted, write it as a decision in What changes, Acceptance, or Assumptions. Do not hide the default only in Assumptions while the question is still open in chat.

Detectors (issue grain only)
IdHitClose
Unresolved valueTBD, range, vague adjective on visible behaviorPin in question or assumption + impact in brief
ContradictionIssue vs comments vs upstream decisions vs current codeAsk which product outcome wins. Do not pick silently
Ambiguous termA noun with two plausible meanings ("company", "account", "user", "title")Ask which one, with the likely meaning recommended
Scope leakBehavior here depends on something declared out of scope, or a new rule could change an existing flowAsk whether it applies only here or to the existing flow too, recommending "only here"

Not a detector: missing labels, branch names, GATE 1, milestone-as-version, PO, full-version language.

Translate technical gaps
Internal note (never publish)Ask requester, then write the answer as a requirement
Table/column / class"Does filtering by Club mean only people linked to that club today?"
Base branch / develop-*Do not ask
Missing Team: *Do not ask
Endpoint / SQL join"When Federation and Role both selected, must a person match both or either?"

Good:

Q1 — When the filter applies
Today the date filter runs only after Search.

➡️ Recommended: same — checkbox applies only after Search.

Never ask: Missing Team label; which develop_* branch; which SQL relation.

Out of scope for question list

Labels; base branch; GATE 1; schema/class/env; "how should we implement"; version/PO/milestone-as-version; filler to look thorough.

Scan categories: references/question-checklist.md.

Phase 4 — Implementation brief

Audience = coding agent. Grain = this issue or pasted description. Cut implementation doubt.

Fill references/comment-template.md. Required sections:

SectionContent
Current behaviorWhat the user sees today on the named screens. No files, classes, or paths
What changesRequirement delta. What stays the same
AcceptanceSteps/outcomes the agent can verify on the screen, not OKR/RICE
AssumptionsDecisions and safe defaults already accepted. Impact if wrong

No Files / areas. No Questions heading. Unanswered gaps stay in the chat batch until folded in. Not a version PRD. Not PM OKR/RICE. Not SDD Specify.

Phase 5 — Close requirements, then GitLab gate

N ≥ 1: send the question batch (Phase 3 shape) and stop. Do not post. Do not paste the GitLab body yet.

On reply: fold each answer into the brief.

ReplyBrief
Accepts Recommended / "all yes" / "all recommended"Move that default into What changes or Assumptions. Drop the question
Other answerWrite that decision into What changes / Acceptance. Drop the question
Skipped numberAsk again in chat. Do not invent. Do not preview or post until every asked item is decided

Then paste the closed brief (template). Zero questions in that body.

ModeAfter closed brief on screen
IssueWait. Post add_issue_comment internal: true only after human explicitly validates that draft (yes / post / equivalent). No silent post. Edits → revise preview → wait again
ChatStop. Closed brief is the deliverable. Forbidden: offer to post; "want me to post?"; GitLab comment

N = 0: no question batch. Paste the ready brief, then the same gate.

Posted / previewed body starts with ✅ and a ready line in the user's language (Portuguese: ✅ Brief de implementação. **Pronto.**). No @. Do not leave that line in English when the body is Portuguese.

Do not post while any question is still open. There is no ❌ GitLab variant.

After a real post: chat with link or project_id + issue_iid.

Decisions wider than this issue (chat only, one line after the closed brief): list the decisions just made that also govern other screens or issues, so the requester records them where the rest of the team reads them. Never in the GitLab body.

Do not use set_issue_status, update_issue, create_issue, start_execution_planning.

Language

One language for the whole user-facing output: questions, ➡️ Recommended label, closer, brief headings, first line, footer. Match the user's language. Portuguese in, Portuguese out — headings included (Comportamento atual, O que muda, Aceite, Premissas). Do not mix English titles with a Portuguese body.

Template in references/comment-template.md is the English skeleton. Translate every heading and the footer before showing or posting. Do not copy the English headings verbatim unless the user writes in English.

  • Chat and brief: no file paths, class names, SQL, env vars, controllers. Requirements only (screen, column, behavior)

Anti-patterns

  • Mixed language in one reply (English headings, Portuguese body, or the reverse)
  • File paths, class names, controllers, or a Files / areas section in chat or in the GitLab comment
  • Putting the question batch, Recommended: lines, or "reply by number" into the GitLab comment
  • Auto-post without human validation of the closed brief
  • Chat mode: offering GitLab post
  • Questions one-by-one instead of batched brief
  • Public (non-internal) comment
  • requirements.md / start_execution_planning / version Clarify artifacts
  • Implementation or branches
  • ➡️ on the same line as the question body (sentence. ➡️), or no blank line before it
  • Calling the closed brief a PRD
  • Filler questions; generic "How should this work?"
  • Business decisions (plan, permissions, defaults for existing customers, money, export, undo, personal data) hidden in Assumptions instead of asked with a Recommended answer
  • Re-asking decisions already answered upstream, or ignoring an upstream open decision this issue touches
  • Re-asking facts already in comments
  • @mention in the brief or the GitLab comment (opener, assignee, or a login copied from another comment)
  • Dev questions (table, branch, label, GATE, test path, JSON)
  • Version / PO / milestone-as-version / "full version" framing
  • Using this skill for PM OKR/RICE or SDD version Specify / Clarify-Strict

Relationship to other skills

LayerSkillWhenGrainNot this
PMns-project-managerIntake → RICE, PRD, budget, decision registerOKR, scale, stakeholders, version-wide product decisionsNot this. Its answered decisions are inputs here; its open ones are asked here when this issue touches them
SDD Clarify-Strict/ns-spec-drivenBefore Specify, Gate 0Version on diskTechnique borrowed; artifacts not
Enricher (this)/ns-requirements-enricherBefore coding one issue / pasted scopePer-issue brief + scarce questionsPreview then internal comment or chat-only brief
Specify/ns-spec-driven SpecifyAfter ClarifyVersion requirements.mdNot per-issue brief
Executens-execution-gitlab-issueAfter brief clearImplements issueNot enrichment
Reviewns-reviewerAfter codeDiff reviewNot enrichment
MCPmcp-gitlab-usageMCP callsTool contractsVersion check; not catalog depends

Quick checklist

  • Mode: issue vs chat
  • Issue: read_issue + list_issue_comments. No @mention in the brief
  • Chat: synthesize from user message; no MCP issue load
  • Upstream PM decisions read when present (answered = do not ask; open = ask with its recommendation)
  • Codebase check first: exists / extends / new
  • Business decision scan + rule probes on every rule the issue adds or changes
  • Developer-lens check before saying ready
  • Questions only if implementing agent would guess; else ready
  • Each open question: title line, body line, blank line, then ➡️ on the next line. Same-line sentence. ➡️ is invalid. Closer: reply by number, then close requirements in chat. Not a PRD
  • After answers: closed brief (decisions in What changes / Acceptance / Assumptions). No Files / areas
  • Whole reply in the user's language, headings included. No English/Portuguese mix
  • GitLab body has no questions and no code paths. Issue: post that closed draft only after human yes. Chat: never offer post
  • No version framing, no status change, no code, no one-by-one Q&A

References

FileWhen
references/comment-template.mdPhase 4–5 — brief / GitLab body
references/question-checklist.mdPhase 3 — gap scan
../../ns-harness/references/session-boot.mdSession boot (blocking)

Comments

Markdown supported