The artifact pipeline
Save, search, verify, truncate, scan. Every artifact goes through the same pipeline.
save-artifact.sh
When a phase completes, the agent calls save-artifact.sh with the phase name and a JSON file. The script runs six steps before anything touches disk:
Input JSON
│
├─ 1. Validate → Is it valid JSON? Does it have required fields?
│ Required: phase, summary. Rejects malformed input.
│
├─ 2. Secret scan → Does any value match a known secret pattern?
│ Redacts matches, logs a warning.
│
├─ 3. Truncate → Is the artifact larger than the findings limit?
│ Default: 50 findings max. Configurable via NANOSTACK_MAX_FINDINGS.
│
├─ 4. Enrich → Adds timestamp, project name, branch, git SHA.
│ Project = basename of git root. Branch = current HEAD.
│
├─ 5. Integrity → Computes SHA-256 of the final content.
│ Stored in the "integrity" field.
│
└─ 6. Write → Writes to the store path.
Filename: {phase}-{timestamp}.jsonUsage:
# Save a review artifact bin/save-artifact.sh review review-findings.json # Save with a custom store path NANOSTACK_STORE=/shared/artifacts bin/save-artifact.sh review findings.json # Output on success: # Saved: .nanostack/artifacts/review-2026-03-28T14:22:31Z.json (2.3KB) # Integrity: sha256:a3f2b8c1d4e5f6...
find-artifact.sh
Locates the most recent artifact for a phase. The search process handles large artifact stores efficiently:
Store directory
│
├─ 1. List files → ls the store path, filter by phase prefix.
│ Only files matching {phase}-*.json.
│
├─ 2. Filter age → Exclude artifacts older than --max-age (default: 30d).
│ Prevents stale context from previous sprints.
│
├─ 3. Pre-filter → Match --project flag against filename or content.
│ Skips artifacts from other projects.
│
├─ 4. Validate → jq check: is it valid JSON with an integrity field?
│ Skips corrupted files silently.
│
├─ 5. Sort → Sort by timestamp field, descending.
│
└─ 6. Return → Output the path to the most recent match.Usage:
# Find the latest review artifact bin/find-artifact.sh --phase review # Find with project scope bin/find-artifact.sh --phase review --project nanostack-site # Find and verify integrity bin/find-artifact.sh --phase review --verify # Output: .nanostack/artifacts/review-2026-03-28T14:22:31Z.json (verified) # If integrity check fails: # WARNING: integrity mismatch for review-2026-03-28T14:22:31Z.json # Expected: sha256:a3f2b8c1... # Got: sha256:7e9d1a4b...
find-solution.sh
Searches the know-how store for previously documented solutions. Unlike find-artifact.sh, which returns the most recent match, find-solution.sh ranks results by relevance using a scoring formula:
Ranked by: severity critical=4, high=3, medium=2, low=1 tag matches +1 per matching word recency +1 if under 30 days old staleness -3 if all referenced files deleted, -1 if some deleted
Usage:
# Find solutions for race conditions bin/find-solution.sh --type "race-condition" # Find with tag filtering bin/find-solution.sh --type "race-condition" --tag "concurrency" --tag "locks" # Output (ranked): # 1. [score:12] Race condition in sprint lock acquisition (2026-03-25) # .nanostack/know-how/solutions/sprint-lock-race.json # 2. [score:8] Database connection pool exhaustion (2026-03-10) # .nanostack/know-how/solutions/db-pool-race.json
Secret scanning
Before any artifact is written, save-artifact.shscans every string value for known secret patterns. Matches are redacted in place — the first 8 characters are preserved for debugging, the rest is replaced with [REDACTED].
Pattern Example match Redacted output ───────────────────────────────────────────────────────────────── sk_live_ sk_live_4eC39HqLyjWD... sk_live_[REDACTED] sk_test_ sk_test_BQokikJO... sk_test_[REDACTED] AKIA AKIAIOSFODNN7EXAMPLE AKIAIOOS[REDACTED] ghp_ ghp_xxxxxxxxxxxx... ghp_xxxx[REDACTED] xoxb- xoxb-1234-5678-abcdef xoxb-123[REDACTED] sk-ant- sk-ant-api03-xxxxx... sk-ant-a[REDACTED] -----BEGIN.*KEY -----BEGIN RSA PRIVATE KEY [KEY_REDACTED] passwords*[:=] password: hunter2 password: [REDACTED]
The scan runs on every value in the JSON tree, including nested objects and arrays. If a secret is found, the artifact is still saved (with the redaction), and a warning is printed to stderr:
WARNING: secret pattern detected in artifact (field: config.api_key) Pattern: sk_live_ Redacted in output. Original value was NOT written to disk.
The secret scanner is not configurable per skill. It runs on every artifact, every time, with no opt-out. If you need to store a value that looks like a secret but is not one, wrap it in a safe: prefix and the scanner will skip it.