Alignment Reader
Thin wrapper around ${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh. The script parses alignment.md per the canonical grammar in references/alignment-contract.md v1.4 and emits structured JSON. This skill gives the parser a Skill-tool-callable name and documents the invocation contract.
Contract
Input: one argument — absolute path to a task folder (the one containing alignment.md).
Output: single JSON object to stdout per references/alignment-contract.md. Exit code always 0 except for unrecoverable read failures (permission denied, IO error).
Fields:
file_exists — boolean
file_path — path to expected alignment.md
task_name — from H1 # Alignment: <name> line (or **Task:** metadata fallback)
created — from **Created:** <YYYY-MM-DD> metadata
schema_version — JSON string, currently "1.0"
sections.{task_level,phase_1,phase_2,phase_3} — each either {present: false} or a populated object with goal, expected_result, success_criteria[], success_criteria_prose, non_goals[], non_goals_prose, extras[], fields_missing[]. The two *_prose fields hold the raw body when it was written as prose instead of a list, and are null otherwise.
- Each
success_criteria[] item: {text, checked, verification, author, id}. verification is a string or null (v1.1, from — verify: <how>). author is "owner", "designer", or null (v1.3, from — by: <owner|designer>) — null means no author was recorded, not that the owner wrote it. id is "c<n>" or null (v1.4, from — id: c<n>); null means no id was recorded on that criterion.
A null id does not by itself send a resolver to task.md. scripts/contract-resolve.sh reads Task-Level ids only. It resolves from alignment.md when at least one Task-Level criterion carries an id, and reports the rest as unmarked — criteria that are invisible to coverage. It falls back to task.md only when no Task-Level criterion carries one. An id on a phase section is parsed and returned here, but no resolver reads it, so putting ids on phase criteria has no effect.
warnings[] — array of {code, …} observations
Defensive posture (never throws)
| Input state |
Warning code |
alignment.md missing |
file_missing |
| Unrecognized H2 heading |
unknown_section |
| Recognized section missing a canonical H3 |
missing_field |
| Recognized section has an unexpected H3 |
unknown_field |
| Canonical H3 present but body empty |
empty_field |
Success criteria body is prose, not a - [ ] task-list |
success_criteria_not_checklist |
Non-goals body is prose, not a bulleted list |
non_goals_not_bulleted |
— by: marker present with a value other than owner/designer |
criterion_author_unrecognized |
— id: marker present with a value that is not c<n> (or a near-miss such as a wrong dash) |
criterion_id_unrecognized |
| Two criteria anywhere in the document carry the same id — the reader is the only place every id is seen together, so detection spans sections |
criterion_id_duplicate |
| Recognized H2 present but the whole section body is empty |
section_empty_stub |
| Recognized H2 present with a body that matched no canonical H3 |
section_unparsed_body |
| Unrecoverable read failure (permission, IO) |
error (only case with non-zero exit) |
Invocation
"${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh" "/abs/path/to/task/folder"
Parse with jq. Examples:
OUT=$("${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh" "$TASK_DIR")
EXISTS=$(jq -r '.file_exists' <<<"$OUT")
TASK_GOAL=$(jq -r '.sections.task_level.goal // empty' <<<"$OUT")
CRITERIA_COUNT=$(jq '.sections.task_level.success_criteria | length' <<<"$OUT")
# Any warnings at all?
jq -e '.warnings | length > 0' <<<"$OUT" >/dev/null && echo "warnings present"
Phase-level sections
Phase sections (phase_1, phase_2, phase_3) are OPTIONAL. A new task's alignment.md typically contains only ## Task-Level; phase sections are appended as the task enters each phase (by /research, /design, /implement).
Consumers checking "is the Phase 2 contract authored yet?" should test .sections.phase_2.present == true — not whether the section object exists (it always exists as {present: false} stub).
Consumers (v3.12.0+)
/ai-dev-assistant:scope — read current state to decide overwrite/edit/cancel
/ai-dev-assistant:research — pre-analysis hook checks whether alignment.md already exists; Phase 1 sub-step appends Phase 1 section
/ai-dev-assistant:design — Phase 2 sub-step appends Phase 2 section
/ai-dev-assistant:implement — Phase 3 sub-step appends Phase 3 section
/ai-dev-assistant:complete — (future) may surface unchecked success criteria
/ai-dev-assistant:review — Spec axis reads the Task-Level contract
analysis-agent — indirectly informs scope_contract_recommended signal (caller reads this skill's output)
spec-axis-reviewer — judges a change against the Task-Level success criteria
scripts/contract-resolve.sh — resolves the criteria list, alignment.md Task-Level ids first, then task.md
scripts/criterion-provenance.sh — reads the — by: author marker
Future consumers needing scope-contract data should call this skill rather than parsing alignment.md directly.
Do NOT
- Do not write to
alignment.md from this skill. Reading only. Writes happen in the command flows (/scope, phase sub-steps).
- Do not treat non-empty
warnings[] as a blocking error — warnings are observations; the parser always returns a best-effort result.
- Do not duplicate the parsing logic elsewhere. Call this skill or the script.
- Do not assume phase sections exist. Always guard on
.sections.phase_N.present.
See also
${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh — the parser
references/alignment-contract.md — canonical grammar, warning codes, JSON output contract
project-state-reader skill (v1.0.0) — same design pattern, project-level metadata
task-frontmatter-reader skill (v2.0.0) — same design pattern, task frontmatter
1---2name: alignment-reader3description: Use when a framework command needs to parse a task's alignment.md (the scope contract — Goal / Expected result / Success criteria / Non-goals per section). Reads defensively via scripts/alignment-read.sh and returns structured JSON with warnings. Never blocks on malformed input.4---56# Alignment Reader78Thin wrapper around `${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh`. The script parses `alignment.md` per the canonical grammar in `references/alignment-contract.md` v1.4 and emits structured JSON. This skill gives the parser a Skill-tool-callable name and documents the invocation contract.910## Contract1112**Input:** one argument — absolute path to a task folder (the one containing `alignment.md`).1314**Output:** single JSON object to stdout per `references/alignment-contract.md`. Exit code always 0 except for unrecoverable read failures (permission denied, IO error).1516Fields:17- `file_exists` — boolean18- `file_path` — path to expected `alignment.md`19- `task_name` — from H1 `# Alignment: <name>` line (or `**Task:**` metadata fallback)20- `created` — from `**Created:** <YYYY-MM-DD>` metadata21- `schema_version` — JSON string, currently `"1.0"`22- `sections.{task_level,phase_1,phase_2,phase_3}` — each either `{present: false}` or a populated object with `goal`, `expected_result`, `success_criteria[]`, `success_criteria_prose`, `non_goals[]`, `non_goals_prose`, `extras[]`, `fields_missing[]`. The two `*_prose` fields hold the raw body when it was written as prose instead of a list, and are `null` otherwise.23 - Each `success_criteria[]` item: `{text, checked, verification, author, id}`. `verification` is a string or `null` (v1.1, from ` — verify: <how>`). `author` is `"owner"`, `"designer"`, or `null` (v1.3, from ` — by: <owner|designer>`) — `null` means no author was recorded, not that the owner wrote it. `id` is `"c<n>"` or `null` (v1.4, from ` — id: c<n>`); `null` means no id was recorded on that criterion.2425**A `null` id does not by itself send a resolver to `task.md`.** `scripts/contract-resolve.sh` reads **Task-Level ids only**. It resolves from `alignment.md` when at least one Task-Level criterion carries an id, and reports the rest as `unmarked` — criteria that are invisible to coverage. It falls back to `task.md` only when *no* Task-Level criterion carries one. An id on a phase section is parsed and returned here, but no resolver reads it, so putting ids on phase criteria has no effect.26- `warnings[]` — array of `{code, …}` observations2728## Defensive posture (never throws)2930| Input state | Warning code |31|---|---|32| `alignment.md` missing | `file_missing` |33| Unrecognized H2 heading | `unknown_section` |34| Recognized section missing a canonical H3 | `missing_field` |35| Recognized section has an unexpected H3 | `unknown_field` |36| Canonical H3 present but body empty | `empty_field` |37| `Success criteria` body is prose, not a `- [ ]` task-list | `success_criteria_not_checklist` |38| `Non-goals` body is prose, not a bulleted list | `non_goals_not_bulleted` |39| ` — by:` marker present with a value other than `owner`/`designer` | `criterion_author_unrecognized` |40| ` — id:` marker present with a value that is not `c<n>` (or a near-miss such as a wrong dash) | `criterion_id_unrecognized` |41| Two criteria anywhere in the document carry the same id — the reader is the only place every id is seen together, so detection spans sections | `criterion_id_duplicate` |42| Recognized H2 present but the whole section body is empty | `section_empty_stub` |43| Recognized H2 present with a body that matched no canonical H3 | `section_unparsed_body` |44| Unrecoverable read failure (permission, IO) | `error` (only case with non-zero exit) |4546## Invocation4748```bash49"${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh" "/abs/path/to/task/folder"50```5152Parse with `jq`. Examples:5354```bash55OUT=$("${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh" "$TASK_DIR")56EXISTS=$(jq -r '.file_exists' <<<"$OUT")57TASK_GOAL=$(jq -r '.sections.task_level.goal // empty' <<<"$OUT")58CRITERIA_COUNT=$(jq '.sections.task_level.success_criteria | length' <<<"$OUT")59# Any warnings at all?60jq -e '.warnings | length > 0' <<<"$OUT" >/dev/null && echo "warnings present"61```6263## Phase-level sections6465Phase sections (`phase_1`, `phase_2`, `phase_3`) are OPTIONAL. A new task's `alignment.md` typically contains only `## Task-Level`; phase sections are appended as the task enters each phase (by `/research`, `/design`, `/implement`).6667Consumers checking "is the Phase 2 contract authored yet?" should test `.sections.phase_2.present == true` — not whether the section object exists (it always exists as `{present: false}` stub).6869## Consumers (v3.12.0+)7071- `/ai-dev-assistant:scope` — read current state to decide overwrite/edit/cancel72- `/ai-dev-assistant:research` — pre-analysis hook checks whether `alignment.md` already exists; Phase 1 sub-step appends Phase 1 section73- `/ai-dev-assistant:design` — Phase 2 sub-step appends Phase 2 section74- `/ai-dev-assistant:implement` — Phase 3 sub-step appends Phase 3 section75- `/ai-dev-assistant:complete` — (future) may surface unchecked success criteria76- `/ai-dev-assistant:review` — Spec axis reads the Task-Level contract77- `analysis-agent` — indirectly informs `scope_contract_recommended` signal (caller reads this skill's output)78- `spec-axis-reviewer` — judges a change against the Task-Level success criteria79- `scripts/contract-resolve.sh` — resolves the criteria list, `alignment.md` Task-Level ids first, then `task.md`80- `scripts/criterion-provenance.sh` — reads the ` — by:` author marker8182Future consumers needing scope-contract data should call this skill rather than parsing `alignment.md` directly.8384## Do NOT8586- Do not write to `alignment.md` from this skill. Reading only. Writes happen in the command flows (`/scope`, phase sub-steps).87- Do not treat non-empty `warnings[]` as a blocking error — warnings are observations; the parser always returns a best-effort result.88- Do not duplicate the parsing logic elsewhere. Call this skill or the script.89- Do not assume phase sections exist. Always guard on `.sections.phase_N.present`.9091## See also9293- `${CLAUDE_PLUGIN_ROOT}/scripts/alignment-read.sh` — the parser94- `references/alignment-contract.md` — canonical grammar, warning codes, JSON output contract95- `project-state-reader` skill (v1.0.0) — same design pattern, project-level metadata96- `task-frontmatter-reader` skill (v2.0.0) — same design pattern, task frontmatter