43-ecosystem-init — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited 43-ecosystem-init (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The procedure backing .claude/commands/ecosystem-init.md (the once-per-fork ecosystem ceremony). The command body holds the five load-bearing invariants + the ceremony order; this skill holds the step-by-step procedure, the input prompts, the D6 schema field set, and the exact tool-call shapes.
Three onboarding surfaces (the core distinction — 02-plans/02-ga-ecosystem-onboarding.md):
| Surface | Moment | Writes | Frequency |
|---|---|---|---|
/onboard | every session entry | NO (read-only) | every session |
/enroll | a human joins an ecosystem | roster + local-links | once / operator |
/ecosystem-init | a fork's first setup | ecosystem-config + genesis trust-root | once / fork |
Ordered per Q4: the registry defines the org, genesis anchors TO that org, the remaining params fill in.
resolver keys (artifact-flow.md § "Repo Classes Map 1:1 To Resolver Logical Keys"): build.py / build.rs / build.prism, use-template.{py,rs,rb,claude-py,claude-rs,claude-rb}, loom, atelier, downstream.<slug>. Each binds to { "org": "<org>", "repo": "<repo>" }.
node .claude/bin/scan-synced-disclosure.mjs --root "$(git rev-parse --show-toplevel)"Exit 0 → proceed. ANY finding (exit non-zero) → HALT; genericize/relocate the offending content and re-scan. NEVER write the config before a clean scan. (ecosystem.json is scanner-self-excluded when scanning its OWN source repo — REPO_ROOT_ACTIVE === REPO_ROOT per scan-synced-disclosure.mjs:215, which is the C1 case — so the scan covers the surrounding synced surface, not the config's own org slugs; those are fenced by path, not by scrub. A DESTINATION --root scan of a DIFFERENT repo DOES scan a stray ecosystem.json, failing loud on bare slugs — the belt-and-suspenders backstop (the destination-mode consequence of D6 §4 fence-iv's isExcluded() source-gate, not a separate fence).)
at the CLIENT's org, never canon's. Automated placement is BLOCKED — a fork AUTHORS its own config.
remote_links block of .claude/bin/ecosystem.json (schema below). The reader isecosystem-config.mjs::getRemoteLink(key); the join is loom-links.mjs::resolveRemote(key).
Invoke .claude/hooks/lib/genesis-ceremony.js::runEnrollmentCeremony({roster, repo, signingKeyPath, signingKeyFingerprint, ghApi, transportAppend}) (invariant 3). It is fail-CLOSED — any failed gh-api verification refuses to emit the genesis-anchor.
roster.genesis.repo_owner_kind: "org"): the verified-org-admin attestation(gh api orgs/{org}/memberships/{login} → role: "admin") is the trust anchor (the issue-#358 org-owned-bootstrap relaxation — a verified active org admin substitutes for an unverified root commit).
gh api .../commits/{root_commit} →verification.verified == true, author == declared owner) is the anchor.
person_id MUST already be in operators.roster.json withrole: owner and the correct github_login. On a truly fresh fork, edit the bootstrap roster or run /whoami --register then promote the role on the resulting PR first.
The signed genesis-anchor lands in .claude/learning/coordination-log.jsonl (fold rule 9a accepts the first verifying owner-bound anchor as the trust root). Full runbook: guides/co-setup/11-genesis-ceremony.md.
Fill the rest of .claude/bin/ecosystem.json; human-confirm each points at the CLIENT's org:
registry → { "host": "docker.io", "org": "<registry-namespace>" } — replaces hardcodeddocker.io/<canon-org>/… (getRegistry()).
vcs → { "default_provider": "github", "overrides": { "build.rs": "azure-devops" } } — ecosystemcomplement to per-repo roster.genesis.provider; roster wins for its own repo (getRepoProvider).
deploy → { "default_targets": [...], "per_project": {...} } (getDeploy()).upstream_canon → { "remote": "upstream", "url": "git@<host>:<canon-org>/loom.git" } — **null incanon**; the client's explicit "sync upstream from" pointer (getUpstreamCanon()).
If the fork's build is NOT Kailash, invoke the EXISTING /onboard-stack (detects the stack, scaffolds STACK.md). Skip for a full-Kailash fork. Does NOT re-implement detection.
Print: "Ecosystem configured. Each operator now runs /enroll, then /onboard at the start of every session." Do NOT enroll the initiating operator — that is /enroll's gated job.
.claude/bin/ecosystem.json){
"schema_version": 1,
"ecosystem": {
"id": "<opaque-local-label>", // NOT a client name
"upstream_canon": {
"remote": "upstream",
"url": "git@<host>:<canon-org>/loom.git",
},
},
"registry": { "host": "docker.io", "org": "<registry-namespace>" },
"remote_links": {
"build.py": { "org": "<org>", "repo": "kailash-py" },
"loom": { "org": "<org>", "repo": "loom" },
},
"vcs": {
"default_provider": "github",
"overrides": { "build.rs": "azure-devops" },
},
"deploy": { "default_targets": [], "per_project": {} },
}Validate by loading ecosystem-config.mjs::getEcosystemConfig() after writing — a malformed / unknown-schema_version file fails loud (the D6 Q6 contract). The synthetic companion .claude/bin/ecosystem.example.json is the only ecosystem* file that syncs/publishes.
ecosystem.json carries real org slugs BY DESIGN. Its isolation is by PATH, not by scrub (invariant 5): committed-but-never-synced (sync-manifest.yaml::loom_only), never-published (publish-to-public.mjs EXCLUDE_WITHIN + KILL_BASENAMES), and scanner-self-excluded at loom-source ONLY (REPO_ROOT_ACTIVE === REPO_ROOT; a destination --root scan of another repo DOES scan a stray copy, failing loud on bare slugs — the belt-and-suspenders backstop). A canon fork and a client fork each carry their OWN file; a fork pulls upstream-only; no canon→client sync path exists. This is the D6 plan §4 (i)-(iv) fence composition — fence by ABSENCE, the strongest guarantee.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.