stilltrue 0.4.1 → 0.5.0
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/README.md +14 -4
- package/dist/cli.js +19 -1
- package/dist/init.d.ts +6 -0
- package/dist/init.js +78 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,10 +36,16 @@ project folder with your facts saved in a JSON file.
|
|
|
36
36
|
npm install --save-dev stilltrue
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
**2.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
**2. Scaffold a check** — this creates a ready-to-edit config file and an
|
|
40
|
+
example facts file (it never overwrites anything you already have):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx stilltrue init
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Open the generated `stilltrue.config.mjs`. Each check answers three
|
|
47
|
+
questions: *where do I fetch the truth from* (`source`), *what do I
|
|
48
|
+
believe* (`expect`), and *how do I compare the two* (`compare`):
|
|
43
49
|
|
|
44
50
|
```js
|
|
45
51
|
import { defineStilltrue, corpus, json, surname } from 'stilltrue';
|
|
@@ -64,6 +70,10 @@ export default defineStilltrue({
|
|
|
64
70
|
This example says: *fetch the board page, and make sure every last name in
|
|
65
71
|
my `school-board.json` file still appears somewhere on it.*
|
|
66
72
|
|
|
73
|
+
Choosing what to assert is the judgment call — surnames beat full names,
|
|
74
|
+
"143 schools" beats a bare "143". The short guide:
|
|
75
|
+
[docs/MARKERS.md](docs/MARKERS.md).
|
|
76
|
+
|
|
67
77
|
**3. Run it:**
|
|
68
78
|
|
|
69
79
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -94,13 +94,31 @@ try {
|
|
|
94
94
|
case 'report':
|
|
95
95
|
process.exit(await report(rest));
|
|
96
96
|
break;
|
|
97
|
+
case 'init': {
|
|
98
|
+
const { init } = await import("./init.js");
|
|
99
|
+
const { created, skipped } = await init(process.cwd());
|
|
100
|
+
for (const f of created)
|
|
101
|
+
console.log(`created ${f}`);
|
|
102
|
+
for (const f of skipped)
|
|
103
|
+
console.log(`kept existing ${f} (never overwritten)`);
|
|
104
|
+
if (created.length) {
|
|
105
|
+
console.log('\nNext steps:\n' +
|
|
106
|
+
' 1. Edit stilltrue.config.mjs — point source at the real page(s) your facts came from\n' +
|
|
107
|
+
' 2. Edit data/example-facts.json — or point the config at a facts file you already have\n' +
|
|
108
|
+
' 3. Run: npx stilltrue drift\n' +
|
|
109
|
+
'Picking good markers: docs/MARKERS.md in the stilltrue repo');
|
|
110
|
+
}
|
|
111
|
+
process.exit(0);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
97
114
|
case 'golden':
|
|
98
115
|
console.error('stilltrue deliberately has no golden runner — promptfoo tests your prompts; stilltrue tests your facts.\n' +
|
|
99
116
|
'Use https://promptfoo.dev for prompt/answer regression evals. Doctrine + pairing guide: docs/GOLDEN.md');
|
|
100
117
|
process.exit(1);
|
|
101
118
|
break;
|
|
102
119
|
default:
|
|
103
|
-
console.log('usage: stilltrue
|
|
120
|
+
console.log('usage: stilltrue init\n' +
|
|
121
|
+
' stilltrue drift [--config <path>] [--only <names>] [--json <path>] [--record] [--history <path>]\n' +
|
|
104
122
|
' stilltrue report [--history <path>] [--out <path>] [--title <text>]');
|
|
105
123
|
process.exit(command ? 1 : 0);
|
|
106
124
|
}
|
package/dist/init.d.ts
ADDED
package/dist/init.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const CONFIG_TEMPLATE = `// stilltrue configuration — one entry per fact-set you want watched.
|
|
5
|
+
// Docs: https://github.com/sg-bfoster/stilltrue#readme
|
|
6
|
+
// Picking good markers: https://github.com/sg-bfoster/stilltrue/blob/main/docs/MARKERS.md
|
|
7
|
+
import { defineStilltrue, corpus, json, surname } from 'stilltrue';
|
|
8
|
+
|
|
9
|
+
export default defineStilltrue({
|
|
10
|
+
drift: [
|
|
11
|
+
{
|
|
12
|
+
// A short id for this check — shows up in output and reports.
|
|
13
|
+
name: 'example-board-roster',
|
|
14
|
+
|
|
15
|
+
// WHERE THE TRUTH LIVES: the official page(s) your facts came from.
|
|
16
|
+
// corpus() fetches each page and strips it down to readable text.
|
|
17
|
+
// If one page is unreachable it warns; only if ALL are down does the
|
|
18
|
+
// check report an error (which never fails your build).
|
|
19
|
+
source: corpus([
|
|
20
|
+
'https://example.org/board',
|
|
21
|
+
// 'https://example.org/about', // add more pages if facts span several
|
|
22
|
+
]),
|
|
23
|
+
|
|
24
|
+
// WHAT YOU BELIEVE: read your saved facts file and pick out the
|
|
25
|
+
// "markers" — short, stable strings that must still appear on the
|
|
26
|
+
// page(s) above. Here: each member's last name, plus one number.
|
|
27
|
+
expect: json('./data/example-facts.json', (data) => [
|
|
28
|
+
...data.members.map((m) => surname(m.name)),
|
|
29
|
+
\`\${data.totalSchools} schools\`,
|
|
30
|
+
]),
|
|
31
|
+
|
|
32
|
+
// HOW TO COMPARE: 'contains-all' = every marker must appear in the
|
|
33
|
+
// fetched text (case-insensitive). Any missing marker = rot = the
|
|
34
|
+
// build fails and tells you which fact went stale.
|
|
35
|
+
compare: 'contains-all',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
`;
|
|
40
|
+
const DATA_TEMPLATE = `{
|
|
41
|
+
"_comment": "Example facts file - replace with your own data, or point the config at a file you already have.",
|
|
42
|
+
"members": [
|
|
43
|
+
{ "name": "Dr. Jane Smith" },
|
|
44
|
+
{ "name": "Robert Jones Jr." }
|
|
45
|
+
],
|
|
46
|
+
"totalSchools": 12
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
/** Write starter config + example data file. Never overwrites. */
|
|
50
|
+
export async function init(dir) {
|
|
51
|
+
const created = [];
|
|
52
|
+
const skipped = [];
|
|
53
|
+
const configPath = join(dir, 'stilltrue.config.mjs');
|
|
54
|
+
const existingConfig = [
|
|
55
|
+
'stilltrue.config.mjs',
|
|
56
|
+
'stilltrue.config.ts',
|
|
57
|
+
'stilltrue.config.mts',
|
|
58
|
+
'stilltrue.config.js',
|
|
59
|
+
'stilltrue.config.cjs',
|
|
60
|
+
].find((name) => existsSync(join(dir, name)));
|
|
61
|
+
if (existingConfig) {
|
|
62
|
+
skipped.push(existingConfig);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
await writeFile(configPath, CONFIG_TEMPLATE);
|
|
66
|
+
created.push('stilltrue.config.mjs');
|
|
67
|
+
}
|
|
68
|
+
const dataPath = join(dir, 'data', 'example-facts.json');
|
|
69
|
+
if (existsSync(dataPath)) {
|
|
70
|
+
skipped.push('data/example-facts.json');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
await mkdir(join(dir, 'data'), { recursive: true });
|
|
74
|
+
await writeFile(dataPath, DATA_TEMPLATE);
|
|
75
|
+
created.push('data/example-facts.json');
|
|
76
|
+
}
|
|
77
|
+
return { created, skipped };
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stilltrue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Your tests check your code. stilltrue checks your facts. CI checks for AI-in-the-loop apps: drift (curated facts vs live sources), golden (regression evals), verify (judge answers against sources).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"drift",
|