@golden-frijoles/cli 0.5.0 → 0.6.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 +13 -0
- package/dist/commands/index.js +3 -0
- package/dist/commands/result-reads.d.ts +36 -0
- package/dist/commands/result-reads.js +123 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,19 @@ already exists **moves** to this metric. The dry run says so before anything is
|
|
|
95
95
|
reuse its key. The server validates the block and prints its `issues` on a 400. A file that still has the template's
|
|
96
96
|
`<…>` placeholders is refused before anything is sent.
|
|
97
97
|
|
|
98
|
+
## Reading a result: `gf north-star readings`, `gf experiments decision`
|
|
99
|
+
|
|
100
|
+
An agent reading an epic's result (the plugin's `epic-read`) fetches the number itself through these two reads. Any
|
|
101
|
+
project member can run them; `--json` prints the body the agent parses.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
gf north-star readings grounded_bets_share --to 2026-11-04 --json # the input's readings; `latest` is the number
|
|
105
|
+
gf experiments decision smart-defaults --json # the experiment's decision record
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`latest` is the last reading on or before `--to`; an input with no reading yet says so rather than reporting zero.
|
|
109
|
+
Cite them as `north-star:<input>@<latest.date>` and `ab:<experiment>`.
|
|
110
|
+
|
|
98
111
|
## Exit codes
|
|
99
112
|
|
|
100
113
|
| Code | Name | Means |
|
package/dist/commands/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const flags_write_1 = require("./flags-write");
|
|
|
14
14
|
const flags_history_1 = require("./flags-history");
|
|
15
15
|
const flags_sync_1 = require("./flags-sync");
|
|
16
16
|
const north_star_1 = require("./north-star");
|
|
17
|
+
const result_reads_1 = require("./result-reads");
|
|
17
18
|
const keys_1 = require("./keys");
|
|
18
19
|
const doctor_1 = require("./doctor");
|
|
19
20
|
const config_1 = require("./config");
|
|
@@ -41,6 +42,8 @@ exports.COMMANDS = [
|
|
|
41
42
|
flags_history_1.flagsHistoryCommand,
|
|
42
43
|
flags_sync_1.flagsSyncCommand,
|
|
43
44
|
north_star_1.northStarSetCommand,
|
|
45
|
+
result_reads_1.northStarReadingsCommand,
|
|
46
|
+
result_reads_1.experimentsDecisionCommand,
|
|
44
47
|
keys_1.keysLsCommand,
|
|
45
48
|
keys_1.keysCreateCommand,
|
|
46
49
|
keys_1.keysRevokeCommand,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Command } from '../command';
|
|
2
|
+
export type InputReadingsBody = {
|
|
3
|
+
project: string;
|
|
4
|
+
metric: string | null;
|
|
5
|
+
input: {
|
|
6
|
+
key: string;
|
|
7
|
+
name: string;
|
|
8
|
+
valueSource: string;
|
|
9
|
+
};
|
|
10
|
+
readings: Array<{
|
|
11
|
+
date: string;
|
|
12
|
+
value: number;
|
|
13
|
+
}>;
|
|
14
|
+
latest: {
|
|
15
|
+
date: string;
|
|
16
|
+
value: number;
|
|
17
|
+
} | null;
|
|
18
|
+
};
|
|
19
|
+
export type ExperimentDecisionBody = {
|
|
20
|
+
project: string;
|
|
21
|
+
key: string;
|
|
22
|
+
version: number;
|
|
23
|
+
lifecycle: string;
|
|
24
|
+
decisions: {
|
|
25
|
+
state: 'undecided' | 'decided';
|
|
26
|
+
current: {
|
|
27
|
+
outcome?: string;
|
|
28
|
+
chosenVariantKey?: string | null;
|
|
29
|
+
rationale?: string;
|
|
30
|
+
createdAt?: string;
|
|
31
|
+
} | null;
|
|
32
|
+
history: unknown[];
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export declare const northStarReadingsCommand: Command;
|
|
36
|
+
export declare const experimentsDecisionCommand: Command;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// result-record · Story 3.2 (D16) — the two reads an agent fetches an epic's result through.
|
|
3
|
+
//
|
|
4
|
+
// gf north-star readings <input> [--to <day>] an input's readings, and the latest on or before --to
|
|
5
|
+
// gf experiments decision <key> [--version <n>] an experiment's decision record (latest version by default)
|
|
6
|
+
//
|
|
7
|
+
// Both are `--json`-first: `epic-read` spawns them and reads the body, so the JSON is the contract and the table is for
|
|
8
|
+
// a person. Both go through `/api/v1/cli/*`, which checks membership exactly as the console does (404 elsewhere).
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.experimentsDecisionCommand = exports.northStarReadingsCommand = void 0;
|
|
11
|
+
const args_1 = require("../args");
|
|
12
|
+
const exit_codes_1 = require("../exit-codes");
|
|
13
|
+
const output_1 = require("../output");
|
|
14
|
+
const flags_read_1 = require("./flags-read");
|
|
15
|
+
const DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
16
|
+
exports.northStarReadingsCommand = {
|
|
17
|
+
path: ['north-star', 'readings'],
|
|
18
|
+
summary: "one North Star input's readings, and the latest on or before a day",
|
|
19
|
+
usage: 'gf north-star readings <input> [--to <YYYY-MM-DD>] [--project <slug>] [--json]',
|
|
20
|
+
needsAuth: true,
|
|
21
|
+
detail: `An agent reading an epic's result calls this: \`latest\` is the number it reports, and
|
|
22
|
+
\`north-star:<input>@<latest.date>\` is the evidence it writes. Nothing is invented: an input
|
|
23
|
+
with no reading on or before --to says so, rather than reporting zero.`,
|
|
24
|
+
flags: [
|
|
25
|
+
{ name: 'to', value: '<YYYY-MM-DD>', describe: 'cut the readings at this day (default: all of them)' },
|
|
26
|
+
{ name: 'project', value: '<slug>', describe: 'the project (default: the remembered one)' },
|
|
27
|
+
],
|
|
28
|
+
async run(context) {
|
|
29
|
+
const input = context.args.positionals[0];
|
|
30
|
+
if (!input) {
|
|
31
|
+
context.emit.fail('invalid', 'Name the input: `gf north-star readings <input-key>`.');
|
|
32
|
+
return exit_codes_1.EXIT.USAGE;
|
|
33
|
+
}
|
|
34
|
+
const to = (0, args_1.flagValue)(context.args, 'to');
|
|
35
|
+
if (to !== undefined && !DAY.test(to)) {
|
|
36
|
+
context.emit.fail('invalid', '--to must be a day written YYYY-MM-DD.');
|
|
37
|
+
return exit_codes_1.EXIT.USAGE;
|
|
38
|
+
}
|
|
39
|
+
const project = (0, flags_read_1.resolveProject)(context);
|
|
40
|
+
if (!project)
|
|
41
|
+
return (0, flags_read_1.missingProject)(context);
|
|
42
|
+
const result = await context.api.get('api/v1/cli/north-star/readings', {
|
|
43
|
+
project,
|
|
44
|
+
input,
|
|
45
|
+
...(to ? { to } : {}),
|
|
46
|
+
});
|
|
47
|
+
if (result.kind === 'network') {
|
|
48
|
+
context.emit.fail('server_error', result.message);
|
|
49
|
+
return exit_codes_1.EXIT.SERVER;
|
|
50
|
+
}
|
|
51
|
+
if (result.kind === 'error') {
|
|
52
|
+
context.emit.fail(result.code, result.message);
|
|
53
|
+
return (0, exit_codes_1.exitForServerCode)(result.code);
|
|
54
|
+
}
|
|
55
|
+
const body = result.body;
|
|
56
|
+
const human = body.readings.length === 0
|
|
57
|
+
? `${body.input.key}: no readings${to ? ` on or before ${to}` : ''} yet.`
|
|
58
|
+
: [
|
|
59
|
+
`${body.input.key} (${body.input.name}) — latest ${body.latest.value} on ${body.latest.date}`,
|
|
60
|
+
(0, output_1.table)(['DAY', 'VALUE'], body.readings.slice(-10).map((r) => [r.date, String(r.value)])),
|
|
61
|
+
].join('\n');
|
|
62
|
+
context.emit.ok({
|
|
63
|
+
project: body.project,
|
|
64
|
+
metric: body.metric,
|
|
65
|
+
input: body.input,
|
|
66
|
+
readings: body.readings,
|
|
67
|
+
latest: body.latest,
|
|
68
|
+
}, human);
|
|
69
|
+
return exit_codes_1.EXIT.OK;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
exports.experimentsDecisionCommand = {
|
|
73
|
+
path: ['experiments', 'decision'],
|
|
74
|
+
summary: "an experiment's decision record (the latest version unless --version)",
|
|
75
|
+
usage: 'gf experiments decision <key> [--version <n>] [--project <slug>] [--json]',
|
|
76
|
+
needsAuth: true,
|
|
77
|
+
detail: `What was decided about an A/B test, from the experiment's append-only decision ledger.
|
|
78
|
+
An agent reading an epic's result cites it as \`ab:<key>\`.`,
|
|
79
|
+
flags: [
|
|
80
|
+
{ name: 'version', value: '<n>', describe: 'the definition version (default: the latest)' },
|
|
81
|
+
{ name: 'project', value: '<slug>', describe: 'the project (default: the remembered one)' },
|
|
82
|
+
],
|
|
83
|
+
async run(context) {
|
|
84
|
+
const key = context.args.positionals[0];
|
|
85
|
+
if (!key) {
|
|
86
|
+
context.emit.fail('invalid', 'Name the experiment: `gf experiments decision <key>`.');
|
|
87
|
+
return exit_codes_1.EXIT.USAGE;
|
|
88
|
+
}
|
|
89
|
+
const version = (0, args_1.flagValue)(context.args, 'version');
|
|
90
|
+
if (version !== undefined && !/^[1-9]\d{0,6}$/.test(version)) {
|
|
91
|
+
context.emit.fail('invalid', '--version must be a whole number from 1.');
|
|
92
|
+
return exit_codes_1.EXIT.USAGE;
|
|
93
|
+
}
|
|
94
|
+
const project = (0, flags_read_1.resolveProject)(context);
|
|
95
|
+
if (!project)
|
|
96
|
+
return (0, flags_read_1.missingProject)(context);
|
|
97
|
+
const result = await context.api.get('api/v1/cli/experiments/decision', {
|
|
98
|
+
project,
|
|
99
|
+
experiment: key,
|
|
100
|
+
...(version ? { version } : {}),
|
|
101
|
+
});
|
|
102
|
+
if (result.kind === 'network') {
|
|
103
|
+
context.emit.fail('server_error', result.message);
|
|
104
|
+
return exit_codes_1.EXIT.SERVER;
|
|
105
|
+
}
|
|
106
|
+
if (result.kind === 'error') {
|
|
107
|
+
context.emit.fail(result.code, result.message);
|
|
108
|
+
return (0, exit_codes_1.exitForServerCode)(result.code);
|
|
109
|
+
}
|
|
110
|
+
const body = result.body;
|
|
111
|
+
const current = body.decisions.current;
|
|
112
|
+
context.emit.ok({
|
|
113
|
+
project: body.project,
|
|
114
|
+
key: body.key,
|
|
115
|
+
version: body.version,
|
|
116
|
+
lifecycle: body.lifecycle,
|
|
117
|
+
decisions: body.decisions,
|
|
118
|
+
}, current
|
|
119
|
+
? `${body.key} v${body.version} (${body.lifecycle}) — decided: ${current.outcome ?? 'recorded'}${current.chosenVariantKey ? ` (${current.chosenVariantKey})` : ''}${current.rationale ? `\n ${current.rationale}` : ''}`
|
|
120
|
+
: `${body.key} v${body.version} (${body.lifecycle}) — no decision recorded yet.`);
|
|
121
|
+
return exit_codes_1.EXIT.OK;
|
|
122
|
+
},
|
|
123
|
+
};
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.6.0";
|
package/dist/version.js
CHANGED
|
@@ -10,4 +10,4 @@ exports.VERSION = void 0;
|
|
|
10
10
|
//
|
|
11
11
|
// It is a literal, and `version.test.ts` asserts it equals `package.json`'s — so the two cannot
|
|
12
12
|
// drift, and the drift is caught by the unit gate rather than by someone reading `gf --version`.
|
|
13
|
-
exports.VERSION = '0.
|
|
13
|
+
exports.VERSION = '0.6.0';
|
package/package.json
CHANGED