faf-cli 6.9.0 → 6.10.1
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 +15 -1
- package/dist/cli.js +168 -168
- package/dist/cli.js.map +5 -5
- package/dist/commands/bench.d.ts +104 -0
- package/dist/core/interview.d.ts +8 -0
- package/dist/detect/turbo-cat-knowledge.d.ts +104 -0
- package/dist/detect/turbo-cat.d.ts +38 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +143 -143
- package/dist/index.js.map +7 -4
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* faf bench — the AI-grounding benchmark (P1, agent-native).
|
|
3
|
+
*
|
|
4
|
+
* Measures the thing FAF sells, falsifiably: AI works better and faster WITH
|
|
5
|
+
* structured context. Two numbers, one harness — grounding ACCURACY (N
|
|
6
|
+
* project questions, cold vs with-faf) and grounding COST (tokens to get
|
|
7
|
+
* grounded, as reported by the runner).
|
|
8
|
+
*
|
|
9
|
+
* The unfair advantage: the .faf IS the answer key. Questions derive from the
|
|
10
|
+
* populated active slots; grading is mechanical (normalize + versioned alias
|
|
11
|
+
* map + significant-token containment — no judge, no rubric drift). The
|
|
12
|
+
* question-set hash rides a ✪ receipt, parity-hash discipline.
|
|
13
|
+
*
|
|
14
|
+
* DOCTRINE (wolfejam 2026-06-11):
|
|
15
|
+
* - "A low score is an ALARM BELL — you are hemorrhaging tokens and the AI
|
|
16
|
+
* is pretty much clueless about what you are doing, even trying to do."
|
|
17
|
+
* Headline: "Trouble ahead, expensive trouble."
|
|
18
|
+
* - NEVER render a low score alone — always the pair (cold → with-faf), or
|
|
19
|
+
* the alarm framing with headroom. The delta is the product; the cold
|
|
20
|
+
* number belongs to the ABSENCE of context ("without context"), never to
|
|
21
|
+
* FAF. Output always ends in a prescription, never a verdict.
|
|
22
|
+
* - The 6Ws are UNDERIVABLE from code: cold exploration can dig out a stack
|
|
23
|
+
* (you pay for the dig); it can never find intent.
|
|
24
|
+
*/
|
|
25
|
+
/** Bump when phrasing, aliases, or grading rules change — part of the qset hash. */
|
|
26
|
+
export declare const BENCH_VERSION = "faf-bench/1";
|
|
27
|
+
export interface BenchQuestion {
|
|
28
|
+
n: number;
|
|
29
|
+
path: string;
|
|
30
|
+
question: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Versioned alias groups — mechanical equivalences, no fuzzy scoring.
|
|
34
|
+
* Members are compared post-normalization. Extend deliberately; every change
|
|
35
|
+
* bumps the qset hash via BENCH_VERSION.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ALIAS_GROUPS: string[][];
|
|
38
|
+
export declare function normalizeAnswer(s: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Mechanical match: exact normalized equality, alias-group equality, or
|
|
41
|
+
* every significant token of the EXPECTED value present in the answer
|
|
42
|
+
* (deterministic set containment — handles sentence-shaped 6W answers
|
|
43
|
+
* without a judge). A miss is a miss.
|
|
44
|
+
*/
|
|
45
|
+
export declare function answersMatch(expected: string, given: string): boolean;
|
|
46
|
+
export interface QuestionSet {
|
|
47
|
+
version: string;
|
|
48
|
+
qsetHash: string;
|
|
49
|
+
questions: BenchQuestion[];
|
|
50
|
+
/** Internal answer key — NEVER printed by `questions`; used by `grade`. */
|
|
51
|
+
answers: Record<number, string>;
|
|
52
|
+
}
|
|
53
|
+
/** Derive the question set + answer key from a project.faf (active populated slots only). */
|
|
54
|
+
export declare function deriveQuestionSet(yaml: string): QuestionSet;
|
|
55
|
+
/**
|
|
56
|
+
* The answer-key-safe projection of a QuestionSet — version + qsetHash +
|
|
57
|
+
* questions, NEVER `answers`. Any "give me the questions" surface (MCP tools,
|
|
58
|
+
* UIs) MUST hand out THIS, not the raw QuestionSet: a tool that prints the
|
|
59
|
+
* answer key makes the benchmark a lie. The CLI's `bench questions` follows
|
|
60
|
+
* the same rule.
|
|
61
|
+
*/
|
|
62
|
+
export declare function publicQuestions(qset: QuestionSet): {
|
|
63
|
+
version: string;
|
|
64
|
+
qsetHash: string;
|
|
65
|
+
questions: BenchQuestion[];
|
|
66
|
+
};
|
|
67
|
+
export interface GradeResult {
|
|
68
|
+
correct: number;
|
|
69
|
+
total: number;
|
|
70
|
+
misses: BenchQuestion[];
|
|
71
|
+
perQuestion: {
|
|
72
|
+
n: number;
|
|
73
|
+
path: string;
|
|
74
|
+
ok: boolean;
|
|
75
|
+
}[];
|
|
76
|
+
}
|
|
77
|
+
export declare function gradeAnswers(qset: QuestionSet, given: Record<string, string>): GradeResult;
|
|
78
|
+
export interface RunRecord {
|
|
79
|
+
score: number;
|
|
80
|
+
total: number;
|
|
81
|
+
tokens?: number;
|
|
82
|
+
model?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface BenchState {
|
|
85
|
+
version: string;
|
|
86
|
+
qsetHash: string;
|
|
87
|
+
protocol: 'in-session';
|
|
88
|
+
cold?: RunRecord;
|
|
89
|
+
faf?: RunRecord;
|
|
90
|
+
}
|
|
91
|
+
/** ✪ receipt — sha256 over the canonical projection; third-party verifiable. */
|
|
92
|
+
export declare function buildReceipt(state: BenchState): {
|
|
93
|
+
projection: string;
|
|
94
|
+
hash: string;
|
|
95
|
+
};
|
|
96
|
+
export interface BenchOptions {
|
|
97
|
+
json?: boolean;
|
|
98
|
+
cold?: boolean;
|
|
99
|
+
faf?: boolean;
|
|
100
|
+
tokens?: string;
|
|
101
|
+
model?: string;
|
|
102
|
+
file?: string;
|
|
103
|
+
}
|
|
104
|
+
export declare function benchCommand(action?: string, answersFile?: string, options?: BenchOptions): void;
|
package/dist/core/interview.d.ts
CHANGED
|
@@ -50,6 +50,14 @@ export declare const STACK_INTERVIEW: InterviewQuestion[];
|
|
|
50
50
|
export declare const INTERVIEW: InterviewQuestion[];
|
|
51
51
|
/** Lookup by slot path. */
|
|
52
52
|
export declare const INTERVIEW_BY_PATH: Map<string, InterviewQuestion>;
|
|
53
|
+
/**
|
|
54
|
+
* Plain-object companion to INTERVIEW_BY_PATH. A Map JSON-serializes to `{}`,
|
|
55
|
+
* which reads as "the export shipped empty" to any consumer that crosses a
|
|
56
|
+
* serialization boundary (caught by the CFM compose handoff, 2026-06-12).
|
|
57
|
+
* Bridge consumers that serialize should use THIS; in-process consumers can
|
|
58
|
+
* use either.
|
|
59
|
+
*/
|
|
60
|
+
export declare const INTERVIEW_PATHS: Record<string, InterviewQuestion>;
|
|
53
61
|
/**
|
|
54
62
|
* Interview voice for ANY slot: the registry question when one exists,
|
|
55
63
|
* otherwise derived from the slot's canonical description — so slot-driven
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔺 TURBO-CAT™ FORMAT PYRAMID v3.1.1
|
|
3
|
+
*
|
|
4
|
+
* ROW 20 IN PROGRESS - 199 FORMATS CATALOGUED!
|
|
5
|
+
*
|
|
6
|
+
* Like precious metals in a catalytic converter - each format triggers
|
|
7
|
+
* a specific intelligence reaction. We CAN catalyze ANY format, but only
|
|
8
|
+
* the WORTHY earn a pyramid stone!
|
|
9
|
+
*
|
|
10
|
+
* Pyramid Evolution:
|
|
11
|
+
* ├── Row 17: Sum(1..17) + 1 = 154 (THE SACRED - ACHIEVED 2024)
|
|
12
|
+
* ├── Row 18: Sum(1..18) + 1 = 172 (BEYOND SACRED - ACHIEVED)
|
|
13
|
+
* ├── Row 19: Sum(1..19) + 1 = 190 (ACHIEVED 2025-12-17)
|
|
14
|
+
* └── Row 20: Sum(1..20) + 1 = 211 (IN PROGRESS - 9/21 added)
|
|
15
|
+
*
|
|
16
|
+
* Row 20 Tier 1 Added (2025-12-17):
|
|
17
|
+
* - build.zig.zon (Zig packages)
|
|
18
|
+
* - gleam.toml (Gleam - 2nd most admired 2025)
|
|
19
|
+
* - bunfig.toml (Bun config)
|
|
20
|
+
* - mise.toml / .mise.toml (mise version manager)
|
|
21
|
+
* - manifest.toml (Flox/Nix environments)
|
|
22
|
+
* - justfile (Just command runner - 10k+ stars)
|
|
23
|
+
* - .pre-commit-config.yaml (Git hooks framework)
|
|
24
|
+
* - CLAUDE.md (Claude Code AI context)
|
|
25
|
+
*
|
|
26
|
+
* THE DOCTRINE: To add a new format, PROVE it's better than existing ones!
|
|
27
|
+
*
|
|
28
|
+
* 😽 We are the FORMAT FREAKS - Quality over Quantity!
|
|
29
|
+
* 🏆 199 formats - CHAMPIONSHIP GRADE FORMAT DETECTION
|
|
30
|
+
*/
|
|
31
|
+
export interface FormatKnowledge {
|
|
32
|
+
frameworks: string[];
|
|
33
|
+
slots: Partial<ContextSlots>;
|
|
34
|
+
priority: number;
|
|
35
|
+
intelligence: 'ultra-high' | 'high' | 'medium' | 'low';
|
|
36
|
+
confirmWith?: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface ContextSlots {
|
|
39
|
+
framework: string;
|
|
40
|
+
mainLanguage: string;
|
|
41
|
+
buildTool: string;
|
|
42
|
+
packageManager: string;
|
|
43
|
+
hosting: string;
|
|
44
|
+
backend: string;
|
|
45
|
+
apiType: string;
|
|
46
|
+
cicd: string;
|
|
47
|
+
database: string;
|
|
48
|
+
cssFramework: string;
|
|
49
|
+
uiLibrary: string;
|
|
50
|
+
stateManagement: string;
|
|
51
|
+
server: string;
|
|
52
|
+
connection: string;
|
|
53
|
+
runtime: string;
|
|
54
|
+
build: string;
|
|
55
|
+
main_language: string;
|
|
56
|
+
build_tool: string;
|
|
57
|
+
pkg_manager: string;
|
|
58
|
+
api: string;
|
|
59
|
+
css: string;
|
|
60
|
+
ui_library: string;
|
|
61
|
+
state: string;
|
|
62
|
+
db: string;
|
|
63
|
+
targetUser: string;
|
|
64
|
+
coreProblem: string;
|
|
65
|
+
missionPurpose: string;
|
|
66
|
+
deploymentMarket: string;
|
|
67
|
+
timeline: string;
|
|
68
|
+
approach: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* THE KNOWLEDGE BASE
|
|
72
|
+
*
|
|
73
|
+
* Add any file format here and map it to:
|
|
74
|
+
* 1. Frameworks it indicates
|
|
75
|
+
* 2. Context slots it can fill
|
|
76
|
+
* 3. Priority/intelligence score
|
|
77
|
+
*
|
|
78
|
+
* The fab-formats engine will automatically use this knowledge!
|
|
79
|
+
*/
|
|
80
|
+
export declare const KNOWLEDGE_BASE: Record<string, FormatKnowledge>;
|
|
81
|
+
/**
|
|
82
|
+
* Get knowledge for a specific format
|
|
83
|
+
*/
|
|
84
|
+
export declare function getFormatKnowledge(format: string): FormatKnowledge | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Get all format keys
|
|
87
|
+
*/
|
|
88
|
+
export declare function getAllFormats(): string[];
|
|
89
|
+
/**
|
|
90
|
+
* Get high-value formats (priority >= 30)
|
|
91
|
+
*/
|
|
92
|
+
export declare function getHighValueFormats(): string[];
|
|
93
|
+
/**
|
|
94
|
+
* Get formats by intelligence level
|
|
95
|
+
*/
|
|
96
|
+
export declare function getFormatsByIntelligence(level: FormatKnowledge['intelligence']): string[];
|
|
97
|
+
/**
|
|
98
|
+
* Get formats that can fill a specific slot
|
|
99
|
+
*/
|
|
100
|
+
export declare function getFormatsForSlot(slotName: keyof ContextSlots): string[];
|
|
101
|
+
/**
|
|
102
|
+
* Calculate total possible intelligence score
|
|
103
|
+
*/
|
|
104
|
+
export declare function getMaxIntelligenceScore(): number;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turbo-Cat™ (= Format-finder) — fills .faf slots from file-format evidence
|
|
3
|
+
* across ~200 formats (the KNOWLEDGE_BASE). Restores the multi-ecosystem
|
|
4
|
+
* manifest interrogation the v6.0 rewrite narrowed to README+Cargo+package.json.
|
|
5
|
+
*
|
|
6
|
+
* v6-native sync port (the v5 engine was async; sync integrates cleanly with
|
|
7
|
+
* `auto`). Two-layer: (1A) config files walking up to the monorepo .git
|
|
8
|
+
* boundary, (1B) source extensions; priority-wins slot recommendations.
|
|
9
|
+
*
|
|
10
|
+
* Used as the LOWEST-precedence filler in `auto`: v6's specific detection wins;
|
|
11
|
+
* Turbo-Cat fills only the slots still empty (esp. non-npm stacks).
|
|
12
|
+
*/
|
|
13
|
+
/** A format actually discovered on disk (config-file layer; real files only). */
|
|
14
|
+
export interface DiscoveredFormat {
|
|
15
|
+
fileName: string;
|
|
16
|
+
/** Derived from the entry's primary slot family (deterministic — real
|
|
17
|
+
* knowledge surfaced, not invented): package-manager, language, framework,
|
|
18
|
+
* backend, database, ci-cd, hosting, build, … */
|
|
19
|
+
category: string;
|
|
20
|
+
priority: number;
|
|
21
|
+
}
|
|
22
|
+
export interface TurboCatResult {
|
|
23
|
+
slotFills: Record<string, string>;
|
|
24
|
+
frameworks: string[];
|
|
25
|
+
confirmedCount: number;
|
|
26
|
+
/** Option B (compose spec 2026-06-12): the per-format breakdown consumers
|
|
27
|
+
* display — surfaced so MCPs can DELETE their local format maps entirely. */
|
|
28
|
+
discoveredFormats: DiscoveredFormat[];
|
|
29
|
+
/** Deterministic lowercase signature, e.g. "typescript-react" ('unknown-stack' when bare). */
|
|
30
|
+
stackSignature: string;
|
|
31
|
+
}
|
|
32
|
+
/** Scan formats → priority-wins slot recommendations. */
|
|
33
|
+
export declare function turboCatScan(projectDir: string): TurboCatResult;
|
|
34
|
+
/** Turbo-Cat slot fills shaped as a v6 .faf partial ({ project, stack }) for fillEmpties. */
|
|
35
|
+
export declare function turboCatSlots(projectDir: string): {
|
|
36
|
+
project?: Record<string, string>;
|
|
37
|
+
stack?: Record<string, string>;
|
|
38
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,9 @@ export { validateFaf } from './core/schema.js';
|
|
|
7
7
|
export { findFafFile, readFaf, readFafRaw } from './interop/faf.js';
|
|
8
8
|
export { generateProjectHtml, writeProjectHtml } from './interop/projecthtml.js';
|
|
9
9
|
export type { InterviewQuestion, InterviewOption } from './core/interview.js';
|
|
10
|
-
export { INTERVIEW, SIX_WS_INTERVIEW, STACK_INTERVIEW, INTERVIEW_BY_PATH, INTERVIEW_VERSION, questionForSlot, interviewForMissing, } from './core/interview.js';
|
|
10
|
+
export { INTERVIEW, SIX_WS_INTERVIEW, STACK_INTERVIEW, INTERVIEW_BY_PATH, INTERVIEW_PATHS, INTERVIEW_VERSION, questionForSlot, interviewForMissing, } from './core/interview.js';
|
|
11
|
+
export { BENCH_VERSION, deriveQuestionSet, publicQuestions, gradeAnswers, buildReceipt, normalizeAnswer, answersMatch, ALIAS_GROUPS, } from './commands/bench.js';
|
|
12
|
+
export type { BenchQuestion, QuestionSet, GradeResult, BenchState, RunRecord } from './commands/bench.js';
|
|
13
|
+
export { turboCatScan, turboCatSlots } from './detect/turbo-cat.js';
|
|
14
|
+
export type { TurboCatResult, DiscoveredFormat } from './detect/turbo-cat.js';
|
|
11
15
|
export * as kernel from './wasm/kernel.js';
|