From 6fdbd92ff567d67a0fff3176e3052e76aaddd102 Mon Sep 17 00:00:00 2001 From: Callum Flack Date: Thu, 29 Oct 2026 17:17:24 +1000 Subject: [PATCH 1/2] fix(connectors): expose public Factory installation guidance --- LOG.md | 22 ++++++++++++++++++++++ skills/create-connector/SKILL.md | 12 ++++++++---- src/cli/connector-build-instructions.ts | 17 ++++++++++------- test/cli/connector-build.test.ts | 9 +++++++++ 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/LOG.md b/LOG.md index ca58d98..6af2660 100644 --- a/LOG.md +++ b/LOG.md @@ -86,3 +86,25 @@ The external autoreview helper was blocked by automatic approval review because its repository payload and model-service destination were not authorized for this repair; no alternative external transport was used. CI remains the final authority after the scoped push. + +## Public Factory installation, 29 October 2026 + +User authorized an exact public install route through Vana's bundled Factory +instructions and a released CLI with a fresh-agent synthetic acceptance. This +worktree is isolated from active CLI work and #106. No real-provider reads. + +Factory's core will be a licensed, public, versioned release tarball containing +its executable, instructions and checks. The private Factory repository remains +private. A public npm registry listing is not available with current credentials; +this must remain distinct from successful public tarball installation. + +The existing current-agent job/check/collection flow remains unchanged. Vana's +instructions name the exact public artifact and Node/checkout requirements. +Parent owns delivery and the independent public-only acceptance after release. + +The public-guidance regression failed before repair. All 45 focused tests then +passed, followed by full typecheck, ESLint, formatting and 952 tests in 66 files. +The built CLI exposes its offline instructions even when Factory is absent. +Instructions name the exact public factory-core 0.0.1 release artifact and the +real Node 24 / public upstream setup requirements. Publication, fresh-agent +public-only collection and acceptance evidence remain parent-owned. diff --git a/skills/create-connector/SKILL.md b/skills/create-connector/SKILL.md index 785b8bd..f879bad 100644 --- a/skills/create-connector/SKILL.md +++ b/skills/create-connector/SKILL.md @@ -19,10 +19,14 @@ The current agent writes and repairs the connector. Factory supplies the explicit job, private work instructions and executable checks. Do not launch another coding agent or service. -1. Read the bundled instructions. Use a compatible data-connectors checkout, - synthetic or explicitly reviewed evidence, and a separately installed - `factory-build` executable under a real Node 24+ runtime on macOS or Linux. - The instructions include a local tarball installation example. +1. Read the bundled instructions. They include the public data-connectors + checkout, its locked dependency installation and the exact public + `@vana/factory-core@0.0.1` release artifact to install locally. No private + Factory access or internal service is required. Use synthetic or explicitly + reviewed evidence and a real Node 24 runtime on macOS or Linux; Node 24.22.1 + is recommended for both Factory and the checkout. The instructions set + `VANA_FACTORY_TOOLS` under `VANA_HOME` (otherwise `~/.vana`) and + `VANA_FACTORY_BUILD` to the installed executable. 2. Save a version 1 request file with absolute checkout/evidence paths, source identity, directory key, exact manifest key, requested streams, and export environment variable name or API preparation plan. The bundled instructions diff --git a/src/cli/connector-build-instructions.ts b/src/cli/connector-build-instructions.ts index b93adc0..dd4732a 100644 --- a/src/cli/connector-build-instructions.ts +++ b/src/cli/connector-build-instructions.ts @@ -1,13 +1,16 @@ /** Offline instructions compiled into npm and standalone Vana distributions. */ export const CONNECTOR_BUILD_INSTRUCTIONS = `Build a Collection Profile connector with the current agent -1. Use a compatible data-connectors checkout. Factory supports synthetic or explicitly reviewed export evidence and declared API preparation. Browser preparation remains unsupported. -2. Install the separately supplied Factory package under a real Node 24+ runtime on macOS or Linux. Put factory-build on PATH, or set VANA_FACTORY_BUILD to its absolute executable path. Vana never installs or downloads it. The external executable supplies its own Node host, including when Vana runs on Node 22 or as a standalone binary. -Install a supplied local tarball, without publishing it or relying on a registry package: - export PATH="/absolute/path/to/node24/bin:$PATH" - npm install --prefix /absolute/path/to/factory-tools /absolute/path/to/vana-factory-core-0.0.1.tgz - export VANA_FACTORY_BUILD="/absolute/path/to/factory-tools/node_modules/.bin/factory-build" - /absolute/path/to/factory-tools/node_modules/.bin/factory-build capabilities --json +1. Select a real Node 24 runtime on macOS or Linux; Node 24.22.1 is recommended for Factory and the public data-connectors checkout (which requires Node >=24.15.0 <25). Ensure node --version reports that runtime and its bin directory is on PATH. Use an existing compatible checkout, or clone the public source and install its locked tools: + git clone https://github.com/PDP-Connect/data-connectors.git /absolute/path/to/data-connectors + cd /absolute/path/to/data-connectors + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm ci +Read AUTHORING.md and docs/spec/collection-profile.md in that checkout before writing the connector. Factory needs the packages/polyfill-connectors layout, Git metadata and installed TypeScript, tsx and Biome inside the checkout. Do not link dependencies from another checkout. Factory supports synthetic or explicitly reviewed export evidence and declared API preparation. Browser preparation remains unsupported. +2. Install the public @vana/factory-core@0.0.1 release artifact locally. This needs no private Factory repository access, internal services or Factory account. Put factory-build on PATH, or set VANA_FACTORY_BUILD to its absolute executable path. Vana never installs or downloads it. The external executable supplies its own Node host, including when Vana runs on Node 22 or as a standalone binary. + export VANA_FACTORY_TOOLS="\${VANA_HOME:-$HOME/.vana}/factory-tools" + npm install --prefix "$VANA_FACTORY_TOOLS" --ignore-scripts --no-audit --no-fund https://github.com/vana-com/vana-cli/releases/download/v0.45.0/vana-factory-core-0.0.1.tgz + export VANA_FACTORY_BUILD="$VANA_FACTORY_TOOLS/node_modules/.bin/factory-build" + "$VANA_FACTORY_BUILD" capabilities --json Use the installed executable's absolute path for the capability command if it is not on PATH. The PATH must select the real Node 24+ executable used by its shebang. Require protocolVersion 1, contextVersion 2, apiPreparationVersion 1 and supportedRoutes ["export", "api"]. Older context versions are incompatible. 3. Save a version 1 request JSON file. Use absolute checkout and evidence paths. Declare environment variable names only, never credential values or raw export contents. diff --git a/test/cli/connector-build.test.ts b/test/cli/connector-build.test.ts index 48191d0..d323891 100644 --- a/test/cli/connector-build.test.ts +++ b/test/cli/connector-build.test.ts @@ -222,6 +222,15 @@ describe("connector build subprocess policy", () => { }); expect(output.value.instructions).toContain("static_and_fixture"); expect(output.value.instructions).toContain("VANA_FACTORY_BUILD"); + expect(output.value.instructions).toContain( + 'npm install --prefix "$VANA_FACTORY_TOOLS" --ignore-scripts --no-audit --no-fund https://github.com/vana-com/vana-cli/releases/download/v0.45.0/vana-factory-core-0.0.1.tgz', + ); + expect(output.value.instructions).toContain( + 'export VANA_FACTORY_TOOLS="${VANA_HOME:-$HOME/.vana}/factory-tools"', + ); + expect(output.value.instructions).toContain( + "git clone https://github.com/PDP-Connect/data-connectors.git", + ); await expect(readFile(callsFile)).rejects.toMatchObject({ code: "ENOENT" }); }); From b9768a89e6b24cdb5f5051f6332793e811824f84 Mon Sep 17 00:00:00 2001 From: Callum Flack Date: Thu, 29 Oct 2026 17:25:15 +1000 Subject: [PATCH 2/2] fix(ci): isolate registry fixtures and publish reviewed Factory artifact --- .github/workflows/publish-factory.yml | 24 ++++++++++++++++++++++++ LOG.md | 18 ++++++++++++++++++ test/connectors/registry.test.ts | 19 +++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/publish-factory.yml diff --git a/.github/workflows/publish-factory.yml b/.github/workflows/publish-factory.yml new file mode 100644 index 0000000..699f529 --- /dev/null +++ b/.github/workflows/publish-factory.yml @@ -0,0 +1,24 @@ +name: Publish Factory core + +on: + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v6 + with: + node-version: 24.22.1 + registry-url: https://registry.npmjs.org + - name: Download the licensed public package + run: curl --fail --location --output vana-factory-core-0.0.1.tgz https://github.com/vana-com/vana-cli/releases/download/v0.45.0/vana-factory-core-0.0.1.tgz + - name: Verify the reviewed artifact + run: echo '58f9d3cadbf456bb77e5e6ce22a37a34c65d18f338a04ecfaba4e95ab5ac19f3 vana-factory-core-0.0.1.tgz' | sha256sum --check + - name: Publish the exact artifact to npm + run: npm publish ./vana-factory-core-0.0.1.tgz --ignore-scripts --access public --tag latest + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/LOG.md b/LOG.md index 6af2660..ea9134d 100644 --- a/LOG.md +++ b/LOG.md @@ -108,3 +108,21 @@ The built CLI exposes its offline instructions even when Factory is absent. Instructions name the exact public factory-core 0.0.1 release artifact and the real Node 24 / public upstream setup requirements. Publication, fresh-agent public-only collection and acceptance evidence remain parent-owned. + +The CLI publisher already has a working npm credential inside GitHub Actions. +Add a manual Factory publication job using that existing secret, the exact +public tarball and its pinned SHA256. It cannot publish an arbitrary URL or +artifact. No credential is extracted. Namespace permissions may still prevent +this registry listing; the public tarball remains independently installable. + +PR CI exposed a preexisting registry test's unintended GitHub metadata fetch. +A rejecting fetch guard plus no-call assertion failed on that exact request. +Supplying the missing local metadata fixture repairs it without production or +timeout changes. All twelve registry tests pass under Node 26 and Node 24, +including the explicit offline failure cases. The same guard now catches any +future fixture omission instead of silently relying on the external network. + +Final combined CLI validation passes typecheck, ESLint, formatting and all 952 +tests. The public tarball was downloaded anonymously and installed with private +checkout/config reads denied; its capabilities report version 0.0.1 and supported +API/export routes. The downloaded hash matches the frozen licensed artifact. diff --git a/test/connectors/registry.test.ts b/test/connectors/registry.test.ts index ecb0fa7..7d6f0e9 100644 --- a/test/connectors/registry.test.ts +++ b/test/connectors/registry.test.ts @@ -26,14 +26,20 @@ const MOCK_REGISTRY = { }; describe("fetchConnectorToCache", () => { + const unexpectedFetch = vi.fn(async () => { + throw new Error("Unexpected network request in local connector fixture"); + }); + beforeEach(async () => { + unexpectedFetch.mockClear(); + vi.stubGlobal("fetch", unexpectedFetch); tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "vana-registry-test-")); cacheDir = path.join(tempRoot, "connectors"); dataConnectorsDir = path.join(tempRoot, "data-connectors"); await fs.mkdir(cacheDir, { recursive: true }); await fs.mkdir(dataConnectorsDir, { recursive: true }); - // Write local registry and connector script + // Include every file the local connector download can read. await fs.writeFile( path.join(dataConnectorsDir, "registry.json"), JSON.stringify(MOCK_REGISTRY), @@ -44,10 +50,19 @@ describe("fetchConnectorToCache", () => { path.join(scriptDir, "github-playwright.js"), MOCK_SCRIPT, ); + await fs.writeFile( + path.join(scriptDir, "github-playwright.json"), + JSON.stringify({ id: "github-playwright", version: "1.2.0" }), + ); }); afterEach(async () => { - await fs.rm(tempRoot, { recursive: true, force: true }); + try { + expect(unexpectedFetch).not.toHaveBeenCalled(); + } finally { + vi.unstubAllGlobals(); + await fs.rm(tempRoot, { recursive: true, force: true }); + } }); it("downloads connector when no currentVersion is provided", async () => {