@tangle-network/starter-foundry 0.5.2 → 0.5.4
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 +49 -0
- package/corpus/ideasai-prompts.json +119 -58
- package/dist/cli.js +28 -2
- package/dist/cli.js.map +1 -1
- package/dist/lib/agent-context.js +34 -22
- package/dist/lib/agent-context.js.map +1 -1
- package/dist/lib/build-plan.d.ts +18 -0
- package/dist/lib/build-plan.js +72 -0
- package/dist/lib/build-plan.js.map +1 -1
- package/dist/lib/buildout-traces.d.ts +113 -0
- package/dist/lib/buildout-traces.js +83 -0
- package/dist/lib/buildout-traces.js.map +1 -0
- package/dist/lib/capability-inferrer.d.ts +40 -0
- package/dist/lib/capability-inferrer.js +82 -0
- package/dist/lib/capability-inferrer.js.map +1 -0
- package/dist/lib/context-pack.d.ts +6 -1
- package/dist/lib/context-pack.js +9 -3
- package/dist/lib/context-pack.js.map +1 -1
- package/dist/lib/keywords.js +71 -18
- package/dist/lib/keywords.js.map +1 -1
- package/dist/lib/llm.d.ts +9 -0
- package/dist/lib/llm.js +70 -0
- package/dist/lib/llm.js.map +1 -0
- package/dist/lib/planner/contracts.d.ts +11 -0
- package/dist/lib/planner/contracts.js +119 -0
- package/dist/lib/planner/contracts.js.map +1 -0
- package/dist/lib/planner/detectors.d.ts +14 -0
- package/dist/lib/planner/detectors.js +195 -0
- package/dist/lib/planner/detectors.js.map +1 -0
- package/dist/lib/planner/helpers.d.ts +2 -0
- package/dist/lib/planner/helpers.js +135 -0
- package/dist/lib/planner/helpers.js.map +1 -0
- package/dist/lib/planner/implicit-caps.d.ts +1 -0
- package/dist/lib/planner/implicit-caps.js +91 -0
- package/dist/lib/planner/implicit-caps.js.map +1 -0
- package/dist/lib/planner/projects.d.ts +13 -0
- package/dist/lib/planner/projects.js +181 -0
- package/dist/lib/planner/projects.js.map +1 -0
- package/dist/lib/planner/signals.d.ts +17 -0
- package/dist/lib/planner/signals.js +324 -0
- package/dist/lib/planner/signals.js.map +1 -0
- package/dist/lib/product-brief.d.ts +25 -0
- package/dist/lib/product-brief.js +129 -0
- package/dist/lib/product-brief.js.map +1 -0
- package/dist/lib/prompt-planner.d.ts +5 -1
- package/dist/lib/prompt-planner.js +59 -622
- package/dist/lib/prompt-planner.js.map +1 -1
- package/dist/lib/prompt-rewriter.d.ts +21 -0
- package/dist/lib/prompt-rewriter.js +118 -0
- package/dist/lib/prompt-rewriter.js.map +1 -0
- package/dist/lib/selection.js +170 -36
- package/dist/lib/selection.js.map +1 -1
- package/dist/lib/telemetry.d.ts +0 -11
- package/dist/lib/telemetry.js +3 -3
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/vb-outcomes.d.ts +61 -0
- package/dist/lib/vb-outcomes.js +88 -0
- package/dist/lib/vb-outcomes.js.map +1 -0
- package/dist/training/variant_b/brief-loader.d.ts +5 -0
- package/dist/training/variant_b/brief-loader.js +263 -0
- package/dist/training/variant_b/brief-loader.js.map +1 -0
- package/dist/training/variant_b/flow.d.ts +56 -0
- package/dist/training/variant_b/flow.js +80 -0
- package/dist/training/variant_b/flow.js.map +1 -0
- package/dist/training/variant_b/generate.d.ts +7 -0
- package/dist/training/variant_b/generate.js +70 -0
- package/dist/training/variant_b/generate.js.map +1 -0
- package/dist/training/variant_b/judge.d.ts +8 -0
- package/dist/training/variant_b/judge.js +24 -0
- package/dist/training/variant_b/judge.js.map +1 -0
- package/dist/training/variant_b/nodes/collect.d.ts +31 -0
- package/dist/training/variant_b/nodes/collect.js +122 -0
- package/dist/training/variant_b/nodes/collect.js.map +1 -0
- package/dist/training/variant_b/nodes/generate.d.ts +22 -0
- package/dist/training/variant_b/nodes/generate.js +171 -0
- package/dist/training/variant_b/nodes/generate.js.map +1 -0
- package/dist/training/variant_b/nodes/judge.d.ts +26 -0
- package/dist/training/variant_b/nodes/judge.js +64 -0
- package/dist/training/variant_b/nodes/judge.js.map +1 -0
- package/dist/training/variant_b/nodes/promote.d.ts +15 -0
- package/dist/training/variant_b/nodes/promote.js +64 -0
- package/dist/training/variant_b/nodes/promote.js.map +1 -0
- package/dist/training/variant_b/nodes/rank.d.ts +12 -0
- package/dist/training/variant_b/nodes/rank.js +46 -0
- package/dist/training/variant_b/nodes/rank.js.map +1 -0
- package/dist/training/variant_b/nodes/train.d.ts +34 -0
- package/dist/training/variant_b/nodes/train.js +209 -0
- package/dist/training/variant_b/nodes/train.js.map +1 -0
- package/dist/training/variant_b/run-flow.d.ts +11 -0
- package/dist/training/variant_b/run-flow.js +21 -0
- package/dist/training/variant_b/run-flow.js.map +1 -0
- package/dist/training/variant_b/train.d.ts +15 -0
- package/dist/training/variant_b/train.js +37 -0
- package/dist/training/variant_b/train.js.map +1 -0
- package/dist/types.d.ts +16 -0
- package/package.json +6 -2
- package/registry/families/browser-extension-ts/files/package.json +4 -1
- package/registry/families/cli-ts/files/package.json +5 -0
- package/registry/families/electron-desktop-ts/files/package.json +3 -1
- package/registry/families/expo-react-native-ts/files/package.json +4 -0
- package/registry/families/fhenix-contracts/files/package.json +1 -1
- package/registry/families/fhevm-contracts/files/package.json +1 -1
- package/registry/families/fullstack-ts/files/package.json +3 -1
- package/registry/families/hardhat-contracts/files/package.json +3 -1
- package/registry/families/nextjs-ts/files/package.json +3 -1
- package/registry/families/react-vite-ts/files/package.json +11 -1
- package/registry/families/react-vite-ts/files/src/components/ui/badge.tsx +9 -0
- package/registry/families/react-vite-ts/files/src/components/ui/button.tsx +18 -0
- package/registry/families/react-vite-ts/files/src/components/ui/card.tsx +22 -0
- package/registry/families/react-vite-ts/manifest.json +14 -2
- package/registry/families/remix-ts/files/package.json +9 -1
- package/registry/families/sveltekit-ts/files/package.json +9 -1
- package/registry/families/tauri-desktop/files/package.json +3 -1
- package/registry/families/vue-ts/files/package.json +9 -1
- package/registry/layers/framework/expo-react-native-ts/files/tsconfig.json +2 -1
- package/registry/layers/framework/forge-foundation/files/foundry.toml +22 -1
- package/registry/layers/framework/fullstack-node-ts/files/personalize.json +5 -5
- package/registry/layers/framework/tangle-blueprint/files/TOOLCHAIN.md +16 -0
- package/registry/layers/framework/tangle-blueprint/files/rust-toolchain.toml +1 -1
- package/registry/layers/framework/tangle-blueprint/manifest.json +4 -0
- package/registry/package-to-capability.json +57 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// promote node: takes top ranked candidates that passed the judge and writes
|
|
2
|
+
// them as minimal capability manifests under registry/layers/capability/<id>/.
|
|
3
|
+
// Stops at top-K promotable-only. Idempotent — won't overwrite existing
|
|
4
|
+
// manifests. The registry is the system of record.
|
|
5
|
+
//
|
|
6
|
+
// Swap strategy: replace the manifest writer with a PR-opener or a dry-run
|
|
7
|
+
// committer without changing the node contract.
|
|
8
|
+
import { mkdir, writeFile, access } from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
async function exists(p) {
|
|
11
|
+
try {
|
|
12
|
+
await access(p);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function promoteNode(input) {
|
|
20
|
+
const promoted = [];
|
|
21
|
+
const skipped = [];
|
|
22
|
+
const max = input.maxPromotions ?? 8;
|
|
23
|
+
const candidates = input.ranked.filter((c) => c.score.promotable).slice(0, max);
|
|
24
|
+
for (const c of candidates) {
|
|
25
|
+
const dir = path.join(input.registryRoot, 'layers', 'capability', c.candidate.id);
|
|
26
|
+
if (await exists(dir)) {
|
|
27
|
+
skipped.push({ id: c.candidate.id, reason: 'already-exists' });
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const manifest = {
|
|
31
|
+
id: c.candidate.id,
|
|
32
|
+
description: c.candidate.description,
|
|
33
|
+
appliesTo: [c.candidate.family],
|
|
34
|
+
defaults: {},
|
|
35
|
+
files: [],
|
|
36
|
+
contextHints: {
|
|
37
|
+
extensionPoints: [],
|
|
38
|
+
notes: `Promoted by variant_b flow (rank=${c.rank}, composite=${c.score.composite.toFixed(3)}).`,
|
|
39
|
+
},
|
|
40
|
+
keywords: c.candidate.promptKeywords,
|
|
41
|
+
buildHints: {
|
|
42
|
+
capabilityBundle: c.candidate.capabilities,
|
|
43
|
+
rationale: c.candidate.rationale,
|
|
44
|
+
},
|
|
45
|
+
// variant_b metadata so a future reviewer can filter promoted
|
|
46
|
+
// archetypes and audit the loop's output.
|
|
47
|
+
provenance: {
|
|
48
|
+
generatedBy: 'variant_b',
|
|
49
|
+
source: c.candidate.source,
|
|
50
|
+
scores: c.score,
|
|
51
|
+
promotedAt: new Date().toISOString(),
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
if (input.dryRun) {
|
|
55
|
+
promoted.push(c.candidate.id);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
await mkdir(dir, { recursive: true });
|
|
59
|
+
await writeFile(path.join(dir, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
60
|
+
promoted.push(c.candidate.id);
|
|
61
|
+
}
|
|
62
|
+
return { promoted, skipped };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=promote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promote.js","sourceRoot":"","sources":["../../../../src/training/variant_b/nodes/promote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ScoredCandidate } from './judge.js';
|
|
2
|
+
export interface RankedCandidate extends ScoredCandidate {
|
|
3
|
+
rank: number;
|
|
4
|
+
paretoFrontier: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface RankInput {
|
|
7
|
+
scored: ScoredCandidate[];
|
|
8
|
+
}
|
|
9
|
+
export interface RankOutput {
|
|
10
|
+
ranked: RankedCandidate[];
|
|
11
|
+
}
|
|
12
|
+
export declare function rankNode(input: RankInput): Promise<RankOutput>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// rank node: Pareto-rank scored candidates across (utility, specificity,
|
|
2
|
+
// novelty, rubric). Dominated candidates are dropped. Non-dominated frontier
|
|
3
|
+
// is ordered by composite score. This is a swap point — could be replaced
|
|
4
|
+
// with Borda count, ELO, or a learned ranker without touching the nodes
|
|
5
|
+
// upstream or downstream.
|
|
6
|
+
function dominates(a, b) {
|
|
7
|
+
const dims = [
|
|
8
|
+
[a.score.utility, b.score.utility],
|
|
9
|
+
[a.score.specificity, b.score.specificity],
|
|
10
|
+
[a.score.novelty, b.score.novelty],
|
|
11
|
+
[a.score.rubric, b.score.rubric],
|
|
12
|
+
];
|
|
13
|
+
let strictlyBetter = false;
|
|
14
|
+
for (const [x, y] of dims) {
|
|
15
|
+
if (x < y)
|
|
16
|
+
return false;
|
|
17
|
+
if (x > y)
|
|
18
|
+
strictlyBetter = true;
|
|
19
|
+
}
|
|
20
|
+
return strictlyBetter;
|
|
21
|
+
}
|
|
22
|
+
export async function rankNode(input) {
|
|
23
|
+
const ranked = [];
|
|
24
|
+
for (const c of input.scored) {
|
|
25
|
+
let isDominated = false;
|
|
26
|
+
for (const other of input.scored) {
|
|
27
|
+
if (other === c)
|
|
28
|
+
continue;
|
|
29
|
+
if (dominates(other, c)) {
|
|
30
|
+
isDominated = true;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
ranked.push({ ...c, rank: 0, paretoFrontier: !isDominated });
|
|
35
|
+
}
|
|
36
|
+
ranked.sort((a, b) => {
|
|
37
|
+
if (a.paretoFrontier !== b.paretoFrontier)
|
|
38
|
+
return a.paretoFrontier ? -1 : 1;
|
|
39
|
+
return b.score.composite - a.score.composite;
|
|
40
|
+
});
|
|
41
|
+
ranked.forEach((c, i) => {
|
|
42
|
+
c.rank = i + 1;
|
|
43
|
+
});
|
|
44
|
+
return { ranked };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=rank.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rank.js","sourceRoot":"","sources":["../../../../src/training/variant_b/nodes/rank.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,6EAA6E;AAC7E,0EAA0E;AAC1E,wEAAwE;AACxE,0BAA0B;AAiB1B,SAAS,SAAS,CAAC,CAAkB,EAAE,CAAkB;IACvD,MAAM,IAAI,GAA4B;QACpC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QAClC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;QAC1C,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QAClC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;KACjC,CAAA;IACD,IAAI,cAAc,GAAG,KAAK,CAAA;IAC1B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;QACvB,IAAI,CAAC,GAAG,CAAC;YAAE,cAAc,GAAG,IAAI,CAAA;IAClC,CAAC;IACD,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAgB;IAC7C,MAAM,MAAM,GAAsB,EAAE,CAAA;IACpC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7B,IAAI,WAAW,GAAG,KAAK,CAAA;QACvB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,KAAK,KAAK,CAAC;gBAAE,SAAQ;YACzB,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;gBACxB,WAAW,GAAG,IAAI,CAAA;gBAClB,MAAK;YACP,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;IAC9D,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnB,IAAI,CAAC,CAAC,cAAc,KAAK,CAAC,CAAC,cAAc;YAAE,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC3E,OAAO,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAA;IAC9C,CAAC,CAAC,CAAA;IACF,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACtB,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAChB,CAAC,CAAC,CAAA;IACF,OAAO,EAAE,MAAM,EAAE,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AxAIService } from '@ax-llm/ax';
|
|
2
|
+
import type { Trace } from './collect.js';
|
|
3
|
+
export interface TrainInput {
|
|
4
|
+
traces: Trace[];
|
|
5
|
+
outPath: string;
|
|
6
|
+
llm: AxAIService;
|
|
7
|
+
maxRounds?: number;
|
|
8
|
+
auto?: 'light' | 'medium' | 'heavy';
|
|
9
|
+
}
|
|
10
|
+
export interface SerializedOptimizedProgram {
|
|
11
|
+
optimizerType: string;
|
|
12
|
+
bestScore: number;
|
|
13
|
+
instruction?: string;
|
|
14
|
+
instructionMap?: Record<string, string>;
|
|
15
|
+
demos?: unknown[];
|
|
16
|
+
modelConfig?: Record<string, unknown>;
|
|
17
|
+
optimizationTime: number;
|
|
18
|
+
totalRounds: number;
|
|
19
|
+
converged: boolean;
|
|
20
|
+
scoreHistory?: number[];
|
|
21
|
+
artifactFormatVersion?: number;
|
|
22
|
+
signature: string;
|
|
23
|
+
promptShape: 'brief';
|
|
24
|
+
trainedAt: string;
|
|
25
|
+
trainingTraceCount: number;
|
|
26
|
+
knownFamilies: string[];
|
|
27
|
+
knownCapabilities: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface TrainOutput {
|
|
30
|
+
optimizedProgram: SerializedOptimizedProgram;
|
|
31
|
+
outPath: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function trainNode(input: TrainInput): Promise<TrainOutput>;
|
|
34
|
+
export declare function buildCorpusMinedInstruction(trainables: Trace[], knownCapabilities: string[]): string;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// train node: takes traces, runs AxMiPRO over the brief signature to find an
|
|
2
|
+
// instruction that biases the brief agent toward producing canonicalPrompts
|
|
3
|
+
// that route correctly through the deterministic planner. The optimized
|
|
4
|
+
// artifact is serialized to JSON at outPath as an AxOptimizedProgram.
|
|
5
|
+
//
|
|
6
|
+
// Swap strategy: replace `AxMiPRO` with `AxBootstrapFewShot` or `AxGEPA` by
|
|
7
|
+
// changing only this file. The TrainOutput contract stays fixed.
|
|
8
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { ax, AxMiPRO } from '@ax-llm/ax';
|
|
11
|
+
import { loadRegistry } from '../../../lib/registry.js';
|
|
12
|
+
import { planPrompt } from '../../../lib/prompt-planner.js';
|
|
13
|
+
const BRIEF_SIGNATURE = '"Turn a user product prompt into a structured product brief that drives a deterministic scaffold pipeline downstream. The canonicalPrompt must be a keyword-rich expansion that names concrete technologies drawn from knownFamilies (e.g. nextjs-ts, fullstack-ts, agent-service-ts, go-api, python-api, forge-contracts, solana-program) and concrete UI/infra capabilities drawn from knownCapabilities (e.g. capability:ai-chat-ui, capability:layout-dashboard, capability:saas-billing). It MUST be longer and more specific than the user prompt. Preserve the user intent exactly. Each list field should have 3-8 items." ' +
|
|
14
|
+
'userPrompt:string, knownFamilies:string[], knownCapabilities:string[] -> ' +
|
|
15
|
+
'canonicalPrompt:string, vision:string, taskChecklist:string[], milestones:string[], testingPlan:string[], e2ePlan:string[], securityConcerns:string[], openQuestions:string[], confidence:number';
|
|
16
|
+
function jaccard(a, b) {
|
|
17
|
+
const A = new Set(a);
|
|
18
|
+
const B = new Set(b);
|
|
19
|
+
if (A.size === 0 && B.size === 0)
|
|
20
|
+
return 1;
|
|
21
|
+
let inter = 0;
|
|
22
|
+
for (const x of A)
|
|
23
|
+
if (B.has(x))
|
|
24
|
+
inter++;
|
|
25
|
+
const union = A.size + B.size - inter;
|
|
26
|
+
return union === 0 ? 1 : inter / union;
|
|
27
|
+
}
|
|
28
|
+
async function buildKnownLists() {
|
|
29
|
+
const registry = await loadRegistry();
|
|
30
|
+
const knownFamilies = [...registry.families.keys()];
|
|
31
|
+
const knownCapabilities = [];
|
|
32
|
+
for (const [key] of registry.layers) {
|
|
33
|
+
if (key.startsWith('capability:'))
|
|
34
|
+
knownCapabilities.push(key);
|
|
35
|
+
}
|
|
36
|
+
return { knownFamilies, knownCapabilities };
|
|
37
|
+
}
|
|
38
|
+
// Build a metric: for each predicted canonicalPrompt, re-route through the
|
|
39
|
+
// deterministic planner and measure capability-jaccard vs the expected
|
|
40
|
+
// capabilities from the training example. This is exactly what downstream
|
|
41
|
+
// eval will measure, so we optimize the metric that matters.
|
|
42
|
+
function makeMetric(expectedByPrompt) {
|
|
43
|
+
return async ({ prediction, example }) => {
|
|
44
|
+
const pred = prediction;
|
|
45
|
+
const canonical = (pred.canonicalPrompt ?? '').trim();
|
|
46
|
+
if (!canonical)
|
|
47
|
+
return 0;
|
|
48
|
+
const ex = example;
|
|
49
|
+
const userPrompt = typeof ex['userPrompt'] === 'string' ? ex['userPrompt'] : '';
|
|
50
|
+
const expected = expectedByPrompt.get(userPrompt) ?? [];
|
|
51
|
+
if (expected.length === 0) {
|
|
52
|
+
// no expected caps — reward length + diversity as a weak proxy
|
|
53
|
+
return canonical.length > userPrompt.length ? 0.5 : 0;
|
|
54
|
+
}
|
|
55
|
+
let plan = null;
|
|
56
|
+
try {
|
|
57
|
+
plan = await planPrompt({ prompt: canonical });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
const p = plan;
|
|
63
|
+
const actual = p?.kind === 'starter'
|
|
64
|
+
? p.spec?.layers ?? []
|
|
65
|
+
: (p?.spec?.projects ?? []).flatMap((proj) => proj.layers ?? []);
|
|
66
|
+
return jaccard(actual, expected);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export async function trainNode(input) {
|
|
70
|
+
const { knownFamilies, knownCapabilities } = await buildKnownLists();
|
|
71
|
+
// Only train on ideasai traces that have expected capabilities. held-out is
|
|
72
|
+
// measurement, not training. We also skip traces where capabilityHit was
|
|
73
|
+
// already 1.0 (nothing to learn).
|
|
74
|
+
const trainables = input.traces.filter((t) => t.corpus === 'ideasai' && t.expectedCapabilities.length > 0 && t.capabilityHit < 1.0);
|
|
75
|
+
const examples = trainables.slice(0, 30).map((t) => ({
|
|
76
|
+
userPrompt: t.prompt,
|
|
77
|
+
knownFamilies,
|
|
78
|
+
knownCapabilities,
|
|
79
|
+
}));
|
|
80
|
+
const expectedByPrompt = new Map();
|
|
81
|
+
for (const t of trainables)
|
|
82
|
+
expectedByPrompt.set(t.prompt, t.expectedCapabilities);
|
|
83
|
+
const briefProgram = ax(BRIEF_SIGNATURE);
|
|
84
|
+
const metric = makeMetric(expectedByPrompt);
|
|
85
|
+
let bestScore = 0;
|
|
86
|
+
let instruction;
|
|
87
|
+
let instructionMap;
|
|
88
|
+
let demos;
|
|
89
|
+
let modelConfig;
|
|
90
|
+
let optimizerType = 'variant_b.fallback';
|
|
91
|
+
let optimizationTime = 0;
|
|
92
|
+
let totalRounds = 0;
|
|
93
|
+
let converged = false;
|
|
94
|
+
let scoreHistory;
|
|
95
|
+
if (examples.length >= 3) {
|
|
96
|
+
try {
|
|
97
|
+
const optimizer = new AxMiPRO({
|
|
98
|
+
studentAI: input.llm,
|
|
99
|
+
numTrials: 3,
|
|
100
|
+
numCandidates: 3,
|
|
101
|
+
minibatch: true,
|
|
102
|
+
minibatchSize: Math.min(6, examples.length),
|
|
103
|
+
verbose: false,
|
|
104
|
+
seed: 42,
|
|
105
|
+
});
|
|
106
|
+
optimizer.configureAuto(input.auto ?? 'light');
|
|
107
|
+
const t0 = Date.now();
|
|
108
|
+
const result = await optimizer.compile(briefProgram, examples, metric, {
|
|
109
|
+
maxMetricCalls: Math.max(examples.length * 2, 12),
|
|
110
|
+
auto: input.auto ?? 'light',
|
|
111
|
+
verbose: false,
|
|
112
|
+
});
|
|
113
|
+
optimizationTime = Date.now() - t0;
|
|
114
|
+
const opt = result.optimizedProgram;
|
|
115
|
+
if (opt) {
|
|
116
|
+
bestScore = opt.bestScore;
|
|
117
|
+
instruction = opt.instruction;
|
|
118
|
+
instructionMap = opt.instructionMap;
|
|
119
|
+
demos = opt.demos;
|
|
120
|
+
modelConfig = opt.modelConfig;
|
|
121
|
+
optimizerType = opt.optimizerType;
|
|
122
|
+
totalRounds = opt.totalRounds;
|
|
123
|
+
converged = opt.converged;
|
|
124
|
+
scoreHistory = opt.scoreHistory;
|
|
125
|
+
}
|
|
126
|
+
else if (result.bestScore !== undefined) {
|
|
127
|
+
bestScore = result.bestScore;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
// Rate-limits, provider blips — fall back to the corpus-mined instruction
|
|
132
|
+
// so the variant still produces an artifact.
|
|
133
|
+
// eslint-disable-next-line no-console
|
|
134
|
+
console.warn('[variant_b/train] AxMiPRO failed, using fallback:', err instanceof Error ? err.message : err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Always attach a corpus-mined instruction as a floor. This is the part that
|
|
138
|
+
// reliably moves capHit because it surfaces the exact vocabulary the
|
|
139
|
+
// deterministic planner keys off. Real optimization can only improve on it.
|
|
140
|
+
if (!instruction) {
|
|
141
|
+
instruction = buildCorpusMinedInstruction(trainables, knownCapabilities);
|
|
142
|
+
optimizerType = optimizerType === 'variant_b.fallback' ? 'variant_b.corpus-mined' : optimizerType;
|
|
143
|
+
}
|
|
144
|
+
const artifact = {
|
|
145
|
+
optimizerType,
|
|
146
|
+
bestScore,
|
|
147
|
+
instruction,
|
|
148
|
+
instructionMap,
|
|
149
|
+
demos: Array.isArray(demos) ? demos.slice(0, 8) : demos,
|
|
150
|
+
modelConfig,
|
|
151
|
+
optimizationTime,
|
|
152
|
+
totalRounds,
|
|
153
|
+
converged,
|
|
154
|
+
scoreHistory,
|
|
155
|
+
artifactFormatVersion: 1,
|
|
156
|
+
signature: BRIEF_SIGNATURE,
|
|
157
|
+
promptShape: 'brief',
|
|
158
|
+
trainedAt: new Date().toISOString(),
|
|
159
|
+
trainingTraceCount: trainables.length,
|
|
160
|
+
knownFamilies,
|
|
161
|
+
knownCapabilities,
|
|
162
|
+
};
|
|
163
|
+
await mkdir(path.dirname(input.outPath), { recursive: true });
|
|
164
|
+
await writeFile(input.outPath, JSON.stringify(artifact, null, 2));
|
|
165
|
+
return { optimizedProgram: artifact, outPath: input.outPath };
|
|
166
|
+
}
|
|
167
|
+
// Mine the training traces to learn the high-signal vocabulary. For each
|
|
168
|
+
// expected capability that was missed, collect the keywords from the original
|
|
169
|
+
// prompt that co-occur with it. Build those into a tight instruction that
|
|
170
|
+
// tells the brief agent to SURFACE the capability name explicitly when it
|
|
171
|
+
// sees those keywords. This is the deterministic floor the optimizer must
|
|
172
|
+
// beat. In practice it already lifts ideasaiCapHit materially because the
|
|
173
|
+
// brief's canonicalPrompt will contain the exact layer IDs the planner scans.
|
|
174
|
+
export function buildCorpusMinedInstruction(trainables, knownCapabilities) {
|
|
175
|
+
const capToKeywords = new Map();
|
|
176
|
+
for (const t of trainables) {
|
|
177
|
+
const words = t.prompt
|
|
178
|
+
.toLowerCase()
|
|
179
|
+
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
180
|
+
.split(/\s+/)
|
|
181
|
+
.filter((w) => w.length >= 4);
|
|
182
|
+
for (const cap of t.expectedCapabilities) {
|
|
183
|
+
if (t.actualCapabilities.includes(cap))
|
|
184
|
+
continue; // already hit, no lesson
|
|
185
|
+
if (!capToKeywords.has(cap))
|
|
186
|
+
capToKeywords.set(cap, new Map());
|
|
187
|
+
const m = capToKeywords.get(cap);
|
|
188
|
+
for (const w of words)
|
|
189
|
+
m.set(w, (m.get(w) ?? 0) + 1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const lines = [];
|
|
193
|
+
lines.push('ALWAYS name the capability IDs explicitly in canonicalPrompt when the user prompt matches.');
|
|
194
|
+
lines.push('For ambiguous AI-saas prompts, prefer fullstack-ts or nextjs-ts family.');
|
|
195
|
+
lines.push('Route rules (ordered):');
|
|
196
|
+
const entries = [...capToKeywords.entries()]
|
|
197
|
+
.map(([cap, m]) => ({ cap, top: [...m.entries()].sort((a, b) => b[1] - a[1]).slice(0, 6).map(([w]) => w) }))
|
|
198
|
+
.filter((e) => knownCapabilities.includes(e.cap))
|
|
199
|
+
.slice(0, 12);
|
|
200
|
+
for (const { cap, top } of entries) {
|
|
201
|
+
lines.push(`- If prompt mentions any of [${top.join(', ')}] include "${cap}" in canonicalPrompt.`);
|
|
202
|
+
}
|
|
203
|
+
lines.push('ALWAYS include capability:tailwind for any UI that renders pages.');
|
|
204
|
+
lines.push('ALWAYS include capability:layout-dashboard when prompt describes analytics, tracking, monitoring, or multiple views.');
|
|
205
|
+
lines.push('ALWAYS include capability:layout-chat when prompt describes messaging, conversation, or companion UX.');
|
|
206
|
+
lines.push('ALWAYS include capability:ai-chat-ui when the product is AI-driven or talks to the user.');
|
|
207
|
+
return lines.join('\n');
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=train.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"train.js","sourceRoot":"","sources":["../../../../src/training/variant_b/nodes/train.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FlowOutput } from './flow.js';
|
|
2
|
+
export interface RunFullFlowInput {
|
|
3
|
+
corpusPath?: string;
|
|
4
|
+
registryRoot?: string;
|
|
5
|
+
tracesDir?: string;
|
|
6
|
+
optimizedPath?: string;
|
|
7
|
+
ideasPath?: string;
|
|
8
|
+
judgePath?: string;
|
|
9
|
+
iterations?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function runFullFlow(input?: RunFullFlowInput): Promise<FlowOutput>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// runFullFlow: runs the entire AxFlow pipeline end-to-end. Used by the
|
|
2
|
+
// variant_b-flow.mjs script and by the integration test. This is the
|
|
3
|
+
// one-shot "do everything" entrypoint.
|
|
4
|
+
import { buildVariantBFlow } from './flow.js';
|
|
5
|
+
import { createLLM } from '../../lib/llm.js';
|
|
6
|
+
export async function runFullFlow(input = {}) {
|
|
7
|
+
const llm = createLLM();
|
|
8
|
+
const flowInstance = buildVariantBFlow();
|
|
9
|
+
const result = await flowInstance.forward(llm, {
|
|
10
|
+
corpusPath: input.corpusPath ?? 'corpus/ideasai-prompts.json',
|
|
11
|
+
registryRoot: input.registryRoot ?? 'registry',
|
|
12
|
+
tracesDir: input.tracesDir ?? '.evolve/traces',
|
|
13
|
+
optimizedPath: input.optimizedPath ?? '.evolve/optimized/brief-variant_b.json',
|
|
14
|
+
ideasPath: input.ideasPath ?? '.evolve/ideas/variant_b.json',
|
|
15
|
+
judgePath: input.judgePath ?? '.evolve/judge/variant_b.jsonl',
|
|
16
|
+
iterations: input.iterations ?? 1,
|
|
17
|
+
llm,
|
|
18
|
+
});
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=run-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-flow.js","sourceRoot":"","sources":["../../../src/training/variant_b/run-flow.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,qEAAqE;AACrE,uCAAuC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAa5C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAA0B,EAAE;IAC5D,MAAM,GAAG,GAAG,SAAS,EAAE,CAAA;IACvB,MAAM,YAAY,GAAG,iBAAiB,EAAE,CAAA;IACxC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE;QAC7C,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,6BAA6B;QAC7D,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,UAAU;QAC9C,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,gBAAgB;QAC9C,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,wCAAwC;QAC9E,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,8BAA8B;QAC5D,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,+BAA+B;QAC7D,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC;QACjC,GAAG;KACJ,CAAC,CAAA;IACF,OAAO,MAAoB,CAAA;AAC7B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SerializedOptimizedProgram } from './nodes/train.js';
|
|
2
|
+
export interface RunTrainingLoopInput {
|
|
3
|
+
corpusPath: string;
|
|
4
|
+
outPath: string;
|
|
5
|
+
tracesDir?: string;
|
|
6
|
+
auto?: 'light' | 'medium' | 'heavy';
|
|
7
|
+
limit?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface RunTrainingLoopResult {
|
|
10
|
+
optimizedProgram: SerializedOptimizedProgram;
|
|
11
|
+
outPath: string;
|
|
12
|
+
traceCount: number;
|
|
13
|
+
tracesFile: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function runTrainingLoop(input: RunTrainingLoopInput): Promise<RunTrainingLoopResult>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Public entrypoint: runTrainingLoop({ corpusPath, outPath })
|
|
2
|
+
//
|
|
3
|
+
// Contract (see scripts/multi-pursue-eval.mjs):
|
|
4
|
+
// - Read corpusPath (defaults to corpus/ideasai-prompts.json)
|
|
5
|
+
// - Synthesize traces via the collect node
|
|
6
|
+
// - Run the train node, which compiles AxMiPRO on the brief signature
|
|
7
|
+
// - Write serialized AxOptimizedProgram JSON to outPath
|
|
8
|
+
//
|
|
9
|
+
// This wraps exactly the first two nodes of the flow. The full flow lives in
|
|
10
|
+
// run-flow.ts. Training is separated so the eval harness can run it without
|
|
11
|
+
// paying for generate/judge/rank/promote.
|
|
12
|
+
import { createLLM } from '../../lib/llm.js';
|
|
13
|
+
import { collectNode } from './nodes/collect.js';
|
|
14
|
+
import { trainNode } from './nodes/train.js';
|
|
15
|
+
export async function runTrainingLoop(input) {
|
|
16
|
+
const tracesDir = input.tracesDir ?? '.evolve/traces';
|
|
17
|
+
const collect = await collectNode({
|
|
18
|
+
corpusPath: input.corpusPath,
|
|
19
|
+
tracesDir,
|
|
20
|
+
limit: input.limit,
|
|
21
|
+
includeHeldOut: true,
|
|
22
|
+
});
|
|
23
|
+
const llm = createLLM();
|
|
24
|
+
const train = await trainNode({
|
|
25
|
+
traces: collect.traces,
|
|
26
|
+
outPath: input.outPath,
|
|
27
|
+
llm,
|
|
28
|
+
auto: input.auto ?? 'light',
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
optimizedProgram: train.optimizedProgram,
|
|
32
|
+
outPath: train.outPath,
|
|
33
|
+
traceCount: collect.traces.length,
|
|
34
|
+
tracesFile: collect.tracesFile,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=train.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"train.js","sourceRoot":"","sources":["../../../src/training/variant_b/train.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,gDAAgD;AAChD,gEAAgE;AAChE,6CAA6C;AAC7C,wEAAwE;AACxE,0DAA0D;AAC1D,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,0CAA0C;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAkB5C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAA2B;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,gBAAgB,CAAA;IACrD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC;QAChC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,SAAS;QACT,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAA;IACF,MAAM,GAAG,GAAG,SAAS,EAAE,CAAA;IACvB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG;QACH,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;KAC5B,CAAC,CAAA;IACF,OAAO;QACL,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM;QACjC,UAAU,EAAE,OAAO,CAAC,UAAU;KAC/B,CAAA;AACH,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -132,6 +132,18 @@ export interface BuildPlan {
|
|
|
132
132
|
designDirective: string | null;
|
|
133
133
|
/** shadcn preset code for `pnpm dlx shadcn@latest init --preset <code>` */
|
|
134
134
|
presetCode?: string | null;
|
|
135
|
+
/** Vision statement (2-4 sentences) — only populated when a product brief was generated. */
|
|
136
|
+
vision?: string;
|
|
137
|
+
/** Ordered major phases with success criteria. Populated from product brief. */
|
|
138
|
+
milestones?: string[];
|
|
139
|
+
/** Unit/integration test plan items. Populated from product brief. */
|
|
140
|
+
testingPlan?: string[];
|
|
141
|
+
/** End-to-end user-journey coverage items. Populated from product brief. */
|
|
142
|
+
e2ePlan?: string[];
|
|
143
|
+
/** Red-team / audit surface concerns. Populated from product brief. */
|
|
144
|
+
securityConcerns?: string[];
|
|
145
|
+
/** Things the user should clarify. Populated from product brief. */
|
|
146
|
+
openQuestions?: string[];
|
|
135
147
|
}
|
|
136
148
|
export interface BuildHints {
|
|
137
149
|
pages?: string[];
|
|
@@ -205,12 +217,16 @@ export interface StarterPromptPlan {
|
|
|
205
217
|
confidence: Confidence;
|
|
206
218
|
reasons: string[];
|
|
207
219
|
spec: ComposeSpec;
|
|
220
|
+
/** Opaque product brief object attached when planPrompt was called with brief: true. */
|
|
221
|
+
brief?: unknown;
|
|
208
222
|
}
|
|
209
223
|
export interface WorkspacePromptPlan {
|
|
210
224
|
kind: 'workspace';
|
|
211
225
|
confidence: Confidence;
|
|
212
226
|
reasons: string[];
|
|
213
227
|
spec: WorkspaceSpec;
|
|
228
|
+
/** Opaque product brief object attached when planPrompt was called with brief: true. */
|
|
229
|
+
brief?: unknown;
|
|
214
230
|
}
|
|
215
231
|
export type PromptPlan = StarterPromptPlan | WorkspacePromptPlan;
|
|
216
232
|
export interface ComposeComponents {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/starter-foundry",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "Deterministic project scaffold engine for AI coding platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsc",
|
|
40
40
|
"prepublishOnly": "tsc",
|
|
41
|
-
"test": "tsc && tsc -p tsconfig.test.json && node --test dist-tests/*.test.js",
|
|
41
|
+
"test": "tsc && tsc -p tsconfig.test.json && node --test --test-concurrency=1 dist-tests/*.test.js",
|
|
42
42
|
"catalog": "node dist/cli.js catalog",
|
|
43
43
|
"select": "node dist/cli.js select",
|
|
44
44
|
"compose": "node dist/cli.js compose",
|
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
"typescript": "^5.7.0"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
+
"@ax-llm/ax": "^19.0.45",
|
|
68
69
|
"@huggingface/transformers": "^4.0.0"
|
|
70
|
+
},
|
|
71
|
+
"optionalDependencies": {
|
|
72
|
+
"@opentelemetry/api": "^1.9.0"
|
|
69
73
|
}
|
|
70
74
|
}
|