Install
$ agentstack add skill-itsalt-nacl-nacl-migrate-ba ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
/nacl-migrate-ba — BA Markdown → Neo4j
Role
You delegate parsing, validation, and Cypher generation to stdlib Python scripts under $NACL_HOME/nacl-migrate-ba/scripts/. You never parse Markdown yourself; the scripts own that entirely. Your own job is:
- Run the scripts in order.
- Read their JSON outputs.
- Execute the Cypher plan against Neo4j via
mcp__neo4j__write-cypher. - Gather live counts via
mcp__neo4j__read-cypherand hand them toaudit_ba.py. - Present results and errors to the user in plain language.
The scripts produce structured JSON with status, error_code, message, and remediation. When a script fails, print the message and remediation verbatim.
Invocation
/nacl-migrate-ba [project_path] [--dry-run] [--adapter=]
| Parameter | Required | Description | |---|---|---| | project_path | No | Project root (default: cwd). Must contain docs/. | | --dry-run | No | Run parse + validate + Cypher generation; skip all Neo4j writes and audit. | | --adapter | No | Force an adapter (inline-table-v1 \| frontmatter-v1). Default: auto-detect. |
Prelude — locate NaCl home and verify Python
Run this first. Emit the messages verbatim on failure.
# Resolve $NACL_HOME
if [ -z "$NACL_HOME" ]; then
for candidate in "$HOME/projects/NaCl" "$HOME/NaCl" "$HOME/code/NaCl" "$HOME/src/NaCl"; do
if [ -f "$candidate/nacl-migrate-core/nacl_migrate_core/__init__.py" ]; then
export NACL_HOME="$candidate"
break
fi
done
fi
if [ -z "$NACL_HOME" ] || [ ! -f "$NACL_HOME/nacl-migrate-core/nacl_migrate_core/__init__.py" ]; then
echo "Unable to locate NaCl repo. Set NACL_HOME=/path/to/NaCl and retry." >&2
exit 1
fi
# Verify Python 3.11+
python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3,11) else 1)' 2>/dev/null \
|| { echo "Python 3.11+ required. On macOS: brew install python@3.11"; exit 1; }
All subsequent commands use $NACL_HOME/nacl-migrate-ba/scripts/....
Soft preflight (direct invocation)
When invoked directly (i.e. not via the /nacl-migrate orchestrator), run a quick ID-pattern scan and warn — but do not block — if any token in the project's filenames or YAML frontmatter does not match a known adapter pattern. The orchestrator path runs the same scan at Phase A.5 with a hard gate; this version is non-blocking so a single-layer rerun stays ergonomic.
mkdir -p .nacl-migrate
python3 "$NACL_HOME/nacl-migrate-ba/scripts/preflight_ids.py" \
--project "$PWD" \
--output .nacl-migrate/preflight.json || true
Exit code 1 from the script means unknown patterns were found. Surface the report's patterns_unknown list to the user with this message:
> Preflight surfaced N unknown ID-shaped tokens. These will likely be > dropped at parse. Review .nacl-migrate/preflight.json and either > widen an adapter (recommended) or pass --force to proceed anyway.
If the user passes --force, continue. Otherwise stop.
Preconditions
config.yamland.mcp.jsonexist at project root (produced bynacl-init).- Neo4j is reachable via
mcp__neo4j__get-schema— run it once before Phase 1 and stop if it errors. - At least one BA folder exists under
docs/. If none, skip this skill with:
"No BA layer detected under docs/. This project may be SA-only. Skipping nacl-migrate-ba."
Phase 0 — Detect adapter
python3 "$NACL_HOME/nacl-migrate-ba/scripts/detect_ba.py" \
--project "$PWD" \
--output .nacl-migrate/detect-ba.json
Read the JSON.
status: "ok"+chosen: ""+ambiguous: false→ proceed with that adapter.ambiguous: true→ show the candidate list to the user; ask them to pass--adapter=.chosen: null+ambiguous: false→ no adapter matches; stop and ask the user to add a new adapter pernacl-migrate-core/README.md.reason: "no_ba_files_found"→ skip the skill (see preconditions above).status: "error"→ printmessage+remediationand stop.
If --adapter was passed, skip this phase and use the user-provided value.
Phase 1 — Parse Markdown → IR
python3 "$NACL_HOME/nacl-migrate-ba/scripts/parse_ba.py" \
--project "$PWD" \
--adapter "" \
--output .nacl-migrate/ba-ir.json
Expected stdout: a counts table and (optionally) a warnings tally. Confirm warnings: 0 or surface each warning code to the user.
On error exit (code ≠ 0), surface message + remediation and stop.
Phase 2 — Validate IR
python3 "$NACL_HOME/nacl-migrate-ba/scripts/validate_ba_ir.py" \
--input .nacl-migrate/ba-ir.json \
--output .nacl-migrate/ba-validation.json
Validator runs 10 checks (V1–V10) covering ID uniqueness, reference integrity, orphan states, source-file presence.
- Exit 0 → all pass, continue.
- Exit 1 → at least one check failed. Print the failure list from stdout
and stop. If the user wants to proceed anyway, they must fix the IR or rerun with adapter adjustments.
Phase 3 — Generate Cypher plan
python3 "$NACL_HOME/nacl-migrate-ba/scripts/generate_ba_cypher.py" \
--input .nacl-migrate/ba-ir.json \
--output .nacl-migrate/ba-cypher.json
Plan is an array of batches, each with cypher, params, kind (node or edge) and label (human-readable). Batches are sized so one MCP call per batch is sub-second.
If --dry-run: stop here. Report the plan's summary to the user and exit.
Phase 4 — Execute Cypher against Neo4j
Preflight:
mcp__neo4j__get-schema() # must succeed
If it errors, stop and tell the user to start the Neo4j stack.
Execute:
Read .nacl-migrate/ba-cypher.json. For each batch in batches, call:
mcp__neo4j__write-cypher(
query = batch.cypher,
params = batch.params
)
Report progress per batch: [i/N] {label} rows={len(params.rows)} ok (or fail: ).
On any batch failure:
- Log the batch index, label, and the Cypher error.
- Stop execution. The partial graph is idempotent — rerunning after a fix
will MERGE over the already-written nodes without duplicating.
Phase 5 — Gather live counts
Query Neo4j via mcp__neo4j__read-cypher for every node label and relationship type listed in audit_ba.py (keep this in sync — the script declares canonical lists).
For each node label:
MATCH (n:{Label}) RETURN count(n) AS n
For each relationship type:
MATCH ()-[r:{TYPE}]->() RETURN count(r) AS n
Write the results to .nacl-migrate/ba-live-counts.json:
{
"nodes": {"BusinessProcess": 10, "WorkflowStep": 74, ...},
"relationships": {"CONTAINS": 10, "HAS_STEP": 74, ...}
}
Batch the reads if convenient (single UNION query) — the shape of the output file is the only hard requirement.
Phase 6 — Audit
python3 "$NACL_HOME/nacl-migrate-ba/scripts/audit_ba.py" \
--ir .nacl-migrate/ba-ir.json \
--counts .nacl-migrate/ba-live-counts.json \
--output .nacl-migrate/ba-audit.json
Exit 0 → "All counts match." — migration is clean. Exit 1 → at least one mismatch. Surface the mismatch list verbatim and ask the user to investigate before declaring migration complete.
Phase 7 — Report
Write MIGRATION-REPORT-BA.md at project root. Template:
# BA Migration Report
**Project:** {project_path}
**Adapter:** {adapter}
**Ran at:** {ISO timestamp}
## IR counts vs live Neo4j
| Node label | IR | Live | Status |
| ... | ... | ... | ... |
(Copy the table from ba-audit.json.)
## Relationships
| Type | IR | Live | Status |
| ... | ... | ... | ... |
## Warnings during parse
{list from ba-ir.json warnings[], or "none"}
## Validation
{summary from ba-validation.json: passed/failed, any failures}
## Next steps
- If audit is clean: proceed to `/nacl-migrate-sa` (if SA layer exists)
or continue to `/nacl-migrate` aggregation.
- If audit has mismatches: investigate each mismatched label via Cypher.
Rerun after fixes — writes are idempotent.
Idempotency
- All Neo4j writes are
MERGEkeyed on canonical IDs; safe to re-run. - Re-detection and re-parse produce the same IR (modulo timestamps).
- If the adapter or the source Markdown changes and yields a different
canonical ID for a given source file, the old node becomes orphaned. audit_ba.py detects this as a count mismatch — investigate rather than auto-delete.
Error handling summary
| Situation | Response | |---|---| | Prelude can't find $NACL_HOME | Stop. Ask user to export NACL_HOME. | | Python < 3.11 | Stop. Ask user to upgrade. | | Adapter unknown / ambiguous | Stop. Present candidates. | | Parse warnings | Continue. Surface tally to user. | | Validation failure | Stop. Print failed checks. | | Neo4j unreachable | Stop before any write. | | Individual batch failure | Stop after that batch; partial writes are safe to resume. | | Audit mismatch | Report. Do not claim success. |
Reads / Writes
Reads
{project}/docs/**/*.mdmcp__neo4j__get-schema(preflight)mcp__neo4j__read-cypher(live counts in Phase 5)
Writes
{project}/.nacl-migrate/detect-ba.json{project}/.nacl-migrate/ba-ir.json{project}/.nacl-migrate/ba-validation.json{project}/.nacl-migrate/ba-cypher.json{project}/.nacl-migrate/ba-live-counts.json{project}/.nacl-migrate/ba-audit.json{project}/MIGRATION-REPORT-BA.mdmcp__neo4j__write-cypher(Phase 4)
Checklist
- [ ] Prelude:
$NACL_HOMEresolved, Python 3.11+ present - [ ] Phase 0: adapter detected or user supplied
- [ ] Phase 1: IR emitted, zero warnings (or tally surfaced)
- [ ] Phase 2: V1–V10 all pass
- [ ] Phase 3: Cypher plan generated
- [ ] Phase 4: every batch executed via
mcp__neo4j__write-cypher - [ ] Phase 5: live counts gathered
- [ ] Phase 6: audit clean
- [ ] Phase 7:
MIGRATION-REPORT-BA.mdwritten
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ITSalt
- Source: ITSalt/NaCl
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.