aura-code 0.5.0 → 0.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 +47 -164
- package/dist/agent/affect.d.ts +13 -0
- package/dist/agent/affect.js +34 -0
- package/dist/agent/affect.js.map +1 -0
- package/dist/agent/compactor.d.ts +27 -4
- package/dist/agent/compactor.js +185 -54
- package/dist/agent/compactor.js.map +1 -1
- package/dist/agent/confess.d.ts +35 -0
- package/dist/agent/confess.js +296 -0
- package/dist/agent/confess.js.map +1 -0
- package/dist/agent/domain-expertise.d.ts +22 -0
- package/dist/agent/domain-expertise.js +110 -0
- package/dist/agent/domain-expertise.js.map +1 -0
- package/dist/agent/executive-queue.d.ts +26 -0
- package/dist/agent/executive-queue.js +50 -0
- package/dist/agent/executive-queue.js.map +1 -0
- package/dist/agent/generational-flush.d.ts +28 -0
- package/dist/agent/generational-flush.js +48 -0
- package/dist/agent/generational-flush.js.map +1 -0
- package/dist/agent/loop-profile.d.ts +50 -0
- package/dist/agent/loop-profile.js +88 -0
- package/dist/agent/loop-profile.js.map +1 -0
- package/dist/agent/loop.d.ts +14 -5
- package/dist/agent/loop.js +167 -23
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/memory-consolidate.d.ts +14 -0
- package/dist/agent/memory-consolidate.js +141 -0
- package/dist/agent/memory-consolidate.js.map +1 -0
- package/dist/agent/mixture.d.ts +33 -0
- package/dist/agent/mixture.js +138 -0
- package/dist/agent/mixture.js.map +1 -0
- package/dist/agent/spawner.js +2 -2
- package/dist/agent/spawner.js.map +1 -1
- package/dist/agent/system-prompt.d.ts +1 -1
- package/dist/agent/system-prompt.js +49 -13
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/agent/unified-memory.d.ts +15 -0
- package/dist/agent/unified-memory.js +164 -0
- package/dist/agent/unified-memory.js.map +1 -0
- package/dist/checkpoints/engine.d.ts +44 -0
- package/dist/checkpoints/engine.js +324 -0
- package/dist/checkpoints/engine.js.map +1 -0
- package/dist/cli/command-palette.d.ts +26 -0
- package/dist/cli/command-palette.js +133 -0
- package/dist/cli/command-palette.js.map +1 -0
- package/dist/cli/context-health.d.ts +51 -0
- package/dist/cli/context-health.js +187 -0
- package/dist/cli/context-health.js.map +1 -0
- package/dist/cli/diamond.d.ts +67 -0
- package/dist/cli/diamond.js +222 -12
- package/dist/cli/diamond.js.map +1 -1
- package/dist/cli/dic.d.ts +2 -0
- package/dist/cli/dic.js +106 -0
- package/dist/cli/dic.js.map +1 -0
- package/dist/cli/diff-view.d.ts +18 -0
- package/dist/cli/diff-view.js +114 -0
- package/dist/cli/diff-view.js.map +1 -0
- package/dist/cli/display.d.ts +18 -4
- package/dist/cli/display.js +74 -146
- package/dist/cli/display.js.map +1 -1
- package/dist/cli/help-data.d.ts +7 -0
- package/dist/cli/help-data.js +80 -0
- package/dist/cli/help-data.js.map +1 -0
- package/dist/cli/index.js +1001 -788
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/markdown.d.ts +5 -0
- package/dist/cli/markdown.js +128 -0
- package/dist/cli/markdown.js.map +1 -0
- package/dist/cli/model-select.d.ts +39 -0
- package/dist/cli/model-select.js +65 -0
- package/dist/cli/model-select.js.map +1 -0
- package/dist/cli/tui.d.ts +34 -0
- package/dist/cli/tui.js +1176 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/config/defaults.d.ts +6 -17
- package/dist/config/defaults.js +25 -39
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/project-config.d.ts +2 -6
- package/dist/config/project-config.js +2 -2
- package/dist/config/project-config.js.map +1 -1
- package/dist/doctor/checks.d.ts +18 -0
- package/dist/doctor/checks.js +524 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/index.d.ts +4 -0
- package/dist/doctor/index.js +229 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/repair.d.ts +19 -0
- package/dist/doctor/repair.js +126 -0
- package/dist/doctor/repair.js.map +1 -0
- package/dist/doctor/types.d.ts +38 -0
- package/dist/doctor/types.js +10 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/dream/dream.d.ts +79 -36
- package/dist/dream/dream.js +327 -117
- package/dist/dream/dream.js.map +1 -1
- package/dist/dream/episode.d.ts +17 -0
- package/dist/dream/episode.js +116 -0
- package/dist/dream/episode.js.map +1 -0
- package/dist/dream/okf.d.ts +10 -0
- package/dist/dream/okf.js +280 -0
- package/dist/dream/okf.js.map +1 -0
- package/dist/dream/parser.d.ts +60 -0
- package/dist/dream/parser.js +176 -0
- package/dist/dream/parser.js.map +1 -0
- package/dist/dream/reconcile.d.ts +69 -0
- package/dist/dream/reconcile.js +303 -0
- package/dist/dream/reconcile.js.map +1 -0
- package/dist/kanban/engine.d.ts +26 -0
- package/dist/kanban/engine.js +208 -0
- package/dist/kanban/engine.js.map +1 -0
- package/dist/kanban/types.d.ts +19 -0
- package/dist/kanban/types.js +9 -1
- package/dist/kanban/types.js.map +1 -1
- package/dist/machina/index.d.ts +16 -0
- package/dist/machina/index.js +61 -0
- package/dist/machina/index.js.map +1 -0
- package/dist/machina/render-html.d.ts +2 -0
- package/dist/machina/render-html.js +191 -0
- package/dist/machina/render-html.js.map +1 -0
- package/dist/machina/render-terminal.d.ts +2 -0
- package/dist/machina/render-terminal.js +99 -0
- package/dist/machina/render-terminal.js.map +1 -0
- package/dist/machina/repair.d.ts +23 -0
- package/dist/machina/repair.js +98 -0
- package/dist/machina/repair.js.map +1 -0
- package/dist/machina/spec.d.ts +61 -0
- package/dist/machina/spec.js +124 -0
- package/dist/machina/spec.js.map +1 -0
- package/dist/machina/verify.d.ts +39 -0
- package/dist/machina/verify.js +95 -0
- package/dist/machina/verify.js.map +1 -0
- package/dist/mining/extract.d.ts +34 -0
- package/dist/mining/extract.js +229 -0
- package/dist/mining/extract.js.map +1 -0
- package/dist/mining/refine.d.ts +28 -0
- package/dist/mining/refine.js +256 -0
- package/dist/mining/refine.js.map +1 -0
- package/dist/perception/extractor.js +5 -3
- package/dist/perception/extractor.js.map +1 -1
- package/dist/perception/graph-store.d.ts +0 -11
- package/dist/perception/graph-store.js +0 -33
- package/dist/perception/graph-store.js.map +1 -1
- package/dist/perception/index.d.ts +1 -1
- package/dist/perception/index.js +1 -2
- package/dist/perception/index.js.map +1 -1
- package/dist/plugins/commands.d.ts +38 -0
- package/dist/plugins/commands.js +134 -0
- package/dist/plugins/commands.js.map +1 -0
- package/dist/plugins/frontmatter.d.ts +14 -0
- package/dist/plugins/frontmatter.js +78 -0
- package/dist/plugins/frontmatter.js.map +1 -0
- package/dist/plugins/hooks.d.ts +12 -0
- package/dist/plugins/hooks.js +148 -0
- package/dist/plugins/hooks.js.map +1 -0
- package/dist/plugins/loader.d.ts +7 -0
- package/dist/plugins/loader.js +255 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/market.d.ts +23 -0
- package/dist/plugins/market.js +281 -0
- package/dist/plugins/market.js.map +1 -0
- package/dist/plugins/types.d.ts +90 -0
- package/dist/plugins/types.js +20 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/providers/anthropic-oauth-draft.d.ts +119 -0
- package/dist/providers/anthropic-oauth-draft.js +414 -0
- package/dist/providers/anthropic-oauth-draft.js.map +1 -0
- package/dist/providers/anthropic.d.ts +4 -1
- package/dist/providers/anthropic.js +34 -6
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/factory.d.ts +71 -14
- package/dist/providers/factory.js +205 -124
- package/dist/providers/factory.js.map +1 -1
- package/dist/providers/google.js +8 -21
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/live-models.d.ts +23 -0
- package/dist/providers/live-models.js +145 -0
- package/dist/providers/live-models.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +1 -12
- package/dist/providers/openai-compatible.js +71 -108
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/providers/resilient-factory.js +1 -1
- package/dist/providers/resilient-factory.js.map +1 -1
- package/dist/rem/graph.d.ts +72 -0
- package/dist/rem/graph.js +139 -0
- package/dist/rem/graph.js.map +1 -0
- package/dist/rem/index.d.ts +16 -0
- package/dist/rem/index.js +60 -0
- package/dist/rem/index.js.map +1 -0
- package/dist/rem/render-html.d.ts +2 -0
- package/dist/rem/render-html.js +189 -0
- package/dist/rem/render-html.js.map +1 -0
- package/dist/rem/render-terminal.d.ts +4 -0
- package/dist/rem/render-terminal.js +94 -0
- package/dist/rem/render-terminal.js.map +1 -0
- package/dist/repl/queue.d.ts +22 -0
- package/dist/repl/queue.js +165 -0
- package/dist/repl/queue.js.map +1 -0
- package/dist/repl/side-channel.d.ts +23 -0
- package/dist/repl/side-channel.js +63 -0
- package/dist/repl/side-channel.js.map +1 -0
- package/dist/research/council.d.ts +5 -2
- package/dist/research/council.js +73 -10
- package/dist/research/council.js.map +1 -1
- package/dist/ruby/alternator.d.ts +11 -30
- package/dist/ruby/alternator.js +59 -38
- package/dist/ruby/alternator.js.map +1 -1
- package/dist/ruby/episode-capture.d.ts +0 -10
- package/dist/ruby/episode-capture.js +0 -33
- package/dist/ruby/episode-capture.js.map +1 -1
- package/dist/ruby/types.js +1 -1
- package/dist/ruby/types.js.map +1 -1
- package/dist/safety/path-jail.d.ts +17 -0
- package/dist/safety/path-jail.js +100 -0
- package/dist/safety/path-jail.js.map +1 -0
- package/dist/safety/permissions.d.ts +12 -21
- package/dist/safety/permissions.js +81 -216
- package/dist/safety/permissions.js.map +1 -1
- package/dist/safety/ssrf.d.ts +29 -0
- package/dist/safety/ssrf.js +185 -0
- package/dist/safety/ssrf.js.map +1 -0
- package/dist/server/index.js +64 -10
- package/dist/server/index.js.map +1 -1
- package/dist/setup/first-run.d.ts +0 -24
- package/dist/setup/first-run.js +10 -344
- package/dist/setup/first-run.js.map +1 -1
- package/dist/setup/key-store.d.ts +12 -0
- package/dist/setup/key-store.js +108 -0
- package/dist/setup/key-store.js.map +1 -0
- package/dist/setup/provider-registry.js +31 -18
- package/dist/setup/provider-registry.js.map +1 -1
- package/dist/setup/provider-test.d.ts +7 -0
- package/dist/setup/provider-test.js +73 -10
- package/dist/setup/provider-test.js.map +1 -1
- package/dist/setup/provider-wizard.d.ts +4 -1
- package/dist/setup/provider-wizard.js +92 -26
- package/dist/setup/provider-wizard.js.map +1 -1
- package/dist/setup/xiaomi.d.ts +1 -1
- package/dist/setup/xiaomi.js +3 -3
- package/dist/setup/xiaomi.js.map +1 -1
- package/dist/tools/browser.js +6 -4
- package/dist/tools/browser.js.map +1 -1
- package/dist/tools/clipboard.js +7 -1
- package/dist/tools/clipboard.js.map +1 -1
- package/dist/tools/dictate.d.ts +60 -0
- package/dist/tools/dictate.js +983 -0
- package/dist/tools/dictate.js.map +1 -0
- package/dist/tools/dictate_patched.js +1057 -0
- package/dist/tools/edit-file.js +10 -2
- package/dist/tools/edit-file.js.map +1 -1
- package/dist/tools/gmail-tool.d.ts +5 -1
- package/dist/tools/gmail-tool.js +151 -11
- package/dist/tools/gmail-tool.js.map +1 -1
- package/dist/tools/http-request.js +14 -4
- package/dist/tools/http-request.js.map +1 -1
- package/dist/tools/image-read.js +34 -2
- package/dist/tools/image-read.js.map +1 -1
- package/dist/tools/index.d.ts +16 -1
- package/dist/tools/index.js +59 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp.js +12 -0
- package/dist/tools/mcp.js.map +1 -1
- package/dist/tools/read-file.js +10 -14
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/telegram-audio-policy.d.ts +30 -0
- package/dist/tools/telegram-audio-policy.js +49 -0
- package/dist/tools/telegram-audio-policy.js.map +1 -0
- package/dist/tools/telegram-bot.js +1136 -539
- package/dist/tools/telegram-bot.js.map +1 -1
- package/dist/tools/telegram-voice.d.ts +18 -5
- package/dist/tools/telegram-voice.js +54 -12
- package/dist/tools/telegram-voice.js.map +1 -1
- package/dist/tools/telegram.d.ts +3 -3
- package/dist/tools/telegram.js +5 -84
- package/dist/tools/telegram.js.map +1 -1
- package/dist/tools/tools.d.ts +2 -14
- package/dist/tools/tools.js +79 -144
- package/dist/tools/tools.js.map +1 -1
- package/dist/tools/web-fetch.js +39 -7
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-search.js +2 -3
- package/dist/tools/web-search.js.map +1 -1
- package/dist/util/errors.js +1 -15
- package/dist/util/errors.js.map +1 -1
- package/dist/util/json-repair.d.ts +11 -0
- package/dist/util/json-repair.js +31 -0
- package/dist/util/json-repair.js.map +1 -0
- package/dist/util/rate-limiter.js +2 -8
- package/dist/util/rate-limiter.js.map +1 -1
- package/dist/viz/index.js +793 -792
- package/dist/viz/index.js.map +1 -1
- package/dist/viz/reader.d.ts +33 -0
- package/dist/viz/reader.js +343 -0
- package/dist/viz/reader.js.map +1 -0
- package/package.json +13 -32
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `:machina` — the Abstract Agent Machine (AAM).
|
|
4
|
+
*
|
|
5
|
+
* This module states a formal model of what `aura-code` *is*, independent of
|
|
6
|
+
* which LLM happens to be plugged in, and then checks every structural claim
|
|
7
|
+
* it makes against the real source tree at run time (see verify.ts). A spec
|
|
8
|
+
* that asserts "the main loop is at loop.ts:127" and never re-checks that
|
|
9
|
+
* line drifts silently as the code changes — this one refuses to.
|
|
10
|
+
*
|
|
11
|
+
* ── The model ──────────────────────────────────────────────────────────────
|
|
12
|
+
* AAM is the 5-tuple (S, P, O, δ, s0):
|
|
13
|
+
*
|
|
14
|
+
* S — state space. A state is the full conversation history plus loop
|
|
15
|
+
* counters: s = (history, turns, usage). Every run lives inside S.
|
|
16
|
+
* P — primitives. The finite, fixed set of tool definitions the machine
|
|
17
|
+
* can invoke (read_file, run_command, edit, ...). P is finite and
|
|
18
|
+
* enumerable — this is NOT where unboundedness comes from.
|
|
19
|
+
* O — the oracle. A function history -> {text, tool_calls, stop_reason}.
|
|
20
|
+
* The oracle is the ONLY part of the tuple that is swappable: it can
|
|
21
|
+
* be an LLM, a human, a rule table, or another AAM run recursively.
|
|
22
|
+
* Swapping the oracle does not change S, P, δ, or s0.
|
|
23
|
+
* δ — the transition function. δ(s, o(s)) -> s'. Concretely: take the
|
|
24
|
+
* oracle's output, run it through the safety gate, execute any tool
|
|
25
|
+
* calls against P, fold the results back into history, and check
|
|
26
|
+
* halting conditions.
|
|
27
|
+
* s0 — the initial state: empty history + the user's task as the first
|
|
28
|
+
* message.
|
|
29
|
+
*
|
|
30
|
+
* ── Why this matters, precisely ────────────────────────────────────────────
|
|
31
|
+
* Because δ can simulate a Turing machine's transition function (the oracle
|
|
32
|
+
* can be made to emit "move tape head" tool calls and the primitives can
|
|
33
|
+
* implement a tape as a file), AAM is Turing-complete *in principle*, for
|
|
34
|
+
* an UNBOUNDED machine (infinite turns, infinite context). Turing-completeness
|
|
35
|
+
* is the ceiling for computability — a quantum computer does not raise this
|
|
36
|
+
* ceiling; it changes the *complexity* of specific problems (factoring,
|
|
37
|
+
* search), not which problems are solvable at all. So "make the oracle
|
|
38
|
+
* quantum" would be a speed upgrade to O, not a power upgrade to the tuple.
|
|
39
|
+
*
|
|
40
|
+
* Turing-completeness has a cost the spec must not hide: the Halting Problem
|
|
41
|
+
* is undecidable for an unbounded AAM — there is no general procedure that
|
|
42
|
+
* decides, for an arbitrary task, whether the loop ever stops. This is
|
|
43
|
+
* exactly why real aura-code is NOT the unbounded machine: maxTurns and the
|
|
44
|
+
* context compactor are deliberate, finite approximations that trade a
|
|
45
|
+
* sliver of theoretical power for guaranteed termination. The unbounded
|
|
46
|
+
* machine is elegant on paper and undecidable in practice; the bounded
|
|
47
|
+
* machine is what you can actually run.
|
|
48
|
+
*/
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.AAM_LIMITS_NOTE = exports.AAM_PREAMBLE = exports.AAM_CLAIMS = void 0;
|
|
51
|
+
exports.AAM_CLAIMS = [
|
|
52
|
+
{
|
|
53
|
+
id: 'main-loop',
|
|
54
|
+
component: 'delta',
|
|
55
|
+
description: 'The main transition loop — one iteration is one application of δ. The turn budget is checked inside the loop so it can widen once when work is still in progress.',
|
|
56
|
+
file: 'src/agent/loop.ts',
|
|
57
|
+
line: 172,
|
|
58
|
+
mustContain: 'while (true)',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'oracle-call',
|
|
62
|
+
component: 'O',
|
|
63
|
+
description: "The oracle invocation — O(history) -> stream of {text, tool_calls, stop_reason}.",
|
|
64
|
+
file: 'src/agent/loop.ts',
|
|
65
|
+
line: 235,
|
|
66
|
+
mustContain: 'provider.stream(',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'safety-gate',
|
|
70
|
+
component: 'delta',
|
|
71
|
+
description: 'The safety gate inside δ — tool calls are checked against permissions before primitives execute.',
|
|
72
|
+
file: 'src/agent/loop.ts',
|
|
73
|
+
line: 349,
|
|
74
|
+
mustContain: 'permissions.check(',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'compaction-threshold',
|
|
78
|
+
component: 'limit',
|
|
79
|
+
description: 'The state-space pressure-relief valve: history is compacted on a generational ladder (55%, then 70%, then 85% of the context window), keeping S finite in practice.',
|
|
80
|
+
file: 'src/agent/compactor.ts',
|
|
81
|
+
line: 13,
|
|
82
|
+
mustContain: 'LADDER = [0.55, 0.70, 0.85]',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'compaction-check',
|
|
86
|
+
component: 'limit',
|
|
87
|
+
description: 'The actual threshold comparison that triggers compaction.',
|
|
88
|
+
file: 'src/agent/compactor.ts',
|
|
89
|
+
line: 227,
|
|
90
|
+
mustContain: 'if (totalTokens < threshold) return false;',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'max-turns',
|
|
94
|
+
component: 'limit',
|
|
95
|
+
description: 'T_max — the halting bound that makes the REAL machine decidable (150 turns by default, widening at most once for in-progress work), unlike the unbounded theoretical AAM.',
|
|
96
|
+
file: 'src/config/defaults.ts',
|
|
97
|
+
line: 10,
|
|
98
|
+
mustContain: 'maxTurns: 150',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: 'primitives',
|
|
102
|
+
component: 'P',
|
|
103
|
+
description: 'P — the finite, enumerable set of tool primitives the machine can invoke.',
|
|
104
|
+
file: 'src/tools/index.ts',
|
|
105
|
+
line: 30,
|
|
106
|
+
mustContain: 'export const TOOL_DEFINITIONS',
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
exports.AAM_PREAMBLE = 'Aura is not "an LLM with a loop around it." It is an Abstract Agent Machine: ' +
|
|
110
|
+
'a 5-tuple (S, P, O, δ, s0) whose computational power comes from its structure ' +
|
|
111
|
+
'— state space, primitives, transition function — not from which oracle (LLM, ' +
|
|
112
|
+
'human, rule table) happens to be plugged into O. Swap the oracle and the ' +
|
|
113
|
+
'machine is unchanged. This is what makes Aura provider-agnostic by ' +
|
|
114
|
+
'construction, not by convention.';
|
|
115
|
+
exports.AAM_LIMITS_NOTE = 'The UNBOUNDED version of this machine (infinite turns, infinite context) is ' +
|
|
116
|
+
'Turing-complete, which means the Halting Problem is undecidable for it: no ' +
|
|
117
|
+
'general test can say whether an arbitrary task ever finishes. Real aura-code ' +
|
|
118
|
+
'is deliberately NOT that machine — maxTurns and the context compactor below ' +
|
|
119
|
+
'are the finite bounds that buy guaranteed termination at the cost of some ' +
|
|
120
|
+
'theoretical power. A quantum oracle would not restore that power: ' +
|
|
121
|
+
'Turing-completeness is already the ceiling for what is computable at all; ' +
|
|
122
|
+
'quantum computation changes the cost of solving certain problems, not which ' +
|
|
123
|
+
'problems are solvable.';
|
|
124
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/machina/spec.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;;;AAcU,QAAA,UAAU,GAAsB;IAC3C;QACE,EAAE,EAAE,WAAW;QACf,SAAS,EAAE,OAAO;QAClB,WAAW,EAAE,mKAAmK;QAChL,IAAI,EAAE,mBAAmB;QACzB,IAAI,EAAE,GAAG;QACT,WAAW,EAAE,cAAc;KAC5B;IACD;QACE,EAAE,EAAE,aAAa;QACjB,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,kFAAkF;QAC/F,IAAI,EAAE,mBAAmB;QACzB,IAAI,EAAE,GAAG;QACT,WAAW,EAAE,kBAAkB;KAChC;IACD;QACE,EAAE,EAAE,aAAa;QACjB,SAAS,EAAE,OAAO;QAClB,WAAW,EAAE,kGAAkG;QAC/G,IAAI,EAAE,mBAAmB;QACzB,IAAI,EAAE,GAAG;QACT,WAAW,EAAE,oBAAoB;KAClC;IACD;QACE,EAAE,EAAE,sBAAsB;QAC1B,SAAS,EAAE,OAAO;QAClB,WAAW,EAAE,qKAAqK;QAClL,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,EAAE;QACR,WAAW,EAAE,6BAA6B;KAC3C;IACD;QACE,EAAE,EAAE,kBAAkB;QACtB,SAAS,EAAE,OAAO;QAClB,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,GAAG;QACT,WAAW,EAAE,4CAA4C;KAC1D;IACD;QACE,EAAE,EAAE,WAAW;QACf,SAAS,EAAE,OAAO;QAClB,WAAW,EAAE,2KAA2K;QACxL,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,EAAE;QACR,WAAW,EAAE,eAAe;KAC7B;IACD;QACE,EAAE,EAAE,YAAY;QAChB,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,2EAA2E;QACxF,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,EAAE;QACR,WAAW,EAAE,+BAA+B;KAC7C;CACF,CAAC;AAEW,QAAA,YAAY,GACvB,+EAA+E;IAC/E,gFAAgF;IAChF,+EAA+E;IAC/E,2EAA2E;IAC3E,qEAAqE;IACrE,kCAAkC,CAAC;AAExB,QAAA,eAAe,GAC1B,8EAA8E;IAC9E,6EAA6E;IAC7E,+EAA+E;IAC/E,8EAA8E;IAC9E,4EAA4E;IAC5E,oEAAoE;IACpE,4EAA4E;IAC5E,8EAA8E;IAC9E,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type VerifiableClaim } from './spec.js';
|
|
2
|
+
export interface ClaimResult extends VerifiableClaim {
|
|
3
|
+
/**
|
|
4
|
+
* verified — mustContain found at the recorded line (exact anchor).
|
|
5
|
+
* drifted — mustContain found elsewhere in the file: the claim still
|
|
6
|
+
* HOLDS, only its line anchor is stale (see foundLine). This is
|
|
7
|
+
* a passing state — pure line churn is noise, not signal.
|
|
8
|
+
* missing — mustContain appears nowhere in the file (or the file is
|
|
9
|
+
* unreadable): the claim is genuinely false. The only failure.
|
|
10
|
+
*/
|
|
11
|
+
status: 'verified' | 'drifted' | 'missing';
|
|
12
|
+
/** The actual line content found at the recorded line, if the file exists. */
|
|
13
|
+
actualLine?: string;
|
|
14
|
+
/** Where mustContain actually lives now (1-indexed) — set when drifted. */
|
|
15
|
+
foundLine?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the aura-code installation's own root directory, the same way
|
|
19
|
+
* telegram-bot.ts locates its repo for systemd unit generation. From a
|
|
20
|
+
* compiled module at dist/machina/verify.js, '../..' lands at the repo root
|
|
21
|
+
* (dist/machina -> dist -> root). This is intentionally independent of
|
|
22
|
+
* process.cwd(), since :machina describes aura-code's own machinery, not
|
|
23
|
+
* whatever project the user happens to be running it inside.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveAuraRepoRoot(): string;
|
|
26
|
+
export interface VerificationReport {
|
|
27
|
+
results: ClaimResult[];
|
|
28
|
+
verifiedCount: number;
|
|
29
|
+
/** Claims that hold but whose line anchor is stale — passing, needs re-anchoring (see repair.ts). */
|
|
30
|
+
drifted: ClaimResult[];
|
|
31
|
+
/** Claims whose content is genuinely gone — the only real failures. */
|
|
32
|
+
missing: ClaimResult[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verify every structural claim the spec makes. `repoRoot` should be the
|
|
36
|
+
* aura-code installation's own source root — pass `__dirname`-derived paths
|
|
37
|
+
* from the CLI entry point, not the user's project root.
|
|
38
|
+
*/
|
|
39
|
+
export declare function verifyAamClaims(repoRoot: string): VerificationReport;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveAuraRepoRoot = resolveAuraRepoRoot;
|
|
37
|
+
exports.verifyAamClaims = verifyAamClaims;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const spec_js_1 = require("./spec.js");
|
|
41
|
+
/**
|
|
42
|
+
* Check a single claim against the real file on disk. `repoRoot` is the
|
|
43
|
+
* aura-code repository root (NOT the user's current project — the AAM
|
|
44
|
+
* describes aura-code's own machinery, regardless of what project it's
|
|
45
|
+
* currently being run inside).
|
|
46
|
+
*
|
|
47
|
+
* The recorded line number is a lookup hint, not the pass/fail condition:
|
|
48
|
+
* whether the claim is TRUE depends only on the content existing in the file.
|
|
49
|
+
*/
|
|
50
|
+
function verifyClaim(repoRoot, claim) {
|
|
51
|
+
const filePath = path.join(repoRoot, claim.file);
|
|
52
|
+
let lines;
|
|
53
|
+
try {
|
|
54
|
+
lines = fs.readFileSync(filePath, 'utf8').split('\n');
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return { ...claim, status: 'missing' };
|
|
58
|
+
}
|
|
59
|
+
const actual = lines[claim.line - 1] ?? '';
|
|
60
|
+
if (actual.includes(claim.mustContain)) {
|
|
61
|
+
return { ...claim, status: 'verified', actualLine: actual.trim() };
|
|
62
|
+
}
|
|
63
|
+
// Anchor miss — search the whole file before declaring the claim false.
|
|
64
|
+
const foundIdx = lines.findIndex(l => l.includes(claim.mustContain));
|
|
65
|
+
if (foundIdx !== -1) {
|
|
66
|
+
return { ...claim, status: 'drifted', actualLine: actual.trim(), foundLine: foundIdx + 1 };
|
|
67
|
+
}
|
|
68
|
+
return { ...claim, status: 'missing', actualLine: actual.trim() };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Resolve the aura-code installation's own root directory, the same way
|
|
72
|
+
* telegram-bot.ts locates its repo for systemd unit generation. From a
|
|
73
|
+
* compiled module at dist/machina/verify.js, '../..' lands at the repo root
|
|
74
|
+
* (dist/machina -> dist -> root). This is intentionally independent of
|
|
75
|
+
* process.cwd(), since :machina describes aura-code's own machinery, not
|
|
76
|
+
* whatever project the user happens to be running it inside.
|
|
77
|
+
*/
|
|
78
|
+
function resolveAuraRepoRoot() {
|
|
79
|
+
return path.resolve(__dirname, '../..');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Verify every structural claim the spec makes. `repoRoot` should be the
|
|
83
|
+
* aura-code installation's own source root — pass `__dirname`-derived paths
|
|
84
|
+
* from the CLI entry point, not the user's project root.
|
|
85
|
+
*/
|
|
86
|
+
function verifyAamClaims(repoRoot) {
|
|
87
|
+
const results = spec_js_1.AAM_CLAIMS.map(c => verifyClaim(repoRoot, c));
|
|
88
|
+
return {
|
|
89
|
+
results,
|
|
90
|
+
verifiedCount: results.filter(r => r.status === 'verified').length,
|
|
91
|
+
drifted: results.filter(r => r.status === 'drifted'),
|
|
92
|
+
missing: results.filter(r => r.status === 'missing'),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/machina/verify.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,kDAEC;AAiBD,0CAQC;AApFD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAA6D;AAkB7D;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,QAAgB,EAAE,KAAsB;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACzC,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IACrE,CAAC;IACD,wEAAwE;IACxE,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IACrE,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,GAAG,CAAC,EAAE,CAAC;IAC7F,CAAC;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,mBAAmB;IACjC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAYD;;;;GAIG;AACH,SAAgB,eAAe,CAAC,QAAgB;IAC9C,MAAM,OAAO,GAAG,oBAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO;QACL,OAAO;QACP,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,MAAM;QAClE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;QACpD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;KACrD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { TaskCategory } from '../ruby/types.js';
|
|
2
|
+
export interface MinedConcept {
|
|
3
|
+
/** Short slug-like identifier for the concept (e.g. "verification_before_completion"). */
|
|
4
|
+
concept: string;
|
|
5
|
+
/** Category this concept was mined from. */
|
|
6
|
+
category: TaskCategory;
|
|
7
|
+
/** Representative example task strings from the cluster (max 5, shortest first). */
|
|
8
|
+
examples: string[];
|
|
9
|
+
/** Number of episodes that contributed to this concept. */
|
|
10
|
+
frequency: number;
|
|
11
|
+
/** Mechanical confidence: cluster cohesion combined with cluster size relative to total. */
|
|
12
|
+
confidence: number;
|
|
13
|
+
/** Depth at which this concept was extracted (1, 2, or 3). */
|
|
14
|
+
depth: number;
|
|
15
|
+
/** The shared keywords that define this cluster. */
|
|
16
|
+
keywords: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface MiningResult {
|
|
19
|
+
concepts: MinedConcept[];
|
|
20
|
+
episodeCount: number;
|
|
21
|
+
/** Episodes that didn't cluster into anything meaningful — too rare or too unique. */
|
|
22
|
+
unclustered: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run Baby Ruby: mine episodes for structural patterns without any LLM call.
|
|
26
|
+
*
|
|
27
|
+
* Pass 1: group by taskCategory (free, already on every episode).
|
|
28
|
+
* Pass 2-3: within each category, recursively split by keyword overlap
|
|
29
|
+
* until no meaningful further split exists or MAX_DEPTH is hit.
|
|
30
|
+
*
|
|
31
|
+
* Returns a flat list of MinedConcept — Papa Ruby (future) will read these
|
|
32
|
+
* and turn the most useful ones into actual training/instruction data.
|
|
33
|
+
*/
|
|
34
|
+
export declare function mineExperience(projectRoot: string): Promise<MiningResult>;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mineExperience = mineExperience;
|
|
4
|
+
const episode_capture_js_1 = require("../ruby/episode-capture.js");
|
|
5
|
+
/**
|
|
6
|
+
* Baby Ruby — experience mining, not learning.
|
|
7
|
+
*
|
|
8
|
+
* Finds structure in raw episode data using pure statistics: clustering,
|
|
9
|
+
* frequency counts, keyword overlap. NO LLM calls. This is deliberate:
|
|
10
|
+
* Baby Ruby's job is to be reliable, boring infrastructure — the kind that
|
|
11
|
+
* doesn't hallucinate, doesn't cost tokens, and produces the same output
|
|
12
|
+
* given the same input every time.
|
|
13
|
+
*
|
|
14
|
+
* This is the "observation" stage of a three-stage cognitive pipeline:
|
|
15
|
+
*
|
|
16
|
+
* episodes (raw experience)
|
|
17
|
+
* -> Baby Ruby (this file) — no LLM, finds structure
|
|
18
|
+
* -> concepts (this file's output)
|
|
19
|
+
* -> Papa Ruby (future) — local LLM, reasons about concepts
|
|
20
|
+
* -> training data / refined knowledge
|
|
21
|
+
*
|
|
22
|
+
* Baby Ruby does NOT produce instruction/output training pairs. That is
|
|
23
|
+
* explicitly Papa Ruby's job, on top of Baby Ruby's structure. Keeping this
|
|
24
|
+
* separation means Baby Ruby never needs a model, a provider, an API key,
|
|
25
|
+
* or a network call — it's pure, fast, and always available.
|
|
26
|
+
*
|
|
27
|
+
* Three-pass recursive clustering:
|
|
28
|
+
* Pass 1 — broad clusters by taskCategory (research/implementation/
|
|
29
|
+
* review/refactor/other). This is free — the category already
|
|
30
|
+
* exists on every episode.
|
|
31
|
+
* Pass 2 — sub-clusters within each category by keyword overlap (shared
|
|
32
|
+
* significant words in task text, e.g. "auth", "type", "test").
|
|
33
|
+
* Pass 3 — extract stable concepts from sub-clusters that meet a minimum
|
|
34
|
+
* size and produce a confidence score.
|
|
35
|
+
*
|
|
36
|
+
* Termination condition (real, not infinite recursion):
|
|
37
|
+
* Recursion stops when a sub-cluster pass finds no split that produces
|
|
38
|
+
* two groups each above MIN_CLUSTER_SIZE, OR when MAX_DEPTH is reached.
|
|
39
|
+
* This is a depth-bounded, size-bounded recursion — it always halts.
|
|
40
|
+
*/
|
|
41
|
+
const MIN_CLUSTER_SIZE = 3;
|
|
42
|
+
const MAX_DEPTH = 3;
|
|
43
|
+
const STOPWORDS = new Set([
|
|
44
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'in', 'on', 'at', 'to', 'for',
|
|
45
|
+
'of', 'and', 'or', 'but', 'this', 'that', 'with', 'it', 'as', 'be', 'by',
|
|
46
|
+
'from', 'has', 'have', 'had', 'do', 'does', 'did', 'not', 'no', 'so', 'if',
|
|
47
|
+
'then', 'there', 'here', 'what', 'when', 'where', 'how', 'why', 'which',
|
|
48
|
+
'who', 'will', 'would', 'can', 'could', 'should', 'i', 'you', 'we', 'they',
|
|
49
|
+
'my', 'your', 'our', 'their', 'me', 'us', 'them',
|
|
50
|
+
]);
|
|
51
|
+
/** Extract significant (non-stopword, length > 2) lowercase words from task text. */
|
|
52
|
+
function significantWords(task) {
|
|
53
|
+
return task
|
|
54
|
+
.toLowerCase()
|
|
55
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
56
|
+
.split(/\s+/)
|
|
57
|
+
.filter(w => w.length > 2 && !STOPWORDS.has(w));
|
|
58
|
+
}
|
|
59
|
+
/** Jaccard-style overlap between two word sets, in [0, 1]. */
|
|
60
|
+
function overlap(a, b) {
|
|
61
|
+
if (a.size === 0 || b.size === 0)
|
|
62
|
+
return 0;
|
|
63
|
+
let shared = 0;
|
|
64
|
+
for (const w of a)
|
|
65
|
+
if (b.has(w))
|
|
66
|
+
shared++;
|
|
67
|
+
const union = a.size + b.size - shared;
|
|
68
|
+
return union === 0 ? 0 : shared / union;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Group episodes by shared keywords using a simple greedy clustering pass.
|
|
72
|
+
* Not k-means, not embeddings — deliberately simple, deterministic, fast.
|
|
73
|
+
* Each episode joins the first existing cluster it overlaps with above
|
|
74
|
+
* OVERLAP_THRESHOLD; otherwise it starts a new cluster.
|
|
75
|
+
*/
|
|
76
|
+
const OVERLAP_THRESHOLD = 0.15;
|
|
77
|
+
function clusterByKeywords(episodes) {
|
|
78
|
+
const wordSets = episodes.map(e => new Set(significantWords(e.task)));
|
|
79
|
+
const clusters = [];
|
|
80
|
+
for (let i = 0; i < episodes.length; i++) {
|
|
81
|
+
const ep = episodes[i];
|
|
82
|
+
const words = wordSets[i];
|
|
83
|
+
let placed = false;
|
|
84
|
+
for (const cluster of clusters) {
|
|
85
|
+
// Compare against the cluster's combined word set (union of members so far).
|
|
86
|
+
const clusterWords = new Set();
|
|
87
|
+
for (const ws of cluster.wordSets)
|
|
88
|
+
for (const w of ws)
|
|
89
|
+
clusterWords.add(w);
|
|
90
|
+
if (overlap(words, clusterWords) >= OVERLAP_THRESHOLD) {
|
|
91
|
+
cluster.episodes.push(ep);
|
|
92
|
+
cluster.wordSets.push(words);
|
|
93
|
+
placed = true;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!placed) {
|
|
98
|
+
clusters.push({ episodes: [ep], wordSets: [words] });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return clusters
|
|
102
|
+
.filter(c => c.episodes.length >= MIN_CLUSTER_SIZE)
|
|
103
|
+
.map(c => {
|
|
104
|
+
// Find the words shared by the most members — the cluster's defining keywords.
|
|
105
|
+
const counts = new Map();
|
|
106
|
+
for (const ws of c.wordSets)
|
|
107
|
+
for (const w of ws)
|
|
108
|
+
counts.set(w, (counts.get(w) ?? 0) + 1);
|
|
109
|
+
const keywords = [...counts.entries()]
|
|
110
|
+
.filter(([, count]) => count >= Math.max(2, Math.ceil(c.episodes.length * 0.4)))
|
|
111
|
+
.sort((a, b) => b[1] - a[1])
|
|
112
|
+
.slice(0, 6)
|
|
113
|
+
.map(([w]) => w);
|
|
114
|
+
return { episodes: c.episodes, keywords, depth: 0 };
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Compute keywords for a leaf node that won't be split further — either
|
|
119
|
+
* because it hit MAX_DEPTH, or because it's too small to split into two
|
|
120
|
+
* valid sub-clusters. Without this, small categories (3-5 episodes) would
|
|
121
|
+
* surface as a "concept" with empty keywords, which is meaningless: a bare
|
|
122
|
+
* category label isn't a concept on its own.
|
|
123
|
+
*/
|
|
124
|
+
function leafKeywords(episodes) {
|
|
125
|
+
const counts = new Map();
|
|
126
|
+
for (const ep of episodes) {
|
|
127
|
+
for (const w of new Set(significantWords(ep.task))) {
|
|
128
|
+
counts.set(w, (counts.get(w) ?? 0) + 1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return [...counts.entries()]
|
|
132
|
+
.filter(([, count]) => count >= Math.max(2, Math.ceil(episodes.length * 0.4)))
|
|
133
|
+
.sort((a, b) => b[1] - a[1])
|
|
134
|
+
.slice(0, 6)
|
|
135
|
+
.map(([w]) => w);
|
|
136
|
+
}
|
|
137
|
+
function recursiveSplit(node) {
|
|
138
|
+
if (node.depth >= MAX_DEPTH) {
|
|
139
|
+
return [{ ...node, keywords: node.keywords.length > 0 ? node.keywords : leafKeywords(node.episodes) }];
|
|
140
|
+
}
|
|
141
|
+
if (node.episodes.length < MIN_CLUSTER_SIZE * 2) {
|
|
142
|
+
// Too small to split into two valid clusters — still compute keywords
|
|
143
|
+
// so this leaf carries real structure instead of an empty label.
|
|
144
|
+
return [{ ...node, keywords: node.keywords.length > 0 ? node.keywords : leafKeywords(node.episodes) }];
|
|
145
|
+
}
|
|
146
|
+
const subClusters = clusterByKeywords(node.episodes);
|
|
147
|
+
// No real split: either zero sub-clusters formed, or exactly one sub-cluster
|
|
148
|
+
// that contains essentially all the same episodes (no new structure found).
|
|
149
|
+
const isRealSplit = subClusters.length >= 2 ||
|
|
150
|
+
(subClusters.length === 1 && subClusters[0].episodes.length < node.episodes.length);
|
|
151
|
+
if (!isRealSplit) {
|
|
152
|
+
return [{ ...node, keywords: node.keywords.length > 0 ? node.keywords : leafKeywords(node.episodes) }];
|
|
153
|
+
}
|
|
154
|
+
const deepened = subClusters.map(c => ({ ...c, depth: node.depth + 1 }));
|
|
155
|
+
return deepened.flatMap(recursiveSplit);
|
|
156
|
+
}
|
|
157
|
+
/** Mechanical confidence: cluster cohesion (size) weighted against the total episode pool. */
|
|
158
|
+
function computeConfidence(clusterSize, totalEpisodes, depth) {
|
|
159
|
+
const sizeRatio = totalEpisodes > 0 ? clusterSize / totalEpisodes : 0;
|
|
160
|
+
// Deeper clusters are more specific — slightly boost confidence for depth,
|
|
161
|
+
// since a stable pattern surviving 2-3 splits is more meaningful than a
|
|
162
|
+
// broad depth-1 cluster that's just "all coding tasks."
|
|
163
|
+
const depthBonus = Math.min(depth * 0.05, 0.15);
|
|
164
|
+
const raw = Math.min(1, sizeRatio * 3 + depthBonus); // *3 so e.g. 17/100 episodes -> 0.51+bonus, not 0.17
|
|
165
|
+
return Math.round(raw * 100) / 100;
|
|
166
|
+
}
|
|
167
|
+
function slugifyConcept(keywords, category) {
|
|
168
|
+
const base = keywords.length > 0 ? keywords.slice(0, 3).join('_') : category;
|
|
169
|
+
return base.toLowerCase().replace(/[^a-z0-9_]/g, '');
|
|
170
|
+
}
|
|
171
|
+
function leafToConcept(leaf, category, totalEpisodes) {
|
|
172
|
+
const sorted = [...leaf.episodes].sort((a, b) => a.task.length - b.task.length);
|
|
173
|
+
const examples = sorted.slice(0, 5).map(e => e.task.slice(0, 140));
|
|
174
|
+
return {
|
|
175
|
+
concept: slugifyConcept(leaf.keywords, category),
|
|
176
|
+
category,
|
|
177
|
+
examples,
|
|
178
|
+
frequency: leaf.episodes.length,
|
|
179
|
+
confidence: computeConfidence(leaf.episodes.length, totalEpisodes, leaf.depth),
|
|
180
|
+
depth: Math.max(1, leaf.depth),
|
|
181
|
+
keywords: leaf.keywords,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Run Baby Ruby: mine episodes for structural patterns without any LLM call.
|
|
186
|
+
*
|
|
187
|
+
* Pass 1: group by taskCategory (free, already on every episode).
|
|
188
|
+
* Pass 2-3: within each category, recursively split by keyword overlap
|
|
189
|
+
* until no meaningful further split exists or MAX_DEPTH is hit.
|
|
190
|
+
*
|
|
191
|
+
* Returns a flat list of MinedConcept — Papa Ruby (future) will read these
|
|
192
|
+
* and turn the most useful ones into actual training/instruction data.
|
|
193
|
+
*/
|
|
194
|
+
async function mineExperience(projectRoot) {
|
|
195
|
+
const episodes = await (0, episode_capture_js_1.loadEpisodes)(projectRoot);
|
|
196
|
+
if (episodes.length === 0) {
|
|
197
|
+
return { concepts: [], episodeCount: 0, unclustered: 0 };
|
|
198
|
+
}
|
|
199
|
+
// Pass 1: broad clusters by category — always free, no clustering needed.
|
|
200
|
+
const byCategory = new Map();
|
|
201
|
+
for (const ep of episodes) {
|
|
202
|
+
const list = byCategory.get(ep.taskCategory) ?? [];
|
|
203
|
+
list.push(ep);
|
|
204
|
+
byCategory.set(ep.taskCategory, list);
|
|
205
|
+
}
|
|
206
|
+
const allConcepts = [];
|
|
207
|
+
let clusteredCount = 0;
|
|
208
|
+
for (const [category, categoryEpisodes] of byCategory) {
|
|
209
|
+
if (categoryEpisodes.length < MIN_CLUSTER_SIZE)
|
|
210
|
+
continue; // too rare to mine
|
|
211
|
+
// Pass 2-3: recursive keyword splitting within this category.
|
|
212
|
+
const initialNode = { episodes: categoryEpisodes, keywords: [], depth: 0 };
|
|
213
|
+
const leaves = recursiveSplit(initialNode);
|
|
214
|
+
for (const leaf of leaves) {
|
|
215
|
+
if (leaf.episodes.length < MIN_CLUSTER_SIZE)
|
|
216
|
+
continue;
|
|
217
|
+
allConcepts.push(leafToConcept(leaf, category, episodes.length));
|
|
218
|
+
clusteredCount += leaf.episodes.length;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Sort by confidence descending — most stable/significant concepts first.
|
|
222
|
+
allConcepts.sort((a, b) => b.confidence - a.confidence);
|
|
223
|
+
return {
|
|
224
|
+
concepts: allConcepts,
|
|
225
|
+
episodeCount: episodes.length,
|
|
226
|
+
unclustered: episodes.length - clusteredCount,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/mining/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TrainingExample, RubyConfig } from '../ruby/types.js';
|
|
2
|
+
import type { MinedConcept } from './extract.js';
|
|
3
|
+
export interface RefinementResult {
|
|
4
|
+
/** Concepts that were judged actionable and written as training examples. */
|
|
5
|
+
accepted: TrainingExample[];
|
|
6
|
+
/** Concepts judged noise (or the model failed) — not written. */
|
|
7
|
+
rejected: number;
|
|
8
|
+
/** Concepts skipped before even calling the model (below confidence/frequency gate). */
|
|
9
|
+
skipped: number;
|
|
10
|
+
/** Path to the .jsonl file new examples were appended to, if any were written. */
|
|
11
|
+
outputPath?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run Papa Ruby over a set of Baby Ruby's concepts.
|
|
15
|
+
*
|
|
16
|
+
* Gates BEFORE calling the model: concepts below MIN_CONFIDENCE_TO_REFINE
|
|
17
|
+
* or MIN_FREQUENCY_TO_REFINE are skipped entirely (not worth a model call
|
|
18
|
+
* to judge — Baby Ruby's own confidence already says this is weak signal).
|
|
19
|
+
*
|
|
20
|
+
* Accepted training examples are appended to training-data/<date>.jsonl.
|
|
21
|
+
* Never overwrites — each run appends, since this mirrors an append-only
|
|
22
|
+
* event log philosophy, same as dreams/.
|
|
23
|
+
*/
|
|
24
|
+
export declare function refineConcepts(opts: {
|
|
25
|
+
projectRoot: string;
|
|
26
|
+
concepts: MinedConcept[];
|
|
27
|
+
rubyConfig?: RubyConfig;
|
|
28
|
+
}): Promise<RefinementResult>;
|