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
22 changes: 22 additions & 0 deletions .github/workflows/package-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Package install smoke

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
package:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- run: npm ci
- run: npm run test:package
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes to pot-cli will be documented in this file.

## [0.8.12] - Unreleased

### Fixed
- Pin `@pot-sdk2/bridge` to the tested `1.2.0`. Fresh npm installs of
`0.8.11` selected `1.3.0`, which removed `checkAuthorVerifierSeparation`
and caused every CLI command to fail during module loading.
- Read the CLI `--version` from the installed package instead of the
hard-coded `0.5.0`.

### Added
- `npm run test:package` packs the build, installs it in a clean consumer
without the development lockfile, and checks `--version` and
`ask --dry-run`. Both checks reproduced the `0.8.11` import failure.

## [0.8.11] - 2026-10-09

Sentinel had been shipping these fixes only as a hand-patched
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pot-cli",
"version": "0.8.11",
"version": "0.8.12",
"description": "Multi-model AI verification with adversarial critique. No AI can verify itself — so they verify each other.",
"main": "dist/index.js",
"bin": {
Expand Down Expand Up @@ -54,6 +54,7 @@
"prepublishOnly": "npm run build",
"test": "node dist/index.js ask 'Test question' --dry-run",
"test:rv": "npm run build && node --test tests/rv-pipeline.test.mjs",
"test:package": "npm run build && node --test tests/cli-package.test.mjs",
"test:plan": "node --test dist/plan/test-*.js dist/plan/probes/test-*.js",
"check:boundaries": "node scripts/check-product-boundaries.mjs",
"smoke:v1": "bash scripts/smoke-v1.sh"
Expand Down Expand Up @@ -82,7 +83,7 @@
"url": "https://github.com/ThoughtProof/pot-cli/issues"
},
"dependencies": {
"@pot-sdk2/bridge": "^1.2.0",
"@pot-sdk2/bridge": "1.2.0",
"better-sqlite3": "^12.8.0",
"chalk": "^5.3.0",
"commander": "^12.0.0",
Expand Down
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node

import { Command } from 'commander';
import { readFileSync } from 'node:fs';
import { askCommand } from './commands/ask.js';
import { deepCommand } from './commands/deep.js';
import { debugCommand } from './commands/debug.js';
Expand All @@ -23,11 +24,14 @@ import { runAutoGen } from './commands/plan-auto-gen.js';
import { runLOOCV } from './commands/plan-loocv.js';

const program = new Command();
const packageVersion = (JSON.parse(
readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
) as { version: string }).version;

program
.name('pot')
.description('ThoughtProof Proof-of-Thought CLI Tool')
.version('0.5.0');
.version(packageVersion);

program
.command('ask <question>')
Expand Down
57 changes: 57 additions & 0 deletions tests/cli-package.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import assert from 'node:assert/strict';
import { execFile } from 'node:child_process';
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { dirname, join } from 'node:path';
import { after, before, test } from 'node:test';
import { fileURLToPath } from 'node:url';
import { promisify } from 'node:util';

const run = promisify(execFile);
const root = dirname(dirname(fileURLToPath(import.meta.url)));
const version = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).version;
const workspace = mkdtempSync(join(tmpdir(), 'pot-cli-package-'));
const consumer = join(workspace, 'consumer');
const cli = join(consumer, 'node_modules', 'pot-cli', 'dist', 'index.js');

before(async () => {
mkdirSync(consumer);
writeFileSync(join(consumer, 'package.json'), '{"private":true}\n');
// npm ci in this repository keeps the development lockfile. A consumer
// installs only the packed package and resolves its declared dependencies.
const packed = await run('npm', ['pack', '--ignore-scripts', '--json', '--pack-destination', workspace], {
cwd: root,
timeout: 120_000,
maxBuffer: 8 * 1024 * 1024,
});
const [{ filename }] = JSON.parse(packed.stdout);
await run('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false', join(workspace, filename)], {
cwd: consumer,
timeout: 120_000,
maxBuffer: 8 * 1024 * 1024,
});
const provider = (model) => ({ name: model, model, apiKey: 'unused-dry-run', baseUrl: 'http://127.0.0.1:1' });
writeFileSync(join(consumer, '.potrc.json'), JSON.stringify({
generators: [provider('mock-author')],
critic: provider('mock-critic'),
synthesizer: provider('mock-synthesizer'),
blockStoragePath: './blocks',
language: 'en',
}));
});

after(() => rmSync(workspace, { recursive: true, force: true }));

test('freshly installed CLI reports the packed package version', async () => {
const { stdout } = await run(process.execPath, [cli, '--version'], { cwd: consumer });
assert.equal(stdout.trim(), version);
});

test('freshly installed CLI runs ask --dry-run without API credentials', async () => {
const { stdout } = await run(process.execPath, [cli, 'ask', 'Test question', '--dry-run'], {
cwd: consumer,
timeout: 30_000,
});
assert.match(stdout, /\[DRY-RUN\] Simulated synthesis/);
assert.match(stdout, /Saved as PoT-001/);
});
Loading