Repository navigation
feat(adk): @pcc/adk skeleton with a pinned agent package and a clean external install check (R4 D1) - #411
Open
LamaSu wants to merge 4 commits into
Open
feat(adk): @pcc/adk skeleton with a pinned agent package and a clean external install check (R4 D1)#411LamaSu wants to merge 4 commits into
LamaSu wants to merge 4 commits into
Conversation
…external install check (R4 D1)
The first cut of the one public ADK package (working name; it stays
"private": true until the operator decides npm publishing and the public
name, queue 36 D1/D2). It depends only on the public @pcc/spec and
@pcc/kernel-sdk, and re-exports kernel-sdk (the digital-kernel backend, R2).
Pinned agent package, no hand-written tool JSON (#2392):
- scripts/generate-agent-pin.mjs writes src/generated/agent-pin.ts from
apps/dashboard/public/agent-package.json: schema, version, tool count,
the sha256 of the exact bytes, and each tool's method/path/required.
A test fails when the pin is stale, so a package change regenerates it.
- resolveToolRequest(name, input, { baseUrl }) builds the gateway request.
It is pure and never adds credentials. It refuses endpoints that are not
gateway paths (the agent package still lists pcc_generate_ui at
http://localhost:3200, the N50 class), "." or ".." path parameters, and
non-http(s) base URLs; path parameters are URL-encoded.
- checkAgentPackage(text) compares a live /agent-package.json with the pin.
Clean external install (scripts/clean-install-check.mjs): build and pnpm
pack spec, kernel-sdk and adk; a boundary gate on every tarball (no
workspace:, no @pcc/* outside the packed set or private, no chain client,
no key or env file); a consumer project outside the workspace installed
OFFLINE from the local store via pnpm.overrides; a Node ESM import and a
TypeScript consumer type-check against the installed declarations. It
passes; with viem added to adk it fails at the gate, and with a private
@pcc dependency it fails at pack. Not wired into CI (a ci.yml change needs
the operator).
pnpm-lock.yaml gains only the packages/adk importer (16 lines); a frozen
offline install accepts it. adk tests 10/10; tsc clean.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy
This was referenced Sep 24, 2026
AGENT_TOOLS is a plain object literal, so a name inherited from Object
("constructor", "toString", "__proto__", "hasOwnProperty", "valueOf") found a
function or Object.prototype instead of nothing. resolveToolRequest then threw
"TypeError: Cannot read properties of undefined (reading 'startsWith')" rather
than AdkToolError("unknown_tool"), so a caller that maps AdkToolError codes
got an untyped crash.
The lookup now requires an own property. The new test fails before this change
and passes after it. adk tests pass 11/11; tsc is clean; the pin is current;
the clean external install check passes.
agent: pcc-adk (4f6668ed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ON only, validate endpoints (verdict 101)
F1. The generated AGENT_PACKAGE_PIN and AGENT_TOOLS are now deeply frozen
(src/deep-freeze.ts), and resolveToolRequest and checkAgentPackage never read
them after load: they use private frozen copies taken when agent-package.ts
loads (a Map of endpoints and the pin's three fields).
F2/F3. The ADK surface is an explicit list instead of a wildcard re-export of
@pcc/kernel-sdk: buildManifest, plus the agent-package exports. The kernel-sdk
registration client and job handler are no longer part of the kit. A test
pins the exact export list, so a new export is a reviewed change.
F4. resolveToolRequest snapshots its input once, as plain JSON: plain objects
(Object.prototype or null prototype) and arrays only, own enumerable data
properties only, string keys, finite numbers, no holes, no cycles, bounded
depth; undefined object fields are dropped as JSON.stringify drops them. The
required check, the path parameters, the query and the body all read that one
snapshot, and the body is written from it without consulting toJSON.
F5. The generator refuses a package it cannot pin faithfully: a reserved,
malformed or duplicate tool name, an unknown method, a malformed required
list, or a path that is neither a well-formed gateway path nor an http(s)
URL. A gateway path is segments of plain path characters or whole {name}
placeholders, with no empty or dot segment, so no query, fragment,
backslash, percent-escape or dot segment can reach a URL parser. The
resolver applies the same rules at call time (the tests run one corpus
through both) and refuses a URL that a parser would not send as built.
Every new test fails at f8c86a2 (13 of 15 at first run) and passes now.
Mutation checks: each guard removed alone fails a test, except the dot-segment
check and the URL round-trip check, which each catch dot segments on their
own (removing both fails). adk tests 29/29; tsc clean; the pin is current.
agent: pcc-adk (4f6668ed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…graph, and the payload (verdict 101 F6) The gate's rules move to scripts/boundary-policy.mjs: pure functions with no side effects on import, unit-tested in src/__tests__/boundary-policy.test.ts, so the tests exercise exactly what the check enforces. - Dependency specs are resolved to the registry package they install: an npm: alias is checked by its target as well as its name, and a spec that is not a registry range (file:, link:, git, URL, workspace:, catalog:) or a bundled dependency is refused. The chain-client list now covers the common families by prefix. - After the offline install, every package in the consumer's pnpm store is checked by the name in its own package.json, so a transitive chain client or a foreign @pcc/* package fails. The walk must find all three packed packages, or the check fails. - The payload is an allowlist: package.json, README, LICENSE, and dist/ build output (.js, .d.ts, maps, json) whose src/ source exists. A stray or stale file fails, whatever its name. Each payload file's text is scanned for secret shapes (private key blocks, PCC, AWS, GitHub, Stripe and Slack tokens, secret-valued key fields). - The check deletes and rebuilds the three packages' dist/ first, so stale build output is not packed at all. - The import step requires the kit's real surface and fails if it exports a registration client or a kernel handler. The README now says what the gate checks, and that its lists catch known names and shapes only. Reproduced at f8c86a2 by running the old gate's own loop and regex on crafted inputs (npm:viem and npm:@pcc/private-package aliases passed; dist/operator.key, id_ecdsa, credentials.json, .p12 and .PEM files passed), and by packing a stale dist/operator.key into the adk tarball. Now: adk tests 39/39, tsc clean, the pin current, and the full clean-install check passes (6 installed packages). With a planted fake key in a source file, it fails on the packed dist output. agent: pcc-adk (4f6668ed) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
LamaSu
marked this pull request as ready for review
October 3, 2026 07:15
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The first cut of R4 D1:
packages/adk(@pcc/adk, working name), plus a clean external install check that proves the public kit installs and imports outside this workspace, with no npm publish.It is interface work, per the reconciliation note (
returns/pcc-adk.md§0.5 D1) and board row R4. The package is"private": trueuntil the operator decides npm publishing and the public name (queue 36, D1 and D2). Nothing publishes.The package
@pcc/specand@pcc/kernel-sdkonly. It re-exports kernel-sdk, which is the digital-kernel backend (R2).scripts/generate-agent-pin.mjswritessrc/generated/agent-pin.tsfromapps/dashboard/public/agent-package.json. The pin holds the schema, version (2.19.1), tool count (253) and the sha256 of the exact bytes, plus each tool's{method, path, required}.pnpm --filter @pcc/adk generate). FYI aeo.resolveToolRequest(name, input, { baseUrl })turns a tool call into{method, url, body?}.pcc_generate_uiathttp://localhost:3200/api/generate, the N50/N11 class; R43 removes it..,..and empty path parameters, which URL normalization would turn into a different route.checkAgentPackage(text)compares a live/agent-package.jsonwith the pin: sha256, version and tool count.Clean external install:
pnpm --filter @pcc/adk check:clean-installpnpm pack,spec,kernel-sdkandadk. Pack rewritesworkspace:*.workspace:left in the package;@pcc/*dependency that is outside the packed set or private in the workspace;viem,ethers,wagmi, …);pnpm.overridespointing at the other two tarballs. It installs offline from the local pnpm store, so there is no network access.Result: passes. It prints "agent package 2.19.1 (253 tools)", then "a TypeScript consumer type-checks against the installed declarations". Negative checks:
viemadded to adk, it fails at the gate (depends on chain client viem);@pcc/gatewaydependency, it fails at pack.It is not wired into CI. A
ci.ymlstep needs operator approval; I'll propose one once this shape is agreed.Lockfile
pnpm-lock.yamlgains only thepackages/adkimporter (16 lines), and a frozen offline install accepts it. A plainpnpm installhad also re-resolved unrelatedzodpeers for viem and wagmi. I dropped that churn deliberately.Tests
tsc --noEmitclean.Next (not in this PR)
planProvenanceonce feat(spec): planProvenance, the deterministic provenance planner (ADK D2) #406 lands.🤖 Generated with Claude Code
https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy