caliper-harness 0.0.0-stage → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Specific Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,30 @@
1
- # Temporary Holding Version
1
+ # Caliper
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Local models, practical coding tools and project memory.
4
+
5
+ ```sh
6
+ npm install -g caliper-harness
7
+ cd your-project
8
+ caliper
9
+ ```
10
+
11
+ The installer downloads the complete application for macOS Apple Silicon,
12
+ Windows x64, or Linux x64/ARM64. Node 20 or newer is needed for this launcher.
13
+ On Windows, the launcher checks the Microsoft Visual C++ runtime before starting.
14
+ If it is missing or outdated, the shared prerequisite helper downloads Microsoft’s
15
+ installer directly and may request administrator approval or a restart. An already
16
+ compatible installation needs no download. Caliper does not bundle Microsoft’s
17
+ installer or runtime DLLs.
18
+
19
+ Model weights and tools belonging to your project remain yours to install.
20
+
21
+ Caliper offers available updates at startup. Use `/update` to download an update
22
+ for your next launch, or `npm install -g caliper-harness@latest`.
23
+
24
+ Your settings, graph and sessions live in your operating system's user-data
25
+ folder, separate from application versions. Updates preserve previous versions
26
+ and never delete your project work or model files.
27
+
28
+ For a project-local installation, `npm install caliper-harness` followed by
29
+ `npx caliper` works too; npm creates `node_modules` in that project. Use the global
30
+ command above to keep project directories free of installation files.
package/bin.cjs ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { spawn } = require('node:child_process');
6
+ const app = require('./install.cjs');
7
+ (async () => {
8
+ const base = app.home();
9
+ let selected;
10
+ try { selected = JSON.parse(fs.readFileSync(path.join(base, 'current.json'), 'utf8')); }
11
+ catch (error) { if (error.code !== 'ENOENT') throw error; await app.install(); selected = JSON.parse(fs.readFileSync(path.join(base, 'current.json'), 'utf8')); }
12
+ if (!/^\d+\.\d+\.\d+$/.test(selected.version) || selected.platform !== app.identity || selected.root !== path.join(base, 'versions', selected.version, app.identity, 'Caliper')) throw new Error('Invalid installed version selection');
13
+ app.validate(selected.root, true);
14
+ await app.ensurePrerequisites(selected.root);
15
+ const env = { ...process.env, PATH: path.join(selected.root, 'bin') + path.delimiter + (process.env.PATH || '') };
16
+ if (process.platform === 'linux') env.LD_LIBRARY_PATH = path.join(selected.root, 'lib') + (process.env.LD_LIBRARY_PATH ? path.delimiter + process.env.LD_LIBRARY_PATH : '');
17
+ const child = spawn(app.executable(selected.root), process.argv.slice(2), { env, stdio: 'inherit', windowsHide: false });
18
+ for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, () => { if (signal === 'SIGTERM') child.kill(signal); });
19
+ child.on('error', error => { console.error(`Cannot start Caliper: ${error.message}`); process.exitCode = 1; });
20
+ child.on('exit', (code, signal) => { process.exitCode = code ?? (signal === 'SIGINT' ? 130 : 1); });
21
+ })().catch(error => { console.error(`Caliper: ${error.message}`); process.exitCode = 1; });
package/install.cjs ADDED
@@ -0,0 +1,122 @@
1
+ 'use strict';
2
+ const fs = require('node:fs');
3
+ const path = require('node:path');
4
+ const os = require('node:os');
5
+ const crypto = require('node:crypto');
6
+ const { pipeline, finished } = require('node:stream/promises');
7
+ const { Transform, Readable } = require('node:stream');
8
+ const tar = require('tar');
9
+ const { spawn } = require('node:child_process');
10
+ const version = require('./package.json').version;
11
+ const identity = `${process.platform === 'win32' ? 'windows' : process.platform}-${process.arch === 'x64' ? 'amd64' : process.arch}`;
12
+ const supported = ['darwin-arm64', 'windows-amd64', 'linux-amd64', 'linux-arm64'];
13
+ function home() {
14
+ if (process.platform === 'darwin') return path.join(os.homedir(), 'Library', 'Application Support', 'caliper');
15
+ if (process.platform === 'win32') return path.join(process.env.LOCALAPPDATA || process.env.APPDATA, 'caliper');
16
+ return path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share'), 'caliper');
17
+ }
18
+ function executable(root) { return path.join(root, process.platform === 'win32' ? 'caliper.exe' : 'caliper-harness'); }
19
+ function validate(root, allowLegacy = false) {
20
+ if (fs.existsSync(path.join(root, 'BUILD-INCOMPLETE'))) throw new Error('Incomplete application bundle');
21
+ const required = ['prompts.yaml', 'MANIFEST.sha256', 'runtime/decision/requirements.lock'];
22
+ if (identity.startsWith('windows-')) { required.push('kuzu_shared.dll', 'bin/rg.exe', 'runtime/decision/python.exe'); if (!allowLegacy || !legacyWindowsRuntime(root)) required.push('ensure-windows-runtime.ps1'); }
23
+ else { required.push('bin/rg', 'runtime/decision/bin/python3', identity.startsWith('darwin-') ? 'lib/libkuzu.dylib' : 'lib/libkuzu.so'); if (identity.startsWith('darwin-')) required.push('runtime/worker/bin/python3'); }
24
+ for (const name of [executable(root), ...required.map(file => path.join(root, file))]) if (!fs.statSync(name).isFile()) throw new Error(`Missing product file: ${name}`);
25
+ if (process.platform !== 'win32') { for (const file of [executable(root), ...required.filter(name => name === 'bin/rg' || name.endsWith('/bin/python3')).map(name => path.join(root,name))]) fs.accessSync(file, fs.constants.X_OK); }
26
+ const manifest = JSON.parse(fs.readFileSync(path.join(root, 'runtime', 'manifest.json'), 'utf8'));
27
+ if (manifest.format !== 1 || manifest.platform !== identity) throw new Error('Application runtime platform mismatch');
28
+ }
29
+ async function verify(root) {
30
+ validate(root);
31
+ const lines = fs.readFileSync(path.join(root, 'MANIFEST.sha256'), 'utf8').trim().split(/\r?\n/);
32
+ for (const line of lines) {
33
+ const match = /^([a-f0-9]{64}) \.\/(.+)$/i.exec(line);
34
+ if (!match || /[\\:\0]/.test(match[2])) throw new Error('Invalid application inventory');
35
+ const file = fs.realpathSync(path.resolve(root, match[2]));
36
+ const rel = path.relative(fs.realpathSync(root), file);
37
+ if (rel === '..' || rel.startsWith('..' + path.sep) || path.isAbsolute(rel)) throw new Error('Application inventory escapes install');
38
+ const hash = crypto.createHash('sha256');
39
+ for await (const chunk of fs.createReadStream(file)) hash.update(chunk);
40
+ if (hash.digest('hex').toLowerCase() !== match[1].toLowerCase()) throw new Error(`Application inventory mismatch: ${match[2]}`);
41
+ }
42
+ }
43
+ async function get(url) { const r = await fetch(url); if (!r.ok) { const error = new Error(`${url}: HTTP ${r.status}`); error.status = r.status; throw error; } return r; }
44
+ function legacyWindowsRuntime(root) {
45
+ try {
46
+ const inventory = '\n' + fs.readFileSync(path.join(root, 'MANIFEST.sha256'), 'utf8').replace(/\r\n/g, '\n').replace(/\n$/, '') + '\n';
47
+ return ['msvcp140.dll', 'vcruntime140.dll', 'vcruntime140_1.dll', 'runtime/decision/msvcp140.dll'].every(name => {
48
+ const file = fs.realpathSync(path.join(root, name)), rel = path.relative(fs.realpathSync(root), file);
49
+ if (rel === '..' || rel.startsWith('..' + path.sep) || path.isAbsolute(rel)) return false;
50
+ const hash = crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
51
+ return inventory.includes(`\n${hash} ./${name}\n`);
52
+ });
53
+ } catch { return false; }
54
+ }
55
+ async function ensurePrerequisites(root) {
56
+ if (process.platform !== 'win32') return;
57
+ const helper = path.join(root, 'ensure-windows-runtime.ps1');
58
+ if (!fs.existsSync(helper) && legacyWindowsRuntime(root)) return;
59
+ if (!process.env.SystemRoot) throw new Error('SystemRoot unavailable; cannot check Windows runtime');
60
+ await new Promise((resolve, reject) => {
61
+ const child = spawn(path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'), ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', helper], {stdio: 'inherit', windowsHide: false});
62
+ child.on('error', reject);
63
+ child.on('exit', code => code === 0 ? resolve() : reject(new Error(`Windows runtime prerequisite failed (${code}); previous selection preserved. Finish any requested restart before retrying.`)));
64
+ });
65
+ }
66
+ async function activateNative(root) {
67
+ await ensurePrerequisites(root);
68
+ const env = { ...process.env, PATH: path.join(root,'bin') + path.delimiter + (process.env.PATH || '') };
69
+ if (process.platform === 'linux') env.LD_LIBRARY_PATH = path.join(root,'lib') + (process.env.LD_LIBRARY_PATH ? path.delimiter + process.env.LD_LIBRARY_PATH : '');
70
+ await new Promise((resolve,reject) => {
71
+ const child=spawn(executable(root),['install-activate'],{env,stdio:'inherit'});
72
+ child.on('error',reject);child.on('exit',code=>code===0?resolve():reject(new Error(`Native installation activation failed (${code}); previous selection preserved`)));
73
+ });
74
+ }
75
+ async function install(base = home(), download = get, activate = activateNative) {
76
+ if (!supported.includes(identity)) throw new Error(`No Caliper product bundle for ${identity}. Supported: ${supported.join(', ')}`);
77
+ const parent = path.join(base, 'versions', version, identity);
78
+ const root = path.join(parent, 'Caliper');
79
+ if (fs.existsSync(parent)) { await verify(root); await activate(root, version, base); return root; }
80
+ fs.mkdirSync(path.join(base, 'versions'), { recursive: true });
81
+ const stage = fs.mkdtempSync(path.join(base, 'versions', '.npm-install-'));
82
+ try {
83
+ const name = `caliper-${version}-${identity}.tar.gz`;
84
+ const url = `https://github.com/santiagoaraoz2001-sketch/caliper-harness/releases/download/v${version}/${name}`;
85
+ const checksum = (await (await download(`${url}.sha256`)).text()).trim().split(/\s+/)[0];
86
+ if (!/^[a-f0-9]{64}$/i.test(checksum)) throw new Error('Invalid release checksum');
87
+ const archive = path.join(stage, 'bundle.tar.gz');
88
+ const hash = crypto.createHash('sha256');
89
+ const tee = new Transform({ transform(chunk, _, cb) { hash.update(chunk); cb(null, chunk); } });
90
+ const output = fs.createWriteStream(archive, { flags: 'wx' });
91
+ try {
92
+ let response;
93
+ try { response = await download(url); }
94
+ catch (error) { if (error.status !== 404) throw error; }
95
+ if (response) await pipeline(Readable.fromWeb(response.body), tee, output);
96
+ else {
97
+ const parts = await (await download(`${url}.parts.json`)).json();
98
+ if (parts.format !== 1 || parts.archive !== name || parts.sha256.toLowerCase() !== checksum.toLowerCase() || !Array.isArray(parts.parts) || !parts.parts.length) throw new Error('Invalid split-archive manifest');
99
+ const seen = new Set();
100
+ for (const part of parts.parts) {
101
+ if (typeof part.name !== 'string' || path.basename(part.name) !== part.name || /[\\:]/.test(part.name) || !part.name.startsWith(name + '.part-') || seen.has(part.name) || !Number.isSafeInteger(part.bytes) || part.bytes <= 0 || !/^[a-f0-9]{64}$/i.test(part.sha256)) throw new Error('Invalid archive part');
102
+ seen.add(part.name); const partHash = crypto.createHash('sha256'); let bytes = 0;
103
+ const source = await download(new URL(part.name, url).href);
104
+ const stream = new Transform({ transform(chunk, _, cb) { bytes += chunk.length; partHash.update(chunk); hash.update(chunk); cb(null, chunk); } });
105
+ await pipeline(Readable.fromWeb(source.body), stream, output, { end: false });
106
+ if (bytes !== part.bytes || partHash.digest('hex').toLowerCase() !== part.sha256.toLowerCase()) throw new Error(`Archive part failed verification: ${part.name}`);
107
+ }
108
+ output.end(); await finished(output);
109
+ }
110
+ } catch (error) { await new Promise(resolve => { if (output.closed) return resolve(); output.once("close", resolve); output.destroy(); }); throw error; }
111
+ if (hash.digest('hex').toLowerCase() !== checksum.toLowerCase()) throw new Error('Release checksum mismatch; previous installation unchanged');
112
+ const unpack = path.join(stage, 'unpacked'); fs.mkdirSync(unpack);
113
+ await tar.x({ file: archive, cwd: unpack, strict: true, preservePaths: false });
114
+ await verify(path.join(unpack, 'Caliper'));
115
+ fs.mkdirSync(path.dirname(parent), { recursive: true });
116
+ fs.renameSync(unpack, parent);
117
+ await activate(root, version, base);
118
+ return root;
119
+ } finally { fs.rmSync(stage, { recursive: true, force: true }); }
120
+ }
121
+ if (require.main === module) install().then(root => console.log(`Caliper ${version} installed: ${root}\nRun caliper from your project directory.`)).catch(error => { console.error(`Caliper installation failed: ${error.message}`); process.exitCode = 1; });
122
+ module.exports = { home, executable, validate, install, identity, version, ensurePrerequisites, activateNative };
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
2
  "name": "caliper-harness",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.2",
4
+ "description": "A local coding harness with tools, planning and durable project memory",
5
+ "license": "MIT",
6
+ "repository": "github:santiagoaraoz2001-sketch/caliper-harness",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "bin": {
11
+ "caliper": "bin.cjs"
12
+ },
13
+ "files": [
14
+ "bin.cjs",
15
+ "install.cjs",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "scripts": {
20
+ "postinstall": "node install.cjs",
21
+ "test": "node --test test.cjs"
22
+ },
23
+ "dependencies": {
24
+ "tar": "7.5.22"
25
+ }
26
+ }