pi-crew 0.9.47 → 0.9.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/AGENTS.md +18 -0
  2. package/CHANGELOG.md +132 -4
  3. package/README.md +1 -1
  4. package/dist/build-meta.json +22 -12
  5. package/dist/index.mjs +430 -388
  6. package/dist/index.mjs.map +3 -3
  7. package/docs/decisions/2026-07-24-oidc-trusted-publishing.md +112 -0
  8. package/docs/publishing.md +5 -2
  9. package/package.json +2 -2
  10. package/scripts/postinstall.mjs +43 -18
  11. package/skills/.gitkeep +0 -0
  12. package/skills/distill-persona/BUILD-NOTES.md +55 -0
  13. package/skills/distill-persona/SKILL.md +612 -0
  14. package/skills/distill-persona/UPGRADE-LOG-RESEARCH-SKILLS.md +100 -0
  15. package/skills/distill-persona/references/coverage-manifest.md +65 -0
  16. package/skills/distill-persona/references/distillation-field-synthesis-pass2.md +59 -0
  17. package/skills/distill-persona/references/distillation-field-synthesis.md +108 -0
  18. package/skills/distill-persona/references/handoff.md +42 -0
  19. package/skills/distill-persona/references/research/lesson-memory-shortcut.md +33 -0
  20. package/skills/distill-persona/references/research/r1-a-examples.md +23 -0
  21. package/skills/distill-persona/references/research/r1-b-scripts.md +26 -0
  22. package/skills/distill-persona/references/research/r1-c-human-readme.md +31 -0
  23. package/skills/distill-persona/references/research/r1-d-tests.md +28 -0
  24. package/skills/distill-persona/references/research/r1-verification.md +36 -0
  25. package/skills/distill-persona/references/research/r2-low-yield.md +26 -0
  26. package/skills/distill-persona/scripts/fidelity_eval.py +244 -0
  27. package/skills/distill-persona/scripts/validate-skill-structure.mjs +177 -0
  28. package/skills/distill-software/BUILD-NOTES.md +56 -0
  29. package/skills/distill-software/SKILL.md +302 -0
  30. package/skills/distill-software/references/handoff.md +47 -0
  31. package/skills/distill-software/scripts/code_dna.py +290 -0
  32. package/skills/research/DISTILLATION-PROCESS-CHECKLIST.md +120 -0
  33. package/skills/research/EXCAVATION-CHECKLIST.md +142 -0
  34. package/skills/research/FIDELITY.md +180 -0
  35. package/skills/research/SKILL.md +432 -0
  36. package/skills/research/references/anti-patterns.md +184 -0
  37. package/skills/research/references/fidelity.md +241 -0
  38. package/skills/research/references/handoff.md +48 -0
  39. package/skills/research/references/research-protocol.md +162 -0
  40. package/skills/research/references/source-inventory.md +135 -0
  41. package/skills/research/references/verified-models.md +163 -0
  42. package/skills/research/scripts/__pycache__/safe_io.cpython-312.pyc +0 -0
  43. package/skills/research/scripts/code_dna.py +233 -0
  44. package/skills/research/scripts/emit_run_summary.py +142 -0
  45. package/skills/research/scripts/safe_io.py +314 -0
  46. package/skills/research/scripts/source_evaluator.py +234 -0
  47. package/skills/research/scripts/validate-skill-structure.mjs +177 -0
  48. package/skills/research/scripts/verify_citations.py +225 -0
  49. package/skills/security-priority.json +28 -0
  50. package/src/config/config.ts +1 -0
  51. package/src/config/role-tools.ts +6 -3
  52. package/src/config/types.ts +8 -0
  53. package/src/runtime/background-runner.ts +11 -16
  54. package/src/runtime/heartbeat-watcher.ts +28 -1
  55. package/src/runtime/task-runner.ts +165 -119
  56. package/src/schema/config-schema.ts +1 -0
  57. package/src/utils/gh-protocol.ts +9 -8
  58. package/workflows/distill.workflow.md +198 -0
@@ -0,0 +1,112 @@
1
+ # ADR: OIDC Trusted Publishing for npm
2
+
3
+ **Date**: 2026-07-24
4
+ **Status**: PROPOSED — not yet active (requires npm-side configuration)
5
+ **Distilled from**: oh-my-pi@c84e9c020 `CONTRIBUTING.md:313-317` + `.github/workflows/release.yml` (GPL-3.0 — pattern only, not code)
6
+
7
+ ## Context
8
+
9
+ pi-crew currently publishes to npm manually via `npm publish` using a long-lived `NPM_TOKEN` (npm user `bom0792`). This has two supply-chain weaknesses:
10
+
11
+ 1. **Token theft surface**: a long-lived npm token stored as a GitHub secret can be exfiltrated via a compromised dependency or workflow `pull_request_target` misuse. The token grants full publish access until manually rotated.
12
+ 2. **No build attestation**: published packages carry no cryptographic proof of *what CI built and published them*. Consumers cannot verify a `pi-crew@x.y.z` tarball came from this repo's CI.
13
+
14
+ The v0.9.3 mid-CI-publish incident class (publishing mid-run rather than from a dedicated gated workflow) is a third motivator: a dedicated release workflow moves publishing out of the general CI run and into a controlled, test-gated path.
15
+
16
+ ## Decision
17
+
18
+ Adopt **npm Trusted Publishing (OIDC)** + **provenance attestation**, following the pattern oh-my-pi@c84e9c020 uses (`id-token: write`, no `NPM_TOKEN`, `--provenance`):
19
+
20
+ 1. Eliminate the long-lived `NPM_TOKEN`. Instead, GitHub Actions exchanges an OIDC token for a short-lived npm publish credential at publish time. No token to steal.
21
+ 2. Attach **provenance** (Sigstore-signed build attestation) to every published tarball. Consumers can verify origin with `npm audit signatures`.
22
+
23
+ ## Implementation steps (external + code)
24
+
25
+ ### A. npm-side (manual, one-time — cannot be done from code)
26
+
27
+ 1. Go to `https://www.npmjs.com/package/pi-crew/access`
28
+ 2. Under **Publishing access**, switch to **Require two-factor authentication and disallow tokens** (or set up Trusted Publishing if available for the account).
29
+ 3. Alternatively, use `npm token create --cidr` to scope a publish-only token to GitHub Actions IPs (weaker than OIDC but simpler).
30
+ 4. For full OIDC: configure the npm-side Trusted Publishing link to `baphuongna/pi-crew` + the `release.yml` workflow.
31
+
32
+ ### B. Code-side (when OIDC is configured)
33
+
34
+ 1. Add `.github/workflows/release.yml` (sample below) — **manual trigger only** (`workflow_dispatch`) until proven stable.
35
+ 2. Do **NOT** add `provenance=true` to a global `.npmrc` — that breaks local `npm publish` with "requires CI environment". Provenance must be a `--provenance` flag inside the CI workflow only.
36
+
37
+ ### Sample `release.yml` (MIT-licensed, pi-crew style — not copied from oh-my-pi)
38
+
39
+ ```yaml
40
+ name: Release
41
+
42
+ on:
43
+ workflow_dispatch:
44
+ inputs:
45
+ version:
46
+ description: 'Version to publish (must match package.json)'
47
+ required: true
48
+ type: string
49
+
50
+ permissions:
51
+ contents: write
52
+ id-token: write # OIDC for trusted publishing
53
+
54
+ concurrency:
55
+ group: release-${{ github.ref }}
56
+ cancel-in-progress: false
57
+
58
+ jobs:
59
+ publish:
60
+ runs-on: ubuntu-latest
61
+ environment: release # requires manual approval via GitHub environment protection
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+ with:
65
+ fetch-depth: 0
66
+
67
+ - uses: actions/setup-node@v4
68
+ with:
69
+ node-version: '22'
70
+ registry-url: 'https://registry.npmjs.org'
71
+
72
+ - run: npm ci
73
+
74
+ - name: Verify version matches input
75
+ run: |
76
+ PKG_VERSION=$(node -p "require('./package.json').version")
77
+ if [ "$PKG_VERSION" != "${{ inputs.version }}" ]; then
78
+ echo "Version mismatch: package.json=$PKG_VERSION input=${{ inputs.version }}"
79
+ exit 1
80
+ fi
81
+
82
+ - run: npm run typecheck
83
+ - run: npm run test:critical
84
+ - run: npm run build:bundle
85
+
86
+ - name: Publish with provenance
87
+ run: npm publish --provenance --access public
88
+ # No NPM_TOKEN env — OIDC trusted publishing exchanges the job's
89
+ # id-token for a short-lived credential automatically.
90
+
91
+ - name: Create GitHub release
92
+ uses: softprops/action-gh-release@v2
93
+ with:
94
+ tag_name: v${{ inputs.version }}
95
+ generate_release_notes: true
96
+ ```
97
+
98
+ ## What this prevents
99
+
100
+ - **Token exfiltration**: no long-lived `NPM_TOKEN` secret to steal.
101
+ - **Unverified publishes**: every tarball carries a signed attestation linking it to this repo's CI.
102
+ - **Accidental publishes**: `workflow_dispatch` + `environment: release` (protected) requires manual approval before publish runs.
103
+
104
+ ## Why not active yet
105
+
106
+ - npm-side Trusted Publishing / token-lockdown must be configured at `npmjs.com/package/pi-crew/access` first.
107
+ - The `environment: release` protection rule (required reviewers) must be configured in GitHub repo settings.
108
+ - Until both are done, keep the manual `npm publish` + GitHub release flow.
109
+
110
+ ## Trade-off
111
+
112
+ OIDC trusted publishing is slightly less convenient than a long-lived token (each publish goes through a workflow dispatch + approval). The supply-chain hardening is worth it for a package with 700+ files shipping to public npm.
@@ -71,8 +71,11 @@ pi install npm:pi-crew
71
71
  1. Builds the ESM bundle (`scripts/build-bundle.mjs`) — best-effort, falls
72
72
  back to strip-types loading if esbuild is missing.
73
73
  2. Installs the bundled `crew-vibes.ttf` font into the user fonts directory.
74
- 3. Copies every `skills/<name>/` dir to `~/.pi/agent/skills/` so pi-crew's
75
- skills are available globally (not just inside the pi-crew project).
74
+ 3. Runs `cleanupStaleSkillCopies()` — a one-time migration that removes
75
+ stale skill copies from `~/.pi/agent/skills/` left by v0.9.47's (now-removed)
76
+ `copySkills()` step. Only removes **byte-identical** copies; user-customized
77
+ skills are preserved. Pi discovers skills natively from the npm package's
78
+ own `skills/` dir, so copies are never needed.
76
79
 
77
80
  All three steps are best-effort and never fail the install.
78
81
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-crew",
3
- "version": "0.9.47",
3
+ "version": "0.9.49",
4
4
  "description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
5
5
  "author": "baphuongna",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "agents/",
37
37
  "teams/",
38
38
  "workflows/",
39
- "skills/**/SKILL.md",
39
+ "skills/**",
40
40
  "themes/",
41
41
  "assets/crew-vibes.ttf",
42
42
  "assets/runner-spritesheet.png",
@@ -6,13 +6,17 @@
6
6
  * let Pi fall back to strip-types loading).
7
7
  * 2. Install the bundled crew-vibes.ttf into the user fonts directory so
8
8
  * the crew-vibes speed/capacity PUA glyphs render.
9
- * 3. Copy bundled skills to ~/.pi/agent/skills/ so they are available
10
- * globally (not just inside the pi-crew project).
9
+ * 3. Remove stale skill copies from ~/.pi/agent/skills/ (migration from
10
+ * the v0.9.47 copySkills() bug — see cleanupStaleSkillCopies()).
11
11
  *
12
12
  * Replaces the old `postinstall` shell chain so the font install runs on
13
13
  * every platform without relying on shell-specific chaining (`;`/`&&`).
14
+ *
15
+ * NOTE: skills are NOT copied here. Pi discovers skills natively from the
16
+ * npm package dir (`~/.pi/agent/npm/node_modules/pi-crew/skills/`); copying
17
+ * them to ~/.pi/agent/skills/ only creates duplicate "collision" warnings.
14
18
  */
15
- import { cpSync, existsSync, mkdirSync, readdirSync } from "node:fs";
19
+ import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
16
20
  import { spawnSync } from "node:child_process";
17
21
  import { dirname, join } from "node:path";
18
22
  import { fileURLToPath } from "node:url";
@@ -29,32 +33,53 @@ function run(scriptRel) {
29
33
  }
30
34
 
31
35
  /**
32
- * Copy each skill directory from pi-crew/skills/ to ~/.pi/agent/skills/.
33
- * Best-effort: must never fail the install.
36
+ * Remove stale skill copies from ~/.pi/agent/skills/ that are byte-identical
37
+ * to the bundled skills/ — left over from the v0.9.47 copySkills() postinstall
38
+ * (which redundantly copied all skills, causing "collision" warnings).
39
+ *
40
+ * Pi discovers skills natively from the npm package dir, so these copies only
41
+ * create noise AND can shadow newer package versions on upgrade.
42
+ *
43
+ * SAFE: only removes EXACT (byte-identical) copies. A skill the user has
44
+ * customized (differs from the package) is preserved. Best-effort, never
45
+ * fails the install.
34
46
  */
35
- function copySkills() {
47
+ function cleanupStaleSkillCopies() {
36
48
  const srcSkillsDir = join(root, "skills");
37
49
  if (!existsSync(srcSkillsDir)) return;
38
50
 
39
51
  const destSkillsDir = join(homedir(), ".pi", "agent", "skills");
40
- try {
41
- mkdirSync(destSkillsDir, { recursive: true });
42
- } catch {
43
- return; // can't create dest — skip silently
44
- }
52
+ if (!existsSync(destSkillsDir)) return;
45
53
 
54
+ let removed = 0;
55
+ let kept = 0;
46
56
  for (const entry of readdirSync(srcSkillsDir, { withFileTypes: true })) {
47
57
  if (!entry.isDirectory()) continue;
48
- const skillMd = join(srcSkillsDir, entry.name, "SKILL.md");
49
- if (!existsSync(skillMd)) continue;
58
+ const srcSkillMd = join(srcSkillsDir, entry.name, "SKILL.md");
59
+ if (!existsSync(srcSkillMd)) continue;
60
+ const destSkillDir = join(destSkillsDir, entry.name);
61
+ const destSkillMd = join(destSkillDir, "SKILL.md");
62
+ if (!existsSync(destSkillMd)) continue;
50
63
  try {
51
- cpSync(join(srcSkillsDir, entry.name), join(destSkillsDir, entry.name), {
52
- recursive: true,
53
- });
64
+ const srcContent = readFileSync(srcSkillMd, "utf8");
65
+ const destContent = readFileSync(destSkillMd, "utf8");
66
+ if (srcContent === destContent) {
67
+ rmSync(destSkillDir, { recursive: true, force: true });
68
+ removed++;
69
+ } else {
70
+ // User customized this skill — preserve it.
71
+ kept++;
72
+ }
54
73
  } catch {
55
74
  // best-effort: skip this skill on error
56
75
  }
57
76
  }
77
+ if (removed > 0) {
78
+ const note = kept > 0 ? ` (${kept} customized copy(ies) preserved)` : "";
79
+ console.warn(
80
+ `[pi-crew] postinstall: removed ${removed} stale skill cop${removed === 1 ? "y" : "ies"} from ~/.pi/agent/skills/${note}.`,
81
+ );
82
+ }
58
83
  }
59
84
 
60
85
  function main() {
@@ -74,8 +99,8 @@ function main() {
74
99
  }
75
100
  // Font install is best-effort and must never fail the install.
76
101
  run("scripts/install-crew-vibes-font.mjs");
77
- // Copy bundled skills to ~/.pi/agent/skills/ for global availability.
78
- copySkills();
102
+ // Migration cleanup: remove stale skill copies from v0.9.47's copySkills().
103
+ cleanupStaleSkillCopies();
79
104
  } catch (err) {
80
105
  // Postinstall must NEVER fail the install (SEC-M2).
81
106
  console.warn("[pi-crew] postinstall: best-effort step failed:", err instanceof Error ? err.message : err);
File without changes
@@ -0,0 +1,55 @@
1
+ # distill-persona — Build Notes (decision traceability)
2
+
3
+ > Why this pi-native port makes each choice. Traces every design decision to a finding from the review/experiment cycle.
4
+
5
+ ## What this is
6
+ A pi-skill port of nuwa's (女娲) distillation engine, incorporating: the nuwa methodology (researched), the rigorous review (NUWA-SKILL-REVIEW), the variant reviews (x-mastery-mentor, mrbeast), the empirical fidelity experiment (f2-experiment), AND **two self-distillation passes** over the 3 source projects (dogfooded — see below).
7
+
8
+ ## Self-distillation log (dogfooded the skill on its own sources)
9
+ The skill was applied to the 3 source projects (nuwa + 2 awesome-lists), topic flavor. Three rounds:
10
+ - **Pass 1** (`references/distillation-field-synthesis.md`): triple-verified 13 candidates → 3 NEW field models (M-F1 dissemination flywheel, M-F2 target taxonomy, M-F3 ethics spectrum) integrated into SKILL.md Phase 0.
11
+ - **Pass 2** (`references/distillation-field-synthesis-pass2.md`): independent re-derivation → **core 8/8 reproduced (100%)** + 1 standout new model **M-F4 (field over-claims its own fidelity)** — elevates the F2' finding from a skill-internal fix to a field-level meta-model.
12
+ - **R1 exhaustive sweep** (user correction: distillation must sweep EVERY part over many rounds, not gestalt): upgraded Phase 1 to add **project/topic exhaustive-sweep mode** (coverage manifest + diminishing-returns gate + self-correction meta-loop). Then RAN it — 4 parallel batches swept the 9 uncovered nuwa examples + scripts + 76KB README + 5 test files (`references/research/r1-{a,b,c,d}.md`). **3 self-corrections integrated**: (1) **M-F2 empirically corrected** — gestalt spectrum was wrong (84% public-figures, bimodal; +meta-tier, living-creator, commemorative-split); (2) **+M-F7** (structural invariants = index-scale quality gate, from the test sweep); (3) **M-F4 strengthened** (quality_check.py structural-pass ≠ behavioral edge-honesty → never trust structural-only auto-pass). This is the self-correction meta-loop firing: the sweep found the skill's own M-F2 was gestalt-inaccurate and fixed it.
13
+ - **R1.5 extraction verification** (user correction: distillation must verify it's optimal+effective, not "chưng cất bừa làm rác"): added **Phase 2.6 Extraction verification gate** (V1 signal-not-persona-content · V2 non-redundant · V3 effective · V4 optimal · reject principle + post-integration delta check). RAN it on R1 output (`references/research/r1-verification.md`): audited ~30 candidates → **5 field models kept** (all pass V1-V4), **~22 persona-content REJECTED** (V1 fail — idiot-index/desire-as-contract/etc. are subject content, not distillation method), 4 reclassified. Over-extraction was already contained (garbage stayed in research files); now made *principled & repeatable*. Skill carries 10 models total (5 core M1-M5 + 5 field M-F1..F4/M-F7) — sharp, not bloated.
14
+ - **Reproducibility (F10 dogfood)**: core model-set overlap 8/8 — methodology is stable (not coin-flip); pass 2 is a strict superset (deeper pass enlarges surface). R1 then enlarged surface further (M-F7) AND corrected an existing model (M-F2). Caveat: same mind across passes — suggestive, not proof.
15
+
16
+ ## Decision → finding trace
17
+
18
+ | Decision in the skill | Driven by |
19
+ |---|---|
20
+ | pi frontmatter (`name` + 1-line `description` + `triggers:` list) | F4/F5 — pi's explicit-trigger convention avoids nuwa's keyword-stuffed descriptions |
21
+ | Detect `<skill-dirs>`; don't hardcode `.claude/skills/` | **F1** — environment lock-in (the #1 reason nuwa won't run in pi) |
22
+ | Dispatch research via `team action='parallel'` / background `Agent`, with **serial + single-agent fallback as documented default** | **F1** + nuwa's own failure table ("runtime without background tasks hangs") |
23
+ | Guard tool availability (WebSearch/rg/git/pi-langsrv "if present") | **F1** — don't assume named external skills exist |
24
+ | Cost tier quoted in Phase 0, context-window segmentation guidance front-loaded | **F6** — nuwa buries this in a failure table; default standard tier is the one that blows windows |
25
+ | Triple-verification with exclusivity emphasized as anti-bloat | **S2** + SOFTWARE-DISTILLATION-DEEP-DIVE §D |
26
+ | Honest boundaries ≥3 + `distilled:` staleness date mandatory | **S3** + software staleness anchor |
27
+ | Fallback tree + anti-example blacklist required in output | **S5** |
28
+ | Contradictions preserved (≥2 tensions, never flattened) | **S7** |
29
+ | **The F2' third inference category** ("in-field-but-never-addressed → flag as inference") in the Agentic Protocol | **f2-experiment finding** — the empirical result; this is the single most important addition over nuwa |
30
+ | Phase 4 mandates a **NOVEL in-domain edge question** not covered by research files | **F2'/f2-experiment** — nuwa's edge questions sat too close to documented material; that's why its 97/100 didn't reproduce (got 71-72) |
31
+ | Scorer MAY read the skill file (kept nuwa's design) | **F2 REFUTED** — experiment showed skill-file access does NOT inflate scores (71 vs 72 converged); so the "blind scoring" fix proposed earlier is dropped |
32
+ | Operational scripts wired INTO the Agentic Protocol Step 2 | **F13** — mrbeast scripts were orphaned showpieces |
33
+ | Engine embeds methodology inline (self-contained) | **F9** — nuwa's engine depends on its own references/ at runtime; outputs are portable but the engine isn't |
34
+ | Three flavors (person / topic / software) with pointers | x-mastery-mentor (topic works, S8/S9/S10) + SOFTWARE-DISTILLATION-DEEP-DIVE |
35
+
36
+ ## What was deliberately NOT copied from nuwa
37
+ - Keyword-stuffed descriptions (F4) → pi triggers list instead.
38
+ - The published 97/100 fidelity scores as ground truth (F2') → re-run on novel edge questions.
39
+ - Chinese-source blacklist as a *universal* rule (F11) → scoped to "Chinese figures only, quality reason".
40
+ - Default = the expensive standard tier in one session (F6) → segmentation front-loaded.
41
+
42
+ ## Known gaps in this port (honest) — status after the gap-closing pass
43
+
44
+ - ✅ **F2' validation — CLOSED.** Ran the experiment on 2 more nuwa skills (ilya, munger): published 94/97 → blind 76/67; edge-honesty 20→13/7. F2' generalizes at n=3. Refined mechanism: **framework-answerable** novel edges are the drift zone; fact-demanding edges give false passes. See `source/f2-experiment/validation-conclusion.md`. The skill's F2' rule + Phase 4 now specifically require a framework-answerable edge.
45
+ - ✅ **Phase 4 automation + reproducibility test — CLOSED.** Shipped `scripts/fidelity_eval.py` (stdlib-only): `validate` (spec must have 3 known + 1 framework-answerable edge + ground-truth + edge-note) · `runbook` (emits runtime-agnostic answerer+scorer prompts) · `parse` (5-dim scorecard → grade, with the F2' edge-honesty gate: edge <14 = NO-SHIP regardless of total) · `repro` (Jaccard/name-overlap on mental models, <60% = non-reproducible). Tested against all 3 experiment scorecards + self/diff-persona repro.
46
+ - ⚠️ **All 3 nuwa skills grade NO-SHIP** under the validated gate (karpathy edge 6, ilya 13, munger 7 — all <14). Strong confirmation the gate catches what it should: none of nuwa's published skills reliably flag framework-derived inference on novel in-domain questions.
47
+ - 🔲 **No operational DNA script shipped yet.** The engine is methodology; a software-flavor distillation should add per-target `scripts/<persona>_dna.py` (per the mrbeast pattern / F13 — wired into the Agentic Protocol, not orphaned). Build per-target.
48
+ - 🔲 **Topic-flavor user-data persistence** (S9) referenced but not implemented — add when building a stateful topic skill.
49
+ - 🔲 **pi-crew specialization adapter** not written — the base is runtime-agnostic by design; a `distill-persona-pi-crew` specialization would pin `team action='parallel'` + pi skill-dirs + pi-langsrv. Defer until the base is battle-tested.
50
+
51
+ ## Suggested next slices (in priority order)
52
+ 1. **Scale F2' validation** to 5+ skills × 3-5 framework-answerable edges each, via `fidelity_eval.py runbook`. The harness makes this cheap. Confirms the 60% repro floor and the edge-honesty gate are calibrated.
53
+ 2. **Build `distill-software`** as a sibling (the SOFTWARE-DISTILLATION-DEEP-DIVE playbook, pi-langsrv-native; ships a `<engineer>_dna.py` code-Expression-DNA script wired into its Agentic Protocol).
54
+ 3. **Write the pi-crew specialization adapter** (pins the runtime; reuses the validated base unchanged).
55
+ 4. **Implement topic-flavor user-data persistence** (S9) when the first topic-skill use case appears.