@giamme/forge 0.0.0-stage → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +181 -0
- package/LICENSE +21 -0
- package/README.md +1854 -2
- package/SKILL.md +122 -0
- package/VERSION +1 -0
- package/forge +74 -0
- package/package.json +26 -4
- package/references/dataset.md +329 -0
- package/references/decompose.md +667 -0
- package/references/fractal-dashboard.md +21 -0
- package/references/fractal.md +307 -0
- package/references/harnesses.md +353 -0
- package/references/jev.md +865 -0
- package/references/memory.md +228 -0
- package/references/planning.md +42 -0
- package/references/ripwire.md +47 -0
- package/references/runtime.md +64 -0
- package/references/solo.md +113 -0
- package/references/ui.md +112 -0
- package/registry.tsv +81 -0
- package/scripts/forge-artifact.sh +78 -0
- package/scripts/forge-contract.py +430 -0
- package/scripts/forge-dataset.py +6 -0
- package/scripts/forge-dispatch.sh +665 -0
- package/scripts/forge-fail-first.py +195 -0
- package/scripts/forge-fractal-dispatch.sh +4 -0
- package/scripts/forge-fractal-options.sh +54 -0
- package/scripts/forge-fractal.py +6 -0
- package/scripts/forge-guard.py +266 -0
- package/scripts/forge-install-fractal.sh +4 -0
- package/scripts/forge-install-ripwire.sh +52 -0
- package/scripts/forge-install.sh +135 -0
- package/scripts/forge-jev-options.sh +259 -0
- package/scripts/forge-jev.py +6 -0
- package/scripts/forge-lib-plans.sh +785 -0
- package/scripts/forge-lib-review.sh +494 -0
- package/scripts/forge-lib-task.sh +302 -0
- package/scripts/forge-lib-verify.sh +30 -0
- package/scripts/forge-memory.sh +575 -0
- package/scripts/forge-metrics.sh +39 -0
- package/scripts/forge-parallel-options.sh +76 -0
- package/scripts/forge-parallel.sh +1717 -0
- package/scripts/forge-plan-check.py +118 -0
- package/scripts/forge-prompt.py +45 -0
- package/scripts/forge-ripwire.py +136 -0
- package/scripts/forge-route.py +344 -0
- package/scripts/forge-runtime.py +533 -0
- package/scripts/forge-schedule.py +312 -0
- package/scripts/forge-shadow.py +305 -0
- package/scripts/forge-solo.sh +347 -0
- package/scripts/forge-ui-options.sh +42 -0
- package/scripts/forge-ui.py +435 -0
- package/scripts/forge-update.sh +71 -0
- package/scripts/forge-verify-coverage.py +956 -0
- package/scripts/forge-version.py +198 -0
- package/scripts/forge_dataset/__init__.py +439 -0
- package/scripts/forge_dataset/capture.py +330 -0
- package/scripts/forge_dataset/checks.py +109 -0
- package/scripts/forge_dataset/cli.py +233 -0
- package/scripts/forge_dataset/export.py +1009 -0
- package/scripts/forge_dataset/harvest.py +716 -0
- package/scripts/forge_dataset/importer.py +412 -0
- package/scripts/forge_dataset/outcomes.py +275 -0
- package/scripts/forge_dataset/routing.py +278 -0
- package/scripts/forge_fractal/__init__.py +83 -0
- package/scripts/forge_fractal/bridge.py +46 -0
- package/scripts/forge_fractal/cli.py +202 -0
- package/scripts/forge_fractal/dashboard.css +138 -0
- package/scripts/forge_fractal/dashboard.html +41 -0
- package/scripts/forge_fractal/dashboard.js +687 -0
- package/scripts/forge_fractal/decomposition.py +262 -0
- package/scripts/forge_fractal/execution.py +659 -0
- package/scripts/forge_fractal/inspection.py +261 -0
- package/scripts/forge_fractal/install.py +158 -0
- package/scripts/forge_fractal/invocation.py +94 -0
- package/scripts/forge_fractal/pipeline.py +124 -0
- package/scripts/forge_fractal/selection.py +179 -0
- package/scripts/forge_jev/__init__.py +376 -0
- package/scripts/forge_jev/backtest.py +322 -0
- package/scripts/forge_jev/cli.py +980 -0
- package/scripts/forge_jev/client.py +418 -0
- package/scripts/forge_jev/corpus.py +156 -0
- package/scripts/forge_jev/coupling.py +244 -0
- package/scripts/forge_jev/features.py +24 -0
- package/scripts/forge_jev/gates.py +100 -0
- package/scripts/forge_jev/memory.py +163 -0
- package/scripts/forge_jev/outcome.py +49 -0
- package/scripts/forge_jev/predict.py +204 -0
- package/scripts/forge_jev/questions.py +661 -0
- package/scripts/forge_jev/review.py +73 -0
- package/scripts/forge_jev/routing.py +271 -0
- package/scripts/forge_jev/subset.py +123 -0
- package/scripts/forge_jev/verify.py +453 -0
- package/scripts/forge_registry.py +140 -0
- package/ui/README.md +287 -0
- package/ui/THIRD_PARTY_NOTICES.md +69 -0
- package/ui/docs/api.md +888 -0
- package/ui/forge_ui/__init__.py +20 -0
- package/ui/forge_ui/__main__.py +135 -0
- package/ui/forge_ui/diffs.py +454 -0
- package/ui/forge_ui/executions.py +436 -0
- package/ui/forge_ui/export.py +204 -0
- package/ui/forge_ui/findings.py +132 -0
- package/ui/forge_ui/fractal.py +583 -0
- package/ui/forge_ui/models.py +216 -0
- package/ui/forge_ui/reader.py +1336 -0
- package/ui/forge_ui/server.py +303 -0
- package/ui/forge_ui/static/app.js +924 -0
- package/ui/forge_ui/static/cloud3d.js +646 -0
- package/ui/forge_ui/static/cloudmodel.js +375 -0
- package/ui/forge_ui/static/cloudui.js +394 -0
- package/ui/forge_ui/static/diffview.js +216 -0
- package/ui/forge_ui/static/favicon.svg +1 -0
- package/ui/forge_ui/static/files.js +776 -0
- package/ui/forge_ui/static/gantt.js +97 -0
- package/ui/forge_ui/static/graph.js +266 -0
- package/ui/forge_ui/static/index.html +55 -0
- package/ui/forge_ui/static/iso.js +765 -0
- package/ui/forge_ui/static/leaderboard.js +315 -0
- package/ui/forge_ui/static/map3d.js +45 -0
- package/ui/forge_ui/static/modelstats.js +249 -0
- package/ui/forge_ui/static/notify.js +179 -0
- package/ui/forge_ui/static/panel.js +526 -0
- package/ui/forge_ui/static/runmodel.js +651 -0
- package/ui/forge_ui/static/scene3d.js +996 -0
- package/ui/forge_ui/static/search.js +119 -0
- package/ui/forge_ui/static/style.css +618 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* forge-ui quick jump: Ctrl/⌘-K or "/" opens one search over every run, task, project, model and command.
|
|
2
|
+
Enter opens the pick, Shift+Enter opens a run (or a task's run) in the cloud. Recent picks come first
|
|
3
|
+
when nothing is typed. All values enter the DOM as text.
|
|
4
|
+
window.ForgeSearch = { init(ctx) }, where ctx = { runs(), commands(), go(href), cloudFilter(filter) }. */
|
|
5
|
+
window.ForgeSearch = (() => {
|
|
6
|
+
'use strict';
|
|
7
|
+
const RM = window.ForgeRunModel, CM = window.ForgeCloudModel;
|
|
8
|
+
const RECENT = 'forge-ui-recent', RECENT_CAP = 30;
|
|
9
|
+
const GROUP = { command: 'Commands', run: 'Runs', task: 'Tasks', project: 'Projects', model: 'Models' };
|
|
10
|
+
const PER = { run: 8, task: 8, project: 5, model: 5, command: 6 };
|
|
11
|
+
const STATE_ST = { live: 'running', failed: 'fail', done: 'merged', pending: 'pending' };
|
|
12
|
+
function el(tag, text, cls) {
|
|
13
|
+
const n = document.createElement(tag);
|
|
14
|
+
if (text !== undefined && text !== null) n.textContent = String(text);
|
|
15
|
+
if (cls) n.className = cls;
|
|
16
|
+
return n;
|
|
17
|
+
}
|
|
18
|
+
const loadRecent = () => { try { const v = JSON.parse(localStorage.getItem(RECENT) || '{}'); return v && typeof v === 'object' ? v : {}; } catch (_) { return {}; } };
|
|
19
|
+
function saveRecent(id) {
|
|
20
|
+
const r = loadRecent(); r[id] = Date.now() / 1000;
|
|
21
|
+
const keep = Object.entries(r).sort((a, b) => b[1] - a[1]).slice(0, RECENT_CAP);
|
|
22
|
+
try { localStorage.setItem(RECENT, JSON.stringify(Object.fromEntries(keep))); } catch (_) { /* not remembered */ }
|
|
23
|
+
}
|
|
24
|
+
const typing = t => t && (t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName));
|
|
25
|
+
const mac = /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || '');
|
|
26
|
+
|
|
27
|
+
function init(ctx) {
|
|
28
|
+
const dlg = el('dialog', undefined, 'jump'); dlg.setAttribute('aria-label', 'Jump to');
|
|
29
|
+
const input = el('input', undefined, 'jump-input');
|
|
30
|
+
input.type = 'search'; input.autocomplete = 'off'; input.spellcheck = false;
|
|
31
|
+
input.placeholder = 'Jump to a run, task, project, model or command…';
|
|
32
|
+
input.setAttribute('role', 'combobox'); input.setAttribute('aria-expanded', 'true'); input.setAttribute('aria-controls', 'jump-list'); input.setAttribute('aria-autocomplete', 'list');
|
|
33
|
+
const listEl = el('ul', undefined, 'jump-list'); listEl.id = 'jump-list'; listEl.setAttribute('role', 'listbox'); listEl.setAttribute('aria-label', 'Results');
|
|
34
|
+
const foot = el('p', 'Enter opens · Shift+Enter opens in the cloud · ↑ ↓ choose · Esc closes', 'jump-foot');
|
|
35
|
+
dlg.append(input, listEl, foot); document.body.append(dlg);
|
|
36
|
+
let items = [], active = 0;
|
|
37
|
+
const cache = { ref: null, idx: [] };
|
|
38
|
+
|
|
39
|
+
function index() {
|
|
40
|
+
const runs = ctx.runs();
|
|
41
|
+
if (runs !== cache.ref) {
|
|
42
|
+
cache.ref = runs;
|
|
43
|
+
const projects = CM ? CM.projects(runs).map(p => ({ id: 'project:' + p.id, kind: 'project', label: p.name, sub: `${p.count} run${p.count === 1 ? '' : 's'} · ${p.repo || ''}`,
|
|
44
|
+
ids: [], words: [p.repo], t: Number.isFinite(p.last) ? p.last : 0, href: '#/cloud/projects/' + encodeURIComponent(p.id) })) : [];
|
|
45
|
+
const used = new Map();
|
|
46
|
+
for (const r of runs) for (const a of new Set((r.models || []).map(RM.alias).filter(Boolean))) { const u = used.get(a) || { n: 0, t: 0 }; u.n++; u.t = Math.max(u.t, r.updated || 0); used.set(a, u); }
|
|
47
|
+
const models = [...used].map(([a, u]) => ({ id: 'model:' + a, kind: 'model', label: a, sub: `in ${u.n} run${u.n === 1 ? '' : 's'} · shows them in the cloud`, ids: [a], t: u.t,
|
|
48
|
+
action: () => ctx.cloudFilter({ models: { aliases: [a], role: 'any' } }) }));
|
|
49
|
+
cache.idx = RM.searchIndex(runs).concat(projects, models);
|
|
50
|
+
}
|
|
51
|
+
return cache.idx.concat(ctx.commands().map(c => ({ ...c, kind: 'command' })));
|
|
52
|
+
}
|
|
53
|
+
function labelWithMark(e) {
|
|
54
|
+
const span = el('span', undefined, 'jump-label'), s = String(e.label || '');
|
|
55
|
+
if (e.mark && e.mark[1] > e.mark[0]) span.append(document.createTextNode(s.slice(0, e.mark[0])), el('mark', s.slice(e.mark[0], e.mark[1])), document.createTextNode(s.slice(e.mark[1])));
|
|
56
|
+
else span.textContent = s;
|
|
57
|
+
return span;
|
|
58
|
+
}
|
|
59
|
+
function render() {
|
|
60
|
+
const ranked = RM.searchRank(index(), input.value, { now: Date.now() / 1000, recent: loadRecent(), limit: 300 });
|
|
61
|
+
const groups = new Map();
|
|
62
|
+
for (const e of ranked) { const g = groups.get(e.kind) || []; if (g.length < (PER[e.kind] || 5)) g.push(e); groups.set(e.kind, g); }
|
|
63
|
+
items = []; listEl.replaceChildren();
|
|
64
|
+
for (const [kind, es] of groups) {
|
|
65
|
+
if (!es.length) continue;
|
|
66
|
+
const h = el('li', GROUP[kind] || kind, 'jump-group'); h.setAttribute('role', 'presentation'); listEl.append(h);
|
|
67
|
+
for (const e of es) {
|
|
68
|
+
const i = items.length, li = el('li', undefined, 'jump-item');
|
|
69
|
+
li.id = 'jump-opt-' + i; li.setAttribute('role', 'option'); li.dataset.i = String(i);
|
|
70
|
+
const dot = el('i', undefined, 'led st-' + (e.kind === 'run' ? STATE_ST[e.state] || 'unknown' : e.kind === 'task' ? String(e.status || 'pending').toLowerCase() : 'none'));
|
|
71
|
+
const text = el('span', undefined, 'jump-text'); text.append(labelWithMark(e), el('span', e.sub || '', 'jump-sub'));
|
|
72
|
+
li.append(dot, text);
|
|
73
|
+
if (e.kind === 'run' || e.kind === 'task') li.title = 'Enter opens · Shift+Enter shows it in the cloud';
|
|
74
|
+
listEl.append(li); items.push({ e, li });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!items.length) { const li = el('li', input.value.trim() ? 'Nothing matches.' : 'No runs yet.', 'jump-empty'); li.setAttribute('role', 'presentation'); listEl.append(li); }
|
|
78
|
+
setActive(Math.min(active, Math.max(0, items.length - 1)));
|
|
79
|
+
}
|
|
80
|
+
function setActive(i) {
|
|
81
|
+
active = i;
|
|
82
|
+
items.forEach((it, k) => it.li.setAttribute('aria-selected', String(k === i)));
|
|
83
|
+
const cur = items[i];
|
|
84
|
+
if (cur) { input.setAttribute('aria-activedescendant', cur.li.id); cur.li.scrollIntoView({ block: 'nearest' }); } else input.removeAttribute('aria-activedescendant');
|
|
85
|
+
}
|
|
86
|
+
function pick(e, inCloud) {
|
|
87
|
+
saveRecent(e.id); close();
|
|
88
|
+
if (inCloud && (e.kind === 'run' || e.kind === 'task')) ctx.go('#/cloud/runs/' + encodeURIComponent(e.key));
|
|
89
|
+
else if (e.action) e.action();
|
|
90
|
+
else if (e.href) ctx.go(e.href);
|
|
91
|
+
}
|
|
92
|
+
function open() {
|
|
93
|
+
if (dlg.open) { input.select(); return; }
|
|
94
|
+
input.value = ''; active = 0; render();
|
|
95
|
+
dlg.showModal(); input.focus();
|
|
96
|
+
}
|
|
97
|
+
function close() { if (dlg.open) dlg.close(); }
|
|
98
|
+
|
|
99
|
+
input.addEventListener('input', () => { active = 0; render(); });
|
|
100
|
+
input.addEventListener('keydown', e => {
|
|
101
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { e.preventDefault(); if (items.length) setActive((active + (e.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length); }
|
|
102
|
+
else if (e.key === 'PageDown' || e.key === 'PageUp') { e.preventDefault(); if (items.length) setActive(Math.max(0, Math.min(items.length - 1, active + (e.key === 'PageDown' ? 8 : -8)))); }
|
|
103
|
+
else if (e.key === 'Enter') { e.preventDefault(); const cur = items[active]; if (cur) pick(cur.e, e.shiftKey); }
|
|
104
|
+
});
|
|
105
|
+
listEl.addEventListener('mousemove', e => { const li = e.target.closest('[role=option]'); if (li && Number(li.dataset.i) !== active) setActive(Number(li.dataset.i)); });
|
|
106
|
+
listEl.addEventListener('click', e => { const li = e.target.closest('[role=option]'); if (li) pick(items[Number(li.dataset.i)].e, e.shiftKey); });
|
|
107
|
+
dlg.addEventListener('click', e => { if (e.target === dlg) close(); }); // the backdrop
|
|
108
|
+
document.addEventListener('keydown', e => {
|
|
109
|
+
if ((e.key === 'k' || e.key === 'K') && (e.ctrlKey || e.metaKey) && !e.altKey) { e.preventDefault(); if (dlg.open) close(); else open(); }
|
|
110
|
+
else if (e.key === '/' && !e.ctrlKey && !e.metaKey && !e.altKey && !dlg.open && !typing(e.target)) { e.preventDefault(); open(); }
|
|
111
|
+
});
|
|
112
|
+
for (const b of document.querySelectorAll('[data-jump]')) {
|
|
113
|
+
b.addEventListener('click', open);
|
|
114
|
+
const k = b.querySelector('kbd'); if (k) k.textContent = mac ? '⌘K' : 'Ctrl K';
|
|
115
|
+
}
|
|
116
|
+
return { open, close, get isOpen() { return dlg.open; } };
|
|
117
|
+
}
|
|
118
|
+
return { init };
|
|
119
|
+
})();
|