Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/publish-factory.yml
Original file line number Diff line number Diff line change
@@ -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 }}
40 changes: 40 additions & 0 deletions LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,43 @@ 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.

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.
12 changes: 8 additions & 4 deletions skills/create-connector/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 10 additions & 7 deletions src/cli/connector-build-instructions.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
9 changes: 9 additions & 0 deletions test/cli/connector-build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" });
});

Expand Down
19 changes: 17 additions & 2 deletions test/connectors/registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ const MOCK_REGISTRY = {
};

describe("fetchConnectorToCache", () => {
const unexpectedFetch = vi.fn<typeof fetch>(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),
Expand All @@ -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 () => {
Expand Down
Loading