fix(pkg): mark pharn-oss private, drop the dead main entry point - #135
Conversation
package.json had no "private": true, so a real `npm publish` could push this whole methodology repo (.dev/, pharn/, .claude/) to the registry under the publishable name "pharn-oss" — the distributable npm package is the separate @pharn-dev/pharn (pharn-cli), never this repo. It also declared "main": "index.js", a file that has never existed, so the package presented itself as importable when it is neither publishable nor an entry point. Both edits are one axis: package.json currently claims a publish/import surface this repo doesn't have. private: true removes the surface; deleting main removes the dead pointer into it — bundled deliberately rather than split, since main's deletion has no meaning without the private context that explains why it was already dead. No SKILLS_VERSION bump: package.json is pure repo-meta per CLAUDE.md's versioning discipline, not shipped product-surface bytes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe package is now private and no longer declares ChangesPackage privacy metadata
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed: dependency version conflict. Check your lock file or package.json. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.dev/features/f8-package-private/GRILL.md:
- Around line 17-40: Update the P1, P0, and P3 findings in
.dev/features/f8-package-private/GRILL.md#L17-L40 to use exact line anchors for
the corresponding evidence ranges in PLAN.md rather than unrelated lines. In
.dev/features/f8-package-private/REVIEW.md#L49-L55, replace package.json:1 with
the exact changed package.json ranges. Preserve each finding’s existing scope
and content while making all references actionable.
In @.dev/features/f8-package-private/PLAN.md:
- Around line 22-34: Expand .dev/features/f8-package-private/PLAN.md with a
verification section documenting acceptance checks for package fields, npm
publish --dry-run, CI, and feature-audit validation, including each command,
expected result, and scope. Keep npm’s refusal of publishing private packages
explicitly advisory, and retain the existing P1 and P0 audit conclusions.
- Around line 26-30: The “This edit does not alter the product surface”
conclusion in the Guarantee audit is incorrectly labeled enum/regex-reducible;
change it to advisory wording because the package exclusion is not enforced by a
floor checker. In PLAN.md, add the package-specific verification checklist
requested by the comment, while preserving the existing CLAUDE.md enumeration
reference and no-bump conclusion.
In @.dev/features/f8-package-private/verify-report.json:
- Around line 3-13: The package-field acceptance check is missing from the
verification report. In .dev/features/f8-package-private/verify-report.json, add
a structured check matching the VERIFY.md requirement that private === true and
main === undefined, including its command, status, and result; do not add an npm
publish --dry-run check. The corresponding requirement in
.dev/features/f8-package-private/VERIFY.md requires no direct change.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b9356d8f-f412-49c9-8b27-3baff4bf50ef
📒 Files selected for processing (9)
.dev/features/f8-package-private/GRILL.md.dev/features/f8-package-private/PLAN.md.dev/features/f8-package-private/REGRESSION.md.dev/features/f8-package-private/REVIEW.md.dev/features/f8-package-private/SHIP.md.dev/features/f8-package-private/VERIFY.md.dev/features/f8-package-private/regression-report.json.dev/features/f8-package-private/verify-report.jsonpackage.json
| - type: FINDING | ||
| rule_id: P1 | ||
| severity: important | ||
| file: ".dev/features/f8-package-private/PLAN.md:1" | ||
| problem: "The plan declares no verification/acceptance approach for the change it makes — the '## Evals to write (P1)' section correctly says 'None' because package.json is not a Capability, but that answers a different question than 'how do we know the fix worked.'" | ||
| evidence: "## Evals to write (P1)\n\n- None — P1 (\"no Capability ships without evals\") governs `role:`-bearing Capabilities under `pharn/`. `package.json` carries no `role:` frontmatter and is not a Capability, so P1 does not apply to this increment." | ||
| ``` | ||
|
|
||
| ```yaml | ||
| - type: FINDING | ||
| rule_id: P0 | ||
| severity: minor | ||
| file: ".dev/features/f8-package-private/PLAN.md:24" | ||
| problem: 'The guarantee audit correctly labels the npm-refusal behavior advisory (no PHARN floor primitive backs it), but does not name that this leaves no regression guard: a future edit could silently drop "private": true and nothing in `npm run check` would catch it.' | ||
| evidence: '"A real `npm publish` refuses once `private: true` is set" -> advisory (external system behavior). ... no PHARN-side hook, hash, or enum check enforces it.' | ||
| ``` | ||
|
|
||
| ```yaml | ||
| - type: FINDING | ||
| rule_id: P3 | ||
| severity: minor | ||
| file: ".dev/features/f8-package-private/PLAN.md:19" | ||
| problem: 'The single ''## Files'' entry bundles two edits to package.json — adding "private": true (a publish-safety fix) and deleting the dead "main" field (a stale-reference cleanup) — under one stated axis; worth the human''s explicit confirmation these are one reason to change, not two glued together.' | ||
| evidence: '- package.json — add "private": true after "version"; delete the "main": "index.js" line — layer repo-meta' |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Use exact line anchors in every review artifact.
Both reports point findings at unrelated lines, which makes the recorded issues non-actionable.
.dev/features/f8-package-private/GRILL.md#L17-L40: update P1, P0, and P3 to the exactPLAN.mdevidence ranges..dev/features/f8-package-private/REVIEW.md#L49-L55: replacepackage.json:1with the changedpackage.jsonranges.
📍 Affects 2 files
.dev/features/f8-package-private/GRILL.md#L17-L40(this comment).dev/features/f8-package-private/REVIEW.md#L49-L55
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.dev/features/f8-package-private/GRILL.md around lines 17 - 40, Update the
P1, P0, and P3 findings in .dev/features/f8-package-private/GRILL.md#L17-L40 to
use exact line anchors for the corresponding evidence ranges in PLAN.md rather
than unrelated lines. In .dev/features/f8-package-private/REVIEW.md#L49-L55,
replace package.json:1 with the exact changed package.json ranges. Preserve each
finding’s existing scope and content while making all references actionable.
| ## Evals to write (P1) | ||
|
|
||
| - None — P1 ("no Capability ships without evals") governs `role:`-bearing Capabilities under `pharn/`. `package.json` carries no `role:` frontmatter and is not a Capability, so P1 does not apply to this increment. | ||
|
|
||
| ## Guarantee audit (P0) | ||
|
|
||
| - "A real `npm publish` refuses once `private: true` is set" → **advisory (external system behavior)**. This is npm's own documented behavior, not a reduction to one of PHARN's three floor primitives (hook / content-hash / enum-regex) — no PHARN-side hook, hash, or enum check enforces it. It is stated as an observable npm behavior, never labeled a PHARN guarantee. | ||
| - "`package.json` still parses and is prettier-clean after the edit" → **floor-adjacent, enforced by the existing gate**: `npm run format:check` (part of `npm run check`) already runs `prettier --check .` over the whole repo, so a malformed or unformatted `package.json` fails that pre-existing gate. No new floor primitive is added by this increment. | ||
| - "This edit does not alter the product surface" → **enum/regex-reducible, by inspection**: `package.json` is not in CLAUDE.md's bump-triggering set (the `pharn/` capability tree, `pharn/floor/*.mjs`, the four trusted docs, the product `.claude/` surface) — it is named explicitly under "Pure repo-meta ... does not bump either." No `SKILLS_VERSION` bump, no floor check needed to prove it (the claim rests on the already-published, human-authored enumeration in CLAUDE.md, not on a new mechanism this increment invents). | ||
|
|
||
| ## Open questions (HALT) | ||
|
|
||
| - None. The defect is reproduced live (see plan args), the fix is a two-field JSON edit with no ambiguity, and CLAUDE.md is dispositive on the no-bump question. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add the acceptance checks to the plan.
## Evals to write (P1) only explains why Capability evals do not apply. It does not record the acceptance checks listed in the PR objectives: package-field checks, npm publish --dry-run, CI checks, and feature-audit validation. Add the commands, expected results, and scope in a verification section. Keep external npm behavior advisory.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.dev/features/f8-package-private/PLAN.md around lines 22 - 34, Expand
.dev/features/f8-package-private/PLAN.md with a verification section documenting
acceptance checks for package fields, npm publish --dry-run, CI, and
feature-audit validation, including each command, expected result, and scope.
Keep npm’s refusal of publishing private packages explicitly advisory, and
retain the existing P1 and P0 audit conclusions.
| ## Guarantee audit (P0) | ||
|
|
||
| - "A real `npm publish` refuses once `private: true` is set" → **advisory (external system behavior)**. This is npm's own documented behavior, not a reduction to one of PHARN's three floor primitives (hook / content-hash / enum-regex) — no PHARN-side hook, hash, or enum check enforces it. It is stated as an observable npm behavior, never labeled a PHARN guarantee. | ||
| - "`package.json` still parses and is prettier-clean after the edit" → **floor-adjacent, enforced by the existing gate**: `npm run format:check` (part of `npm run check`) already runs `prettier --check .` over the whole repo, so a malformed or unformatted `package.json` fails that pre-existing gate. No new floor primitive is added by this increment. | ||
| - "This edit does not alter the product surface" → **enum/regex-reducible, by inspection**: `package.json` is not in CLAUDE.md's bump-triggering set (the `pharn/` capability tree, `pharn/floor/*.mjs`, the four trusted docs, the product `.claude/` surface) — it is named explicitly under "Pure repo-meta ... does not bump either." No `SKILLS_VERSION` bump, no floor check needed to prove it (the claim rests on the already-published, human-authored enumeration in CLAUDE.md, not on a new mechanism this increment invents). |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- PLAN ---'
sed -n '1,90p' .dev/features/f8-package-private/PLAN.md
printf '%s\n' '--- CLAUDE bump rules ---'
rg -n -A12 -B8 'bump|trigger|Pure repo-meta|SKILLS_VERSION|package\.json' CLAUDE.md
printf '%s\n' '--- floor files ---'
git ls-files 'pharn/floor/*.mjs'Repository: pharn-dev/pharn-oss
Length of output: 18719
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- bump-related enforcement ---'
rg -n -i -A5 -B5 'SKILLS_VERSION|bump-triggering|product surface|package\.json' .dev pharn .claude package.json CLAUDE.md \
| head -n 240
printf '%s\n' '--- plan lines ---'
nl -ba .dev/features/f8-package-private/PLAN.md | sed -n '22,34p'
printf '%s\n' '--- package metadata ---'
cat package.json
printf '%s\n' '--- relevant scripts ---'
node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log(JSON.stringify(p.scripts ?? {}, null, 2));
JSRepository: pharn-dev/pharn-oss
Length of output: 25452
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- feature files ---'
git ls-files '.dev/features/f8-package-private/*'
printf '%s\n' '--- feature objectives and verification references ---'
rg -n -i -A4 -B4 'objective|verification|verify|publish|private|bump|checklist' .dev/features/f8-package-private
printf '%s\n' '--- deterministic wording and checker references ---'
python3 - <<'PY'
from pathlib import Path
import re
plan = Path(".dev/features/f8-package-private/PLAN.md").read_text()
claude = Path("CLAUDE.md").read_text()
floor = "\n".join(
p.read_text()
for p in Path("pharn/floor").glob("*.mjs")
if not p.name.endswith(".test.mjs")
)
print("plan says enum/regex-reducible:",
bool(re.search(r"enum/regex-reducible", plan)))
print("plan says no floor primitive:",
bool(re.search(r"no floor check needed|no .*floor primitive", plan, re.I)))
print("CLAUDE explicitly excludes package.json:",
bool(re.search(r"package\.json\s*/?\s*`?\s*/?\s*SKILLS_VERSION itself", claude)))
print("product-set sentence includes package.json:",
bool(re.search(r"package\.json", claude[claude.find("The bump-triggering set"):claude.find("The bump-triggering set") + 800])))
print("product floor contains SKILLS_VERSION bump logic:",
bool(re.search(r"SKILLS_VERSION|bump-triggering|package\.json", floor, re.I)))
PYRepository: pharn-dev/pharn-oss
Length of output: 30680
Mark the no-bump conclusion as advisory.
CLAUDE.md explicitly excludes package.json from the bump-triggering set, but no floor checker enforces that set. A manual comparison is not an enum/regex check. Replace enum/regex-reducible, by inspection with advisory wording and add the package-specific verification checklist to PLAN.md.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.dev/features/f8-package-private/PLAN.md around lines 26 - 30, The “This
edit does not alter the product surface” conclusion in the Guarantee audit is
incorrectly labeled enum/regex-reducible; change it to advisory wording because
the package exclusion is not enforced by a floor checker. In PLAN.md, add the
package-specific verification checklist requested by the comment, while
preserving the existing CLAUDE.md enumeration reference and no-bump conclusion.
Source: Coding guidelines
| "gates": { | ||
| "format:check": 0, | ||
| "lint": 0, | ||
| "lint:md": 0, | ||
| "structural:pharn/pharn-review/trust-fence/evals/expected/expected-injection-comment.json": 0, | ||
| "test": 0, | ||
| "validate": 0 | ||
| }, | ||
| "verdict": "PASS", | ||
| "failing_gates": [], | ||
| "verifiers": { "registered": 0, "findings": [] } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- verify-report.json ---'
cat -n .dev/features/f8-package-private/verify-report.json
printf '%s\n' '--- VERIFY.md ---'
cat -n .dev/features/f8-package-private/VERIFY.md
printf '%s\n' '--- feature files and references ---'
rg -n -C 3 'npm publish|dry-run|private|main|verify-report|gates|verifier|acceptance|package-field' .dev/features/f8-package-private package.json pharn/floor 2>/dev/null || trueRepository: pharn-dev/pharn-oss
Length of output: 50378
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- feature directory ---'
git ls-files .dev/features/f8-package-private
printf '%s\n' '--- package metadata ---'
node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log(JSON.stringify({private: p.private, main: p.main}, null, 2));
JS
printf '%s\n' '--- relevant floor/checker definitions ---'
rg -n -C 4 'count-verifiers|verify-report|failing_gates|registered|dry-run|private.*true|main.*undefined' pharn .dev package.json 2>/dev/null || trueRepository: pharn-dev/pharn-oss
Length of output: 50378
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- PLAN acceptance and contracts ---'
sed -n '14,36p' .dev/features/f8-package-private/PLAN.md
printf '%s\n' '--- REVIEW evidence ---'
sed -n '12,36p' .dev/features/f8-package-private/REVIEW.md
printf '%s\n' '--- package scripts and publish-related artifacts ---'
node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log(JSON.stringify(p.scripts || {}, null, 2));
JS
rg -n -C 2 'npm publish|dry-run|private === true|main === undefined|package\.json.*private|package-field' .dev/features/f8-package-private .claude pharn --glob '!**/node_modules/**' --glob '!**/test*.mjs' 2>/dev/null || trueRepository: pharn-dev/pharn-oss
Length of output: 12387
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
import json
from pathlib import Path
report = json.loads(Path('.dev/features/f8-package-private/verify-report.json').read_text())
verify = Path('.dev/features/f8-package-private/VERIFY.md').read_text()
plan = Path('.dev/features/f8-package-private/PLAN.md').read_text()
print('report_keys:', sorted(report))
print('gate_names:', sorted(report['gates']))
print('has_named_feature_checks:', any(k in report for k in ('checks', 'acceptance_checks', 'feature_checks')))
print('verify_has_private_check:', "private === true" in verify)
print('verify_has_main_check:', "main === undefined" in verify)
print('verify_has_publish_dry_run:', "npm publish --dry-run" in verify)
print('plan_has_publish_dry_run:', "npm publish --dry-run" in plan)
print('plan_has_private_check:', 'private' in plan and 'true' in plan)
print('plan_has_main_check:', 'main' in plan and 'undefined' in plan)
PYRepository: pharn-dev/pharn-oss
Length of output: 605
Add the package-field check to verify-report.json.
VERIFY.md records private === true and main === undefined. verify-report.json contains no corresponding named check. Add a structured entry with the command, status, and result. Do not add an npm publish --dry-run requirement because the plan does not define it as an acceptance check.
📍 Affects 2 files
.dev/features/f8-package-private/verify-report.json#L3-L13(this comment).dev/features/f8-package-private/VERIFY.md#L22-L32
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.dev/features/f8-package-private/verify-report.json around lines 3 - 13, The
package-field acceptance check is missing from the verification report. In
.dev/features/f8-package-private/verify-report.json, add a structured check
matching the VERIFY.md requirement that private === true and main === undefined,
including its command, status, and result; do not add an npm publish --dry-run
check. The corresponding requirement in
.dev/features/f8-package-private/VERIFY.md requires no direct change.
Summary
"private": truetopackage.jsonso a realnpm publishrefuses instead of pushing this methodology repo (.dev/,pharn/,.claude/) under the publishable namepharn-oss— the distributable package is@pharn-dev/pharn, not this repo."main": "index.js"field (file never existed), so the package no longer claims an import surface it does not have.package.jsoncurrently claims a publish/import surface this repo does not have. NoSKILLS_VERSIONbump — pure repo-meta.Test plan
require('./package.json').private === trueand.main === undefinednpm publish --dry-runrefuses (or would refuse) with a private-package errornpm test,pharn/floor/validate.mjs ., lint/format gates.dev/features/f8-package-private/(verifyPASS, regressno-regressions, review GREEN)Made with Cursor
Summary by CodeRabbit
New Configuration
Documentation
Validation