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 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. Describe a check** — create a file called `stilltrue.config.mjs` in
40
- the same folder. Each check answers three questions: *where do I fetch the
41
- truth from* (`source`), *what do I believe* (`expect`), and *how do I
42
- compare the two* (`compare`):
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 drift [--config <path>] [--only <names>] [--json <path>] [--record] [--history <path>]\n' +
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
@@ -0,0 +1,6 @@
1
+ export interface InitResult {
2
+ created: string[];
3
+ skipped: string[];
4
+ }
5
+ /** Write starter config + example data file. Never overwrites. */
6
+ export declare function init(dir: string): Promise<InitResult>;
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.4.1",
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",