| name | evidence-pack |
| description | Assemble per-release evidence packages from artifacts already produced elsewhere in the project (traceability matrix, CI logs, PR review records, signed-commit lists, external research citations, risk file). Output is a self-contained directory under evidence/<version>/ containing a manifest.yaml, per-artifact subdirectories, and an INTEGRITY checksum. Read-mostly with respect to source code: writes only under evidence/. Opt-in gate: no-op when the consumer project has no evidence/ parent directory, so non-regulated repos are unaffected. Idempotent: refuses to overwrite an existing pack unless --force is passed. |
| argument-hint | <version> [--include <pattern>] [--exclude <pattern>] [--dry-run] [--force] |
| user-invocable | true |
| disable-model-invocation | true |
| allowed-tools | ["Bash","Read","Write","Glob","Grep"] |
| loop_safe | false |
| max_iterations | 1 |
| halt_conditions | [{"type":"success","expr":"evidence/<version>/manifest.yaml and INTEGRITY written; per-artifact subdirectories populated"},{"type":"success","expr":"no-op exit when evidence/ parent directory is absent"},{"type":"success","expr":"dry-run exit after printing the manifest plan without writing"},{"type":"failure","expr":"evidence/<version>/ already exists and --force is not set"},{"type":"failure","expr":"any required collector errors out (matrix copy, gh, git) and --include did not exclude that kind"},{"type":"failure","expr":"version argument missing or not a valid semantic version / tag"}] |
| on_halt | Print collected/skipped artifact summary and exit non-zero on failure, zero on success or no-op |
| tiers | {"light":{"ref_docs":[],"deep_checks":false},"standard":{"ref_docs":["manifest","sources"],"deep_checks":true},"deep":{"ref_docs":["manifest","sources"],"deep_checks":true}} |
| default_tier | standard |
| iso_class | A |
| applies_at_or_above | A |
evidence-pack Skill
Assemble per-release evidence packages for projects that have adopted the regulated-industry
track. The skill is the release-time partner of the traceability skill: where traceability
maintains the per-commit matrix, evidence-pack packages that matrix together with surrounding
artifacts (CI logs, PR reviews, signed commits, research citations, risk file) into a single
directory an external auditor can consume without further stitching.
The skill is a Design History File (DHF) generator in spirit. It does not invent evidence; it
collects what already exists.
Usage
/evidence-pack v1.2.0 # Build full pack for tag v1.2.0
/evidence-pack v1.2.0 --include matrix,ci_run_log # Only collect specific kinds
/evidence-pack v1.2.0 --exclude pr_review # Collect everything except PR review records
/evidence-pack v1.2.0 --dry-run # Plan only; print what would be collected and exit
/evidence-pack v1.2.0 --force # Overwrite an existing evidence/v1.2.0 pack
Exactly one positional argument is required: the release version or git tag. Flags are optional.
Arguments
| Position / Flag | Behavior |
|---|
<version> (positional, required) | Release identifier used as the output subdirectory name. Accepts semantic versions (v1.2.0), date-tagged releases (2026-05-04), or any other ASCII slug matching [A-Za-z0-9._-]+. Refuses values containing path separators or whitespace. |
--include <pattern> | Comma-separated allowlist of artifact kind values to collect. When set, all kinds not in the list are skipped. See reference/manifest-schema.md for valid kinds. |
--exclude <pattern> | Comma-separated denylist of artifact kind values to skip. Mutually independent from --include; if both are set, the include list is applied first, then the exclude list removes from it. |
--dry-run | Run the planning phase only. Print the manifest plan (kinds, sources, collection commands) to stdout and exit zero. No files are written. Useful for previewing in CI before allowing real collection. |
--force | Overwrite an existing evidence/<version>/ directory. Without --force, the skill refuses to clobber a previously generated pack and exits non-zero (idempotency contract). |
Inputs
| Path | Required | Purpose |
|---|
evidence/ (parent dir at repo root) | Yes (gate) | Opt-in marker. Skill is a no-op when this directory is absent. |
docs/.index/traceability.yaml | Optional | Verbatim copy collected as the matrix artifact. Skipped when absent. |
risk-file/ | Optional | Recursively collected as the risk_file artifact. Skipped when absent. |
docs/research/ | Optional | Citation files collected as research_artifact entries. Skipped when absent. |
gh CLI authenticated to the current repo | Yes for ci_run_log and pr_review kinds | Used to query workflow runs and PR review history. Skipped (with one info line per kind) if gh is not on PATH. |
git history with the release tag reachable | Yes for signed_commits kind | Used to enumerate commits between the previous tag and <version>. |
The detailed source-to-artifact mapping is documented in reference/source-mapping.md.
Outputs
All outputs live under evidence/<version>/ (relative to the consumer project root):
| Path | Format | Purpose |
|---|
evidence/<version>/manifest.yaml | YAML | Top-level manifest. One entry per collected artifact. Schema: reference/manifest-schema.md. |
evidence/<version>/INTEGRITY | Plain text | Single-line sha256:<hex> over the sorted manifest entries. Detect tampering of the manifest itself. |
evidence/<version>/<kind>/... | Varies by kind | Per-artifact subdirectory. One subdirectory per kind value in the manifest. Layout per kind: see reference/source-mapping.md. |
The skill writes manifest.yaml and INTEGRITY atomically: each goes to a sibling *.tmp
file and is renamed on success. A failed run never leaves a half-written manifest.
Opt-in Gate
The skill is purely additive and must not break repos that have not adopted the regulated track.
if [[ ! -d evidence ]]; then
echo "evidence-pack: ./evidence directory absent -- skill is a no-op for this repo"
exit 0
fi
This check runs before any other phase. The exit code is 0 so CI invocations on
non-regulated repos do not fail. To opt in, a consumer project creates an empty evidence/
directory at the repo root (a .gitkeep is sufficient) and tracks the per-release subdirectories
that the skill produces.
Instructions
Phase 0: Validate Environment
- Confirm
evidence/ exists at the repo root; if not, print the no-op message and exit 0.
- Validate
<version> matches ^[A-Za-z0-9._-]+$. If it contains a path separator,
whitespace, or is empty, exit non-zero with a clear message.
- If
evidence/<version>/ already exists and --force is not set, exit non-zero with the
path and the suggestion to pass --force.
- Resolve git HEAD (
git rev-parse HEAD) and the current tag (git describe --tags --exact-match
or git rev-parse --short HEAD as fallback). Record both for the manifest header.
- Detect optional collectors:
gh on PATH and authenticated (probe with gh auth status).
git available and the current directory is a git work tree.
sha256sum (Linux) or shasum -a 256 (macOS) for checksumming.
Missing optional collectors do not fail the skill; they downgrade the affected kinds to
skipped-with-reason in the manifest.
Phase 1: Plan the Manifest
Reference: reference/manifest-schema.md defines the row shape of each manifest entry, and
reference/source-mapping.md defines per-kind collection commands and target subdirectories.
- Build the candidate kind list from the schema (
matrix, ci_run_log, pr_review,
signed_commits, research_artifact, risk_file).
- Apply
--include if set: keep only kinds in the include list.
- Apply
--exclude if set: remove kinds in the exclude list.
- For each remaining kind, run the source mapping's "presence check" (e.g.
[[ -f docs/.index/traceability.yaml ]] for matrix). Kinds whose source is absent are
recorded as skipped: source_absent in the manifest plan rather than triggering an error.
- Emit the planned manifest (header + per-kind plan rows) to stdout.
Phase 2: Dry-run Exit Point
If --dry-run is set, exit zero immediately after Phase 1. Print the planned manifest as
YAML to stdout but do not create evidence/<version>/.
Phase 3: Collect Artifacts
For each kind that survived Phase 1 with a present source, run the collector defined in
reference/source-mapping.md and write the output under evidence/<version>/<kind>/. The
collector for each kind is documented there; the skill body must not invent new collection
strategies.
For each artifact written:
- Compute
sha256 of the file (or, for directory-shaped kinds like risk_file or
research_artifact, the sha256 of a deterministic listing produced by
find <dir> -type f | sort | xargs sha256sum).
- Record
collected_at as the UTC ISO 8601 timestamp at which the collector finished.
- Record
source as the original repo-relative path or the gh / git command that
produced the artifact (verbatim, including arguments). This is the audit trail.
- Record
related_clauses as the list of clause IDs the artifact bears on (e.g. the
matrix maps to IEC-62304-5.2.6 and ISO-13485-7.3.6; CI run logs map to
IEC-62304-5.5.5 and ISO-13485-7.3.6). The mapping table lives in
reference/source-mapping.md.
If a collector errors out (non-zero exit, network failure, permission denied), the entry is
recorded as failed: <message> rather than silently dropped. The overall skill exits
non-zero only when a collector fails for a kind that was explicitly requested via --include;
failures for default-collected kinds emit a warning but allow the pack to be produced
(the manifest will mark the kind as failed so an auditor can see the gap).
Phase 4: Write Manifest and Integrity File
Skip if --dry-run was already handled in Phase 2.
- Write
evidence/<version>/manifest.yaml.tmp with the schema documented in
reference/manifest-schema.md. Sort entries by kind then source for stable diffs.
- Compute
sha256 over the canonical (sorted, no extra whitespace) manifest content.
Write the result to evidence/<version>/INTEGRITY.tmp as a single line:
sha256:<hex>\n.
- On success, rename both
*.tmp files to their final names. On any error, delete the
*.tmp files plus any partial per-artifact subdirectories that this invocation created
and exit non-zero. (Existing artifacts under evidence/<version>/ from a prior --force
overwrite are left alone unless this invocation produced them.)
Phase 5: Report
Emit a summary block on stdout:
## Evidence Pack Generated
| Metric | Value |
|--------|-------|
| Version | <version> |
| Kinds collected | N |
| Kinds skipped | N (source_absent) |
| Kinds failed | N |
| manifest.yaml | X bytes |
| INTEGRITY sha256 | <16-char-prefix>... |
| Output | evidence/<version>/ |
Append a per-kind table when --dry-run was passed or when at least one kind failed.
Output
The skill produces the per-version evidence directory plus the on-stdout summary. No other
files in the consumer project are modified -- in particular, the skill never edits source
code, never runs builds, and never publishes to external systems. Submission to an external
eQMS is explicitly out of scope (see issue #595 "Out of Scope").
Error Handling
| Condition | Action |
|---|
evidence/ parent absent | No-op exit 0 (opt-in gate, see Phase 0). |
<version> argument missing or invalid | Exit non-zero with usage hint. |
evidence/<version>/ exists and --force not set | Exit non-zero with the existing path and --force suggestion. |
gh not authenticated (kinds ci_run_log, pr_review) | Mark affected kinds as skipped: tool_unavailable; do not fail the skill. |
Collector for an --include-requested kind fails | Exit non-zero after writing a partial manifest that records the failure. |
| Collector for a default-collected kind fails | Mark the kind as failed: <message> in the manifest; continue. |
| Write step fails (permission, disk) | Delete *.tmp files and any subdirectories this invocation created; report the path; exit non-zero. |
<version> already collected (without --force) | See above; refusal is the correct behavior to preserve audit history. |
Policies
Side Effects and Loop-Safety
This skill is loop_safe: false. Each invocation produces an immutable per-release artifact
directory, and re-running for the same <version> either refuses (default) or destructively
overwrites (--force). Wrapping in /loop would either no-op after the first iteration or
churn the same directory; both outcomes are wrong.
The idempotency contract is "one pack per version" rather than "no-side-effect retry":
existing packs are evidence in their own right and must not be silently replaced.
Command-Specific Rules
| Item | Rule |
|---|
| Inputs | Only existing artifacts produced by other tools (matrix from traceability, CI logs from gh, etc.). The skill never invents data. |
| Outputs | Only files under evidence/<version>/. No other directory is touched. |
| Opt-in | Absent evidence/ parent is a no-op exit 0, never a failure. |
| Atomicity | Manifest and integrity file go to *.tmp first, then rename on success. Failure deletes them. |
| Idempotency | Re-running for an existing <version> is refused unless --force is passed. |
| External submission | Never. Submission to eQMS / regulator portals is out of scope. |
| Cryptographic signing | Out of scope. The INTEGRITY checksum protects against accidental tampering only; it is not a signed attestation. |
How Other Components Use the Pack
| Consumer | Use |
|---|
| External auditor | Reads evidence/<version>/manifest.yaml and walks per-kind subdirectories. The INTEGRITY file lets them detect post-hoc edits to the manifest. |
release skill (future P2) | Could invoke evidence-pack <version> automatically after a release tag is created. |
pr-work skill (future P2) | Could surface "evidence pack updated" as part of release-candidate PR descriptions. |
traceability skill (sibling P0-1) | Produces docs/.index/traceability.yaml which becomes the matrix artifact in this pack. |
References
- Manifest schema:
reference/manifest-schema.md
- Per-kind source mapping:
reference/source-mapping.md
- Sibling matrix producer:
global/skills/_internal/traceability/SKILL.md
- Compliance clause source files:
compliance/iec-62304.md, compliance/iso-13485.md
- Parent epic:
kcenon/claude-config#588
- Originating issue:
kcenon/claude-config#595