Skip to content

fix(mcp): registry-safe README embedding — JSR rejects text-import attributes#810

Merged
rickylabs merged 11 commits into
mainfrom
fix/mcp-readme-text-import
Jul 17, 2026
Merged

fix(mcp): registry-safe README embedding — JSR rejects text-import attributes#810
rickylabs merged 11 commits into
mainfrom
fix/mcp-readme-text-import

Conversation

@rickylabs

@rickylabs rickylabs commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

JSR rejected @netscript/mcp@0.0.1-beta.10 while building cli.ts because the registry does not support with { type: "text" }, even though local deno publish --dry-run passes. This draft replaces publishable import attributes with checked-in generated constants, keeps those constants fresh through release cuts and CI, and hardens release preflight against the registry-only failure class.

Publish evidence: publish.yml run 29558968037 failed @netscript/mcp@0.0.1-beta.10 at file:///cli.ts:18:27 with The import attribute type of "text" is unsupported; 33 siblings published and @netscript/cli was dependency-skipped.

Scope

Slices

  • S1 harness bootstrap and locked design — 1934f357, PLAN-EVAL b5568180
  • S2 generated publish assets and complete publish-surface sweep — 7c17a6d1
  • S3 registry-failing preflight and corrected release guidance — ad0e5d54, owner correction 03a1111f
  • S4 release-cut/CI freshness integration and evaluator handoff — 169e2544, 594f4240
  • Separate IMPL-EVAL PASS and no-suppression follow-up — 6de08672, 17d287dc, 6258cf71

Definition of Done

  • No with { type: ... } import attribute remains in publishable packages/** or plugins/** source.
  • MCP README/docs corpus and needed package assets are deterministic generated constants with a freshness task.
  • Freshness gate is witnessed green and failing on a seeded stale output.
  • Release preflight is witnessed green on the fixed tree and failing on a seeded import attribute.
  • Release cuts regenerate after the version bump, stage all generated outputs, and CI enforces freshness.
  • Embedded README data is semantically classified without adding a validator suppression or allowance.
  • Focused MCP tests, MCP publish dry-run, changed-file quality scan, architecture check, release-cut tests, and skill sync pass.
  • Separate-session IMPL-EVAL returns PASS.

Validation

  • PLAN-EVAL — PASS in separate local Qwen session f03ae1dd-da69-406a-b725-f3bf391255a8.
  • Opposite-family ordinary review — PASS in Claude Opus session 12b534fe-2771-462a-b012-c61c91968f2a after its release-cut drift finding was fixed.
  • IMPL-EVAL — PASS in separate local Qwen session e12ca085-a89a-4bc7-b144-5482f8b4289f; artifact .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/evaluate.md.
  • MCP tests — PASS, 45/45; MCP publish:dry-run — PASS.
  • Scanner tests — PASS, 7/7; release-cut tests — PASS, 6/6.
  • release:preflight — PASS on the fixed tree; seeded import attribute exits 1 with the conditional upstream/canary sunset criterion.
  • check:publish-assets — PASS on the fixed tree; seeded stale output exits 1 and names the stale file.
  • Changed-file quality scan — 0 findings / 0 allowances; arch:check — PASS with baseline warnings only.
  • Skill mirror regeneration/sync — PASS, 17 skills / 21 mirrored files.
  • JSR emitted-specifier guard — PASS, 0 failures; the only allowance is pre-existing, and the focused test proves non-README source in the same generated file remains enforced.

Harness

  • Run dir: .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/
  • Phase: impl-eval PASS; PR intentionally remains draft and status:impl-eval per the hotfix handoff constraint.

Integration with #812

PR #812 composes this PR's canonical release:preflight task into publish:readiness; it does not duplicate the import-attribute scanner. The #812 tests seed the task boundary and preserve this PR's sunset criterion: lift the ban only after denoland/deno#35546 is fixed, merged, and released in the pinned Deno version and an authenticated canary text-import probe is green.

Drift / Debt

  • PLAN-EVAL transport fallback/recovery is recorded in drift.md; the successful formal verdict used the canonical local Qwen route.
  • No architecture debt created or deepened.

@rickylabs rickylabs added this to the 0.0.1-beta.10 milestone Jul 17, 2026
@rickylabs rickylabs added type:fix area:tooling status:plan-eval Awaiting plan evaluation priority:p0 Critical / release blocker labels Jul 17, 2026
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: PLAN]

Registry-safe publish plan locked at 1934f357.

Locked decisions

  1. Generated TypeScript constants are the only sanctioned bundled-asset form.
  2. Release preflight rejects every with { type: ... } attribute on the actual publish-rule-filtered source surface.
  3. The gate is proven both green and red on seeded violations/stale output.

Next

  • Separate OpenHands/Qwen PLAN-EVAL; no implementation before PASS.

@rickylabs

Copy link
Copy Markdown
Owner Author

@openhands-agent model=openrouter/qwen/qwen3.7-max provider=openrouter effort=xhigh output=pr-comment

use harness

SKILL

  • netscript-harness; netscript-doctrine; netscript-release; netscript-tools; jsr-audit

Act as the separate formal PLAN-EVAL session for run .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/ in /home/codex/repos/b10-textimport.

Read .llm/harness/evaluator/plan-protocol.md, .llm/harness/gates/plan-gate.md, the selected ARCHETYPE-6-cli-tooling.md, the gate matrix, relevant debt, and the run's research.md, plan.md, and worklog.md Design section. Spot-check load-bearing findings against the current tree. Evaluate only the plan; do not implement or edit product/release source.

Write the completed verdict to .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/plan-eval.md using the template. Emit exactly PASS or FAIL_PLAN in that artifact, with checklist evidence and required fixes if any. This is a separate evaluator session from the Codex generator.


OUTPUT CONTRACT (mandatory — verdict first)

  1. Post the verdict PR comment IMMEDIATELY after you form the verdict — BEFORE any
    optional deep-dive, extra verification, or long context dump. Iteration budgets
    exhaust; a verdict comment deferred to the end of the run is frequently lost.
  2. That PR comment MUST start with the formal header line, exactly:
    [PHASE: ] [VERDICT: ]
    where is your eval phase (e.g. IMPL-EVAL, PLAN-EVAL) and is one
    of PASS, FAIL_FIX, FAIL_RESCOPE, FAIL_DEBT, FAIL_PLAN.
  3. ALWAYS end BOTH the verdict PR comment AND your summary file with one final
    machine-readable line of the exact form:
    OPENHANDS_VERDICT:
    using a literal token from: PASS, FAIL_FIX, FAIL_RESCOPE, FAIL_DEBT, FAIL_PLAN,
    NONE. Use NONE only when no verdict could be reached.

@rickylabs

rickylabs commented Jul 17, 2026

Copy link
Copy Markdown
Owner Author

OpenHands Agent — Agent failed

OPENHANDS_VERDICT: NONE

Model: openrouter/qwen/qwen3.7-max
Provider: OPENROUTER
Job status: failure
Verdict source: none
Summary source: none
Housekeeping: ack=success trace=success commit-artifacts=success replies=skipped draft-pr=skipped
Trace: .llm/tmp/run/openhands/pr-810/run-29559553914-1 (in the Actions artifact)
Artifact: openhands-agent-29559553914-1

OpenHands Agent Summary

The agent run failed before producing a summary.

This is a workflow failure, not a task verdict.

Diagnostics

See the uploaded Actions artifact for bootstrap.log and agent.log when present.

Run: https://github.com/rickylabs/netscript/actions/runs/29559553914

@rickylabs

Copy link
Copy Markdown
Owner Author

Historical lineage — this is the SECOND time this defect shipped (supervisor note)

Consequences encoded in this PR (verify at review):

  1. The preflight ban on with { type: … } in publishable source is permanent doctrine, not a workaround — it must survive the upstream fix (defense in depth; the rejection path is untestable locally). The gate must be proven-to-fail on a seed.
  2. The prose (release skill + preflight comments) must cite this lineage (fix(release): enable --unstable-raw-imports for whole-workspace publish (alpha.5 republish) #138/chore(release): restore text-import asset embedding + bump to 0.0.1-alpha.6 #142/chore(release): recover alpha.6 half-publish via alpha.7 string-const embedding #143 → beta.10 → deno publish rejects ("import attribute type of text is unsupported") even though it is runtime-stable and --dry-run accepts it denoland/deno#35546) so the rule cannot be "simplified away" again when someone reads that text imports are stable.

Follow-up (separate issue, beta.11): a release:canary authenticated publish gate to a scratch scope — the only honest pre-release test of registry acceptance.

🤖 Generated with Claude Code

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: PLAN-EVAL] [VERDICT: PASS]

Separate local Claude Code + OpenRouter/Qwen session f03ae1dd-da69-406a-b725-f3bf391255a8 passed every Plan-Gate item. It spot-checked the registry-rejected MCP import, existing generated-constant pattern, publish-rule filtering, and the broader publishable attribute sweep.

Artifact: .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/plan-eval.md

Next

  • Implementation slice 2 may begin.

OPENHANDS_VERDICT: PASS

@rickylabs rickylabs added status:impl and removed status:plan-eval Awaiting plan evaluation labels Jul 17, 2026
@rickylabs

Copy link
Copy Markdown
Owner Author

Owner correction to my lineage note above (supersedes point 1): the preflight ban on import attributes is conditional, not permanent — it carries an explicit sunset criterion: lift only when denoland/deno#35546 is fixed, merged, AND released, and the fix is verified by a green authenticated canary publish of a text-import probe. Encode that sunset condition (with the upstream issue link) directly in the preflight check's message and the release-skill prose, so lifting it later is a deliberate, evidence-backed act rather than drift in either direction.

🤖 Generated with Claude Code

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL]

S2 generated publish assets and the complete publish-surface sweep landed at 7c17a6d1.

Scope

  • MCP README/version, CLI version/schema, and six plugin versions are deterministic generated TypeScript constants.
  • All attributes selected by actual package/plugin publish rules were removed; remaining raw attributes are excluded tests/verifiers or inert generated template text.
  • Added gen:publish-assets + non-mutating check:publish-assets.

Evidence

  • MCP: check PASS; 45 tests PASS; publish dry-run PASS.
  • CLI + ai/auth/sagas/streams/triggers/workers checks PASS.
  • Freshness PASS and seeded stale-output exit 1 witnessed.
  • Changed-file quality scan: 0 findings/allowances.
  • arch:check: exit 0.

Reconcile

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL]

S3 registry-failing release preflight and corrected guidance landed at ad0e5d54.

Scope

  • Publish-rule-filtered source now fails on any real with { type: ... } syntax.
  • Strings, comments, and template payloads are lexically excluded; line attribution is preserved.
  • Import-meta asset-read remediation now points only to generated TypeScript constants.
  • Release and JSR-audit skills are corrected in both .agents and .claude.

Evidence

  • Scanner tests: 7 PASS.
  • Fixed-tree release:preflight: PASS, zero attribute findings.
  • Explicit seeded JSON attribute: exit 1 with file/line finding.
  • Skill mirror/hook lock check: PASS.
  • Focused wrapper fmt/lint: 0 findings.

Reconcile

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL] [VERDICT: FAIL_FIX ADDRESSED]

Commit 03a1111f encodes the owner correction: the preflight failure now states the conditional ban, links denoland/deno#35546, and names the fixed + merged + released + authenticated-green-canary sunset. The netscript-release and jsr-audit source skills carry the #138/#142 alpha.6 half-publish → #143 string-constant recovery → beta.10 partial publish → denoland/deno#35546 lineage; mirrors were regenerated.

Evidence: scanner tests 7/7 PASS; seeded import attribute exits 1 with the required sunset message; agentic skill sync check PASS; drift.md now explicitly records the PLAN-EVAL fallback lane. Awaiting separate evaluator recheck.

@rickylabs

Copy link
Copy Markdown
Owner Author

IMPL-EVAL — cycle 2 PASS (supervisor-dispatched; Claude · Fable 5 · low, review_codex)

Verdict: .llm/runs/beta10-cli--orchestrator/slices/textimport-fix/evaluate.md. Cycle 1 verified the mechanism end-to-end (zero import attributes on the publish surface, freshness gate + preflight both proven-to-fail on seeds, mcp docs tools live-smoked against the generated-constant corpus — no #809 regression); cycle 2 confirms the owner's sunset criterion (denoland/deno#35546 + canary-probe condition) is in the scanner message with a test asserting it, and the #138/#142/#143 lineage is in both skill sources with mirrors in sync. Incidental live proof: a seeded violation passed deno publish --dry-run — dry-run structurally cannot catch this class.

Merging on CI green; then fast-forwarding tag v0.0.1-beta.10 to fixed main and re-dispatching publish.yml (33 already-published members skip; @netscript/mcp + @netscript/cli publish at the same semver).

🤖 Generated with Claude Code

@rickylabs
rickylabs marked this pull request as ready for review July 17, 2026 06:57
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL]

CI guard classification fix landed at 2c41803a.

  • Added an explicit path allowance only for packages/mcp/src/publish-assets.generated.ts: its matches are embedded documentation strings and are never emitted or executed as framework specifiers.
  • Added regression coverage proving that exact generated file is allowed while the same versionless jsr:@netscript/mcp in any other MCP source remains a failure.

Evidence: guard test 1/1 PASS; deno task check:netscript-jsr-specifiers PASS with the scoped MCP documentation allowances and zero failures; focused format/lint PASS. PR remains draft at status:impl-eval.

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL] [VERDICT: PASS]

Separate local Claude Code + OpenRouter/Qwen session e12ca085-a89a-4bc7-b144-5482f8b4289f independently verified the approved plan and corrected implementation.

Evidence: MCP tests 45/45; scanner tests 7/7; release-cut tests 6/6; freshness and preflight green plus seeded-red proofs; MCP publish dry-run; changed-file quality scan; architecture check; skill mirror sync; release-cut regeneration/staging and CI freshness integration.

Artifact: .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/evaluate.md (6de08672).

The PR remains draft at status:impl-eval; it is not merged.

OPENHANDS_VERDICT: PASS

@rickylabs
rickylabs marked this pull request as draft July 17, 2026 07:02
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL] [VERDICT: PASS]

Follow-up in the same separate Qwen evaluator session e12ca085-a89a-4bc7-b144-5482f8b4289f verified the explicit no-new-suppressions constraint after 17d287dc.

The blanket generated-file allowance was removed. Only the MCP_PACKAGE_README initializer is semantically classified as embedded data; the focused test asserts zero new allowances and proves versionless specifiers elsewhere in the same file remain findings. Full guard: 2,156 files scanned, 0 failures, 1 pre-existing scaffold alias allowance.

Updated artifact: .llm/runs/fix-mcp-readme-text-import--beta10-jsr-hotfix/evaluate.md at 6258cf71.

The PR remains draft at status:impl-eval; it is not merged.

OPENHANDS_VERDICT: PASS

@rickylabs
rickylabs marked this pull request as ready for review July 17, 2026 07:15
@rickylabs
rickylabs merged commit 8a8a953 into main Jul 17, 2026
14 checks passed
@rickylabs

Copy link
Copy Markdown
Owner Author

Upstream loop closed: root cause filed against the registry as jsr-io/jsr#1478 (server-side analyzer builds its graph with unstable_text_imports: false — full chain + proposed 2-line fix in a sub-comment there), and denoland/deno#35546 cross-referenced with the reframing (Deno CLI not at fault; issue effectively belongs to jsr-io/jsr). The preflight ban here keeps its sunset criterion pointed at the upstream resolution.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant