Skip to content

refactor(agent-bundle): dedupe route, JSON, and IP-range helpers onto shared owners - #660

Merged
ScriptedAlchemy merged 2 commits into
mainfrom
refactor/ponytail-dedupe-helpers
Sep 6, 2026
Merged

ScriptedAlchemy merged 2 commits into
mainfrom
refactor/ponytail-dedupe-helpers

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

Consolidation only: local copies of helpers move onto their shared owners (dev/http.ts, core/strict-json.ts, core/errors.ts, core/paths.ts) or the stdlib. Avoid-listed files (install/**, adapters/**, build/** except entry-exports.ts, dev/routes/**, dev/mcp-session/**, dev/mcp-apps/mcp-app-routes.ts, foreground-server.ts, runtime-*-routes.ts, …) were not touched.

  1. Record guards → core/strict-json.ts — done. isRecord in claude-plugin-validation, cursor-plugin-validation, portable-plugin-validation, mcp-tasks; prototype-checking isRecord/isPlainRecordisPlainRecord in mcp-app-bridge, mcp-app-host-profiles (also its isConfigExtensionRecord alias), notice-retention, mcp-app-metadata. Note: isPlainRecord also admits null-prototype objects, which the three === Object.prototype copies did not; every caller reads structured-clone or JSON.parse output, where such objects cannot occur.
  2. Route boilerplate → dev/http.ts — done. New exports responseJsonOrDestroy(response, body, status = 200) (the nine writeJsonResponse(…, { destroyIfEnded: true }) wrappers), badRequest(code, message): () => never (the invalidShape/pathError/invalidRequest throwers), and noQuery(requestTarget, invalid). Applied to inspector-routes, logs/dev-log-routes, artifacts/artifact-routes, playground/{playground,hook-playground,lifecycle-replay,mcp-probe,host-discovery}-routes, eval/eval-routes. In eval-routes, the inline decodedSegment, jsonBody, isRecord retype and hasOnly alias are now decodedOpaqueSegment, readJsonBody, and hasOnly from dev/http.ts; codes AB8070/AB8072/AB8009/AB8001/AB8010 are unchanged. dev/routes/route-manifest-routes.ts skipped (avoid-list); web-host-routes.ts had no wrapper to replace.
  3. JSON walkers → shared — done. mcp-app-bridge and mcp-app-binding-service drop isJsonValue/cloneJson/jsonRecord for snapshotMcpAppJson/cloneMcpAppJson/snapshotMcpAppJsonRecord/requireMcpAppJson from the existing dev/mcp-apps/mcp-app-json.ts (which wraps snapshotStrictJsonValue); one-line aliases keep the ~70 bridge call sites unchanged. The shared walker additionally rejects cyclic values (the old walkers recursed without bound) and accessor/non-enumerable/symbol properties; inputs arrive via structured clone or JSON.parse, where neither occurs. Error message ${label} must be a finite JSON value. preserved.
  4. snapshotStrictJsonValue + mapStrictJsonReason for playground-store, runtime-mcp-registry, playground-routesskipped, all three, per the "messages must be reproduced exactly" rule: playground-store.json and runtime-mcp-registry.finiteJson emit a distinct … must not contain accessors. message that StrictJsonReason cannot distinguish from not-json, and both sort object keys (Object.keys(...).sort()) and the store emits null-prototype objects, which snapshotStrictJsonValue does not reproduce (observable in persisted JSON byte order). playground-routes.jsonValue enforces a depth bound (maxValueDepth = 32, AB8042) the shared walker has no equivalent for.
  5. stdlib swaps — done. combineSignals/CombinedAbortSignal in runtime-mcp-registryAbortSignal.any (two call sites, dispose() plumbing removed). throwIfAborted(signal, label) in mcp-app-binding-servicesignal?.throwIfAborted(): no test asserts the label, and every production abort() on those signals passes an Error reason (or the default AbortError), so the thrown value is identical. hasOwn one-liners in mcp-app-bridge, mcp-app-sandbox, mcp-app-metadata, app/index.tsObject.hasOwn. pathExists in epoch-store, cursor-plugin-validation, test/packed.tsexists from core/paths.ts (identical: lstat + ENOENT).
  6. errorMessage — done in config/{command,rule,skill,dev-contracts,render-markdown}.ts, install-entry.ts, mcp-tasks.ts, mcp-server-runtime.ts, including both private describeError copies (mcp-tasks, mcp-server-runtime).
  7. parseOperatorEnvutil.parseEnvskipped, not applied. util.parseEnv (Node 22.23) fails both existing launch-env.test.ts vectors: it truncates a double-quoted value at the first escaped \" (DOUBLE="two\nlines \"quoted\""two\nlines \, ESCAPED="a \" b"a \), accepts 9BAD=ignored as a key, and reads TRAILER="x" not-a-comment as x instead of the dotenv literal "x" not-a-comment. launch-env.ts is untouched.
  8. build/entry-exports.ts → TypeScript parser — done. scanEntryExportsSource now walks ts.createSourceFile(...).statements (ExportAssignment excluding export =, non-type-only ExportDeclaration named elements, export default modifier, export function main / export const|let|var … main). The 100-line stripCommentsAndStrings tokenizer is deleted. scanEntryExportsSource(source, fileName?) lets TypeScript pick the grammar from the extension (.tsx/.jsx parse JSX, .ts keeps angle-bracket assertions); every caller passes the real path. export declare … statements are skipped since they emit nothing. One test edit: entry-shell.test.ts imported stripCommentsAndStrings for one assertion (toContain('export const main') after stripping a division expression); it is now the equivalent public-API assertion scanEntryExportsSource('const division = a / b / c; export const main = 1;').hasMainExport === true. Keeping the tokenizer alive only for that line would have left a test-only module in production, so I judged this the intended outcome; revert is one line if not.
  9. Special-purpose IP detectors → net.BlockList — done, new leaf core/special-ip.ts (isSpecialPurposeIp, isNonGlobalUnicastIpv6) imported by mcp-app-host-profiles and mcp-app-sandbox; both hand parsers deleted. The two old detectors did not share one table. Verified with a /tmp old-vs-new script over every hostname in the two test files plus the eleven requested vectors: identical for both callers except ::ffff:127.0.0.1 (dotted-quad mapped form), which both old parsers failed to parse and therefore treated as public; BlockList rejects it. That input is unreachable in production (WHATWG URL serialises it as [::ffff:7f00:1], which both old and new reject). Beyond the requested vectors, the sandbox's hand-rolled IPv4 table was an approximation of the IANA registry and now follows it exactly: 192.31.196/24, 192.52.193/24, 192.175.48/24 are newly rejected; ordinary public space in 192.0/16, 192.2/16, 192.88/16, 198.51/16 outside the registry blocks (e.g. 192.0.3.1, 192.2.0.1, 192.88.1.1, 198.51.1.1) is newly accepted. The sandbox's documented fail-closed IPv6 rule (only 2000::/3) is preserved via isNonGlobalUnicastIpv6. Host-profiles behaviour is unchanged on every vector.
  10. rsc-runtime notices ledger → recipientSchemaskipped. The ledger's recipient() rejects whitespace-only axes (nonEmptyText trims) and notices-ledger.test.ts asserts recipient: { conversation: ' ' }invalid-input; recipientSchema is z.string().min(1) and accepts it, and .strict() rejects unknown keys the ledger silently drops. Reusing the journal schema would change the publish contract; @agent-bundle/runtime is untouched, so the changeset names only agent-bundle.

Validation

  • pnpm build && pnpm typecheck && pnpm lint && pnpm test:unit — green (4237 unit tests).
  • Targeted runs after each item: artifact-routes, claude/cursor/portable-plugin-validation, command-config, dev-log-routes, entry-shell, epoch-store, eval-routes, hook-playground-routes, host-discovery-routes, inspector-routes, lifecycle-replay-routes, mcp-app-{binding-service,bridge,bridge-cancellation,host-profiles,metadata,preview-service,sandbox}, mcp-probe-routes, mcp-server-runtime, mcp-tasks, notice-retention-config, playground-routes, rule-config, runtime-mcp-registry, skill-ir — 443 passed.
  • Dead-module check: git grep -l special-ip -- ':!repos' → the two importers; no remaining references to stripCommentsAndStrings, combineSignals, parseIpv6, or specialIpv4Prefixes.
  • /tmp old-vs-new IP comparison (61 vectors) as described in item 9.

Deslop

Deslop: Claude Fable 5.1, 3 edits (dropped redundant type annotations on the bridge's cloneJson/jsonRecord aliases; repaired an Object.Object.hasOwn sed artefact inside the sandbox's embedded script strings; removed a now-unused lstat import).

Self-review

Reviewer: gpt-5.6-sol-medium (generalPurpose; TraceDecay daemon was down so change-risk-reviewer could not run). Scope: all 35 files, with emphasis on the sandbox IP policy (core/special-ip.ts), abort/throwIfAborted semantics, route status/body shape, null-prototype admission per isRecord call site, and the entry-export scanner. Two findings, both fixed:

  1. build/entry-exports.ts parsed every entry as plain TS, so JSX before an export in a .tsx entry mis-parsed and JSX text containing export default could false-positive. Fixed — the source file name now selects the grammar; scanEntryExports and both config/validate.ts callers pass the real path. Tests added.
  2. export declare const|function main counted as a runtime main export. Fixed — statements with a declare modifier are skipped. Tests added.

The IP policy, abort, route, record-guard, and errorMessage substitutions were verified to preserve the reviewed contracts.

Second pass (same reviewer): no merge risks found.

@changeset-bot

changeset-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9af572b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ScriptedAlchemy
ScriptedAlchemy force-pushed the refactor/ponytail-dedupe-helpers branch from a512673 to c4b2393 Compare September 6, 2026 00:38
@pkg-pr-new

pkg-pr-new Bot commented Sep 6, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@660
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@660
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@660
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@660

commit: c4b2393

@ScriptedAlchemy
ScriptedAlchemy marked this pull request as ready for review September 6, 2026 00:45
@ScriptedAlchemy
ScriptedAlchemy enabled auto-merge (squash) September 6, 2026 00:45
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@ScriptedAlchemy
ScriptedAlchemy merged commit 3b92ab4 into main Sep 6, 2026
5 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the refactor/ponytail-dedupe-helpers branch September 14, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant