elanous 0.2.8 → 0.2.9
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/bFI5EEwg7T6aG88ibX4Zq/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8630-cdfc61e82c653ffc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8894-7317998f6cb97d8c.js → 8894-e263b332208e3957.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9454-139040d37c79dbc9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-fb7c2d458f32fcad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-f4d2ecbbae6088d6.js → page-35e2713597dd24d1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-2053e49930c82748.js → page-918b656f064577ba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-d4b6df905f185055.js → page-f972fc1c00a62e88.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-a70ba27c33003dd0.js → page-5f30e00693527ebd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-7fbae173b3c103a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-18166f885d831d3e.js → page-3b4edcce364062ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/{page-1c9d6cfe68b121c2.js → page-c5794f484c251f44.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1130d8eefcd87e76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-973996d584f008c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-147a328753d983e2.js → page-016e2bda04eecb1f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-799395a9df7d95aa.js → page-b4d6d9a3b56f2940.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-6a8158b71d1fe9d7.js → page-ec49a466121233ba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-f72db356744ceade.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-a6fd9b50d1b85378.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/{page-c0c0d19d51342d3e.js → page-8b0402a46a749a3d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2e002ad8faa43291.js → page-037f83e2a1edc8e2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-b672e02e4bec8deb.js → page-adfbd2ba9598e59a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-46fedff57d4bec67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/{page-9db2226f38c542fb.js → page-0cf318e9dcee2bbf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-899b327cb8b6845c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6c1e6ba743a29dfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/{page-70ee65f5f7a151dc.js → page-1a8e4807292f6b17.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-28deba6bcb834916.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-092e1bcf27d751cc.js → page-de68e2205794037d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/{page-eb52580c4b75b905.js → page-c71c33a573230672.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-7464c1987dd76e6d.js → page-0df30e0c7e50148a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4fc56790fe0d2682.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-59df2aebb38a7c1e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-085847b088675978.js → page-4647be5dbcbd0795.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/{page-9fe9d38c36999eb4.js → page-e025892bda74b743.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a0955de73b89f078.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-369846d2921af584.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-295a02b1026b8255.js → page-72cbc1c8cdd0f65d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-77b28bfb0996d5ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-3220c4934f49c6c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-90670589b87abea8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-2e367075ffdbc062.js → page-7df9243ed021a4cc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-647ed2b66c1d49f1.js → page-4498c3853f4f688d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-35bedde6d885f08f.js +1 -0
- package/apps/pwa/out/_next/static/css/f92f63a5df0ba229.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +30 -29
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +30 -29
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +30 -29
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +27 -26
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +27 -26
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +27 -26
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +30 -29
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +30 -29
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +30 -29
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +30 -29
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +30 -29
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +30 -29
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +27 -26
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +30 -29
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +30 -29
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +27 -26
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +27 -26
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +30 -29
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +30 -29
- package/apps/pwa/out/ops/checklist/index.html +1 -0
- package/apps/pwa/out/ops/checklist/index.txt +30 -0
- package/apps/pwa/out/ops/release/index.html +1 -0
- package/apps/pwa/out/ops/release/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +28 -27
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +30 -29
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +27 -26
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +30 -29
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +30 -29
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +30 -29
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +30 -29
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +30 -29
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +27 -26
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +30 -29
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +30 -29
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +30 -29
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +30 -29
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +30 -29
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +30 -29
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +30 -29
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +30 -29
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +3 -1
- package/graphs/test-diet/nightly-audit.yaml +18 -0
- package/graphs/test-diet/recipes.yaml +3 -0
- package/package.json +1 -1
- package/plugins/doc-draft/graphs/run-step.ts +1 -1
- package/scripts/release-loop/cutoff.ts +20 -2
- package/scripts/release-loop/export-check-node.ts +85 -0
- package/scripts/release-loop/gate-node.ts +18 -4
- package/scripts/release-loop/node-verdict.ts +8 -1
- package/scripts/test-diet/lib.ts +1 -0
- package/scripts/test-diet/node.ts +56 -14
- package/src/auth/setup-link-tokens.fixture.ts +19 -0
- package/src/auth/setup-link-tokens.ts +153 -0
- package/src/budget/unified-usage.ts +75 -0
- package/src/channel-bot-token.ts +37 -10
- package/src/chat/index.ts +9 -9
- package/src/cli/op-proxy-sync.ts +83 -0
- package/src/cli/pr-cli.ts +6 -2
- package/src/cli/release-cli.ts +41 -1
- package/src/dashboard/dashboard-status-lines.ts +45 -0
- package/src/dashboard/first-screen-band.ts +35 -0
- package/src/dashboard/index.ts +70 -13
- package/src/dashboard/provider-slash-runtime.ts +28 -11
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -0
- package/src/dashboard/turn-stream-formatter.ts +1 -1
- package/src/decisions/decision-cards.ts +1 -1
- package/src/index.ts +16 -4
- package/src/maturity/feature-maturity.ts +2 -0
- package/src/nexus/api/http-server.ts +20 -0
- package/src/nexus/api/meta-api.ts +27 -0
- package/src/nexus/api/operator.ts +61 -0
- package/src/nexus/api/ops-api.ts +139 -0
- package/src/nexus/api/ops-seats-sources.ts +65 -0
- package/src/nexus/api/ops-seats.ts +114 -0
- package/src/nexus/api/public-routes.ts +14 -1
- package/src/nexus/api/setup-claim.ts +21 -0
- package/src/nexus/config/secrets/file-backend.ts +56 -18
- package/src/onboarding/first-run-doctor.ts +54 -0
- package/src/release-loop/checklist.ts +5 -64
- package/src/release-loop/feature-store.ts +327 -0
- package/src/release-loop/manifest.ts +59 -5
- package/src/seat-dispatch/ceo-commands.ts +65 -0
- package/src/skills/tools/usage-slash.ts +8 -7
- package/src/telegram-commands.ts +16 -0
- package/src/telegram-run.ts +83 -13
- package/src/thinking-line.ts +28 -20
- package/src/tui/chat/execution-badge.ts +1 -1
- package/src/ux-sim/turn-states.ts +1 -1
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/4836-3084c58c1725a40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-a3e0953307216c58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-9aa47b0bc6d570ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-186fc6952f027acc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-cbbe03c0da7b081a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c108ff1fdb665c97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9567560270857531.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e7ed3d010153d818.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-1ba4a5d857276334.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-0bb8e43203efb23b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-e573437b0a1c728f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-294300625e49e4d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d8ab4d1489223459.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6141f67f531d8b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1eb9a0e1e054209d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-82efa177a30f3741.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d0be51cec4f62606.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ba058c56e38f2792.js +0 -1
- package/apps/pwa/out/_next/static/css/5ef72a618a8994f3.css +0 -1
- package/apps/pwa/out/_next/static/lywc8m_HDzH9MKSDQhyEj/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{lywc8m_HDzH9MKSDQhyEj → bFI5EEwg7T6aG88ibX4Zq}/_ssgManifest.js +0 -0
|
@@ -1,32 +1,33 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[67976,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-
|
|
3
|
-
3:I[12248,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-
|
|
4
|
-
4:I[38519,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-
|
|
5
|
-
5:I[
|
|
6
|
-
6:I[
|
|
7
|
-
7:I[
|
|
8
|
-
8:I[
|
|
9
|
-
9:I[
|
|
10
|
-
a:I[
|
|
11
|
-
b:I[
|
|
12
|
-
c:I[
|
|
13
|
-
d:I[
|
|
14
|
-
e:I[
|
|
15
|
-
f:I[
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
19:"
|
|
21
|
-
|
|
2
|
+
2:I[67976,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"ServiceWorkerRegister"]
|
|
3
|
+
3:I[12248,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"NewBuildBanner"]
|
|
4
|
+
4:I[38519,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"DaemonProvider"]
|
|
5
|
+
5:I[77884,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"OperatorRoleDefault"]
|
|
6
|
+
6:I[8687,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"NexusClientProvider"]
|
|
7
|
+
7:I[94936,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"ThemeProvider"]
|
|
8
|
+
8:I[85039,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"TooltipProvider"]
|
|
9
|
+
9:I[21545,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"ToastProvider"]
|
|
10
|
+
a:I[85258,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"AppShell"]
|
|
11
|
+
b:I[51411,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","6062","static/chunks/6062-73e68343a9814f6a.js","7990","static/chunks/7990-e12efba616f46e03.js","6998","static/chunks/6998-a654fe5c58271600.js","1201","static/chunks/1201-09613bce624467c0.js","7032","static/chunks/7032-f4ef698518fba61c.js","8519","static/chunks/8519-5632377cce994f86.js","2375","static/chunks/2375-cb6debea56cce4fb.js","9454","static/chunks/9454-139040d37c79dbc9.js","8067","static/chunks/8067-d976b441a104ab74.js","8619","static/chunks/8619-4365e03a2862830f.js","5791","static/chunks/5791-bb82743fa6299562.js","7177","static/chunks/app/layout-f72db356744ceade.js"],"MaturityBanner"]
|
|
12
|
+
c:I[57048,[],""]
|
|
13
|
+
d:I[75854,[],""]
|
|
14
|
+
e:I[70766,["2977","static/chunks/2977-e38442e86289f1d3.js","920","static/chunks/920-f7dceb78f1c585ef.js","7990","static/chunks/7990-e12efba616f46e03.js","6416","static/chunks/6416-505ba707cacafbba.js","9454","static/chunks/9454-139040d37c79dbc9.js","4345","static/chunks/app/not-found-46fedff57d4bec67.js"],"default"]
|
|
15
|
+
f:I[79013,[],"ClientPageRoot"]
|
|
16
|
+
10:I[81403,["920","static/chunks/920-f7dceb78f1c585ef.js","6998","static/chunks/6998-a654fe5c58271600.js","2375","static/chunks/2375-cb6debea56cce4fb.js","2975","static/chunks/app/worktrees/page-35bedde6d885f08f.js"],"default"]
|
|
17
|
+
13:I[78357,[],"OutletBoundary"]
|
|
18
|
+
15:I[70112,[],"AsyncMetadataOutlet"]
|
|
19
|
+
17:I[78357,[],"ViewportBoundary"]
|
|
20
|
+
19:I[78357,[],"MetadataBoundary"]
|
|
21
|
+
1a:"$Sreact.suspense"
|
|
22
|
+
1c:I[26324,[],""]
|
|
22
23
|
:HL["/app/_next/static/media/22a5144ee8d83bca-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
23
|
-
:HL["/app/_next/static/css/
|
|
24
|
+
:HL["/app/_next/static/css/f92f63a5df0ba229.css","style"]
|
|
24
25
|
:HL["/app/_next/static/css/04dabcbcc4bfa6db.css","style"]
|
|
25
|
-
0:{"P":null,"b":"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
0:{"P":null,"b":"bFI5EEwg7T6aG88ibX4Zq","p":"/app","c":["","worktrees",""],"i":false,"f":[[["",{"children":["worktrees",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/app/_next/static/css/f92f63a5df0ba229.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/app/_next/static/css/04dabcbcc4bfa6db.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"ko","className":"font-sans __variable_45c93f","children":[["$","head",null,{"children":["$","link",null,{"rel":"preload","as":"font","type":"font/ttf","href":"/app/fonts/JetBrainsMonoNerdFontMono-Regular.ttf","crossOrigin":"anonymous"}]}],["$","body",null,{"className":"min-h-screen bg-background text-foreground antialiased","children":[["$","$L2",null,{}],["$","$L3",null,{}],["$","$L4",null,{"children":[["$","$L5",null,{}],["$","$L6",null,{"children":["$","$L7",null,{"children":["$","$L8",null,{"children":["$","$L9",null,{"children":["$","$La",null,{"children":[["$","$Lb",null,{}],["$","$Lc",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$Ld",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","$Le",null,{}],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]]}]}]}]}]}]]}]]}]]}]]}],{"children":["worktrees",["$","$1","c",{"children":[null,["$","$Lc",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$Ld",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$Lf",null,{"Component":"$10","searchParams":{},"params":{},"promises":["$@11","$@12"]}],null,["$","$L13",null,{"children":["$L14",["$","$L15",null,{"promise":"$@16"}]]}]]}],{},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$L17",null,{"children":"$L18"}],["$","meta",null,{"name":"next-size-adjust","content":""}]],["$","$L19",null,{"children":["$","div",null,{"hidden":true,"children":["$","$1a",null,{"fallback":null,"children":"$L1b"}]}]}]]}],false]],"m":"$undefined","G":["$1c",[]],"s":false,"S":true}
|
|
27
|
+
11:{}
|
|
28
|
+
12:"$0:f:0:1:2:children:2:children:1:props:children:0:props:params"
|
|
29
|
+
18:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1"}],["$","meta","2",{"name":"theme-color","content":"#1e1e2e"}]]
|
|
30
|
+
14:null
|
|
31
|
+
1d:I[48592,[],"IconMark"]
|
|
32
|
+
16:{"metadata":[["$","title","0",{"children":"elanous"}],["$","meta","1",{"name":"description","content":"elanous — voice · chat · intake · control · terminal."}],["$","meta","2",{"name":"application-name","content":"elanous"}],["$","link","3",{"rel":"manifest","href":"/app/manifest.webmanifest","crossOrigin":"$undefined"}],["$","link","4",{"rel":"icon","href":"/app/icons/elanous-32.png","sizes":"32x32","type":"image/png"}],["$","link","5",{"rel":"icon","href":"/app/icons/elanous-16.png","sizes":"16x16","type":"image/png"}],["$","link","6",{"rel":"apple-touch-icon","href":"/app/icons/elanous-180.png","sizes":"180x180","type":"image/png"}],["$","$L1d","7",{}]],"error":null,"digest":"$undefined"}
|
|
33
|
+
1b:"$16:metadata"
|
|
@@ -11,6 +11,9 @@ gate:
|
|
|
11
11
|
command: 'bun scripts/release-loop/gate-node.ts --json'
|
|
12
12
|
# 4h — the Pod gate took 2h02m on 09-30 (G1f ②) and the 0.2.5 loop was cut at exactly 2h with no verdict; K9 (≤15 min) is the real fix.
|
|
13
13
|
timeout_ms: 14400000
|
|
14
|
+
export-check:
|
|
15
|
+
command: 'bun scripts/release-loop/export-check-node.ts'
|
|
16
|
+
timeout_ms: 1800000
|
|
14
17
|
pwa:
|
|
15
18
|
command: 'bun scripts/release-loop/node-verdict.ts pwa'
|
|
16
19
|
timeout_ms: 1800000
|
|
@@ -15,6 +15,7 @@ nodes:
|
|
|
15
15
|
- { node_id: cutoff, kind: judge, recipe: 'cmd:cutoff', max_visits: 1 }
|
|
16
16
|
- { node_id: checklist-gate, kind: gate, recipe: 'cmd:checklist-gate', max_visits: 1 }
|
|
17
17
|
- { node_id: gate, kind: gate, recipe: 'cmd:gate', max_visits: 1, notify: start }
|
|
18
|
+
- { node_id: export-check, kind: gate, recipe: 'cmd:export-check', max_visits: 1 }
|
|
18
19
|
- { node_id: pwa, kind: gate, recipe: 'cmd:pwa', max_visits: 1, notify: start }
|
|
19
20
|
- { node_id: prepare, kind: agent, recipe: 'cmd:prepare', max_visits: 1, notify: start }
|
|
20
21
|
- { node_id: upgrade, kind: gate, recipe: 'cmd:upgrade', max_visits: 1 }
|
|
@@ -36,7 +37,8 @@ edges:
|
|
|
36
37
|
- { from: version-release, on: outcome, map: { ok: cutoff, fail: failed, error: failed } }
|
|
37
38
|
- { from: cutoff, on: outcome, map: { ok: checklist-gate, fail: failed, error: failed } }
|
|
38
39
|
- { from: checklist-gate, on: outcome, map: { ok: gate, fail: failed, error: failed } }
|
|
39
|
-
- { from: gate, on: outcome, map: { ok:
|
|
40
|
+
- { from: gate, on: outcome, map: { ok: export-check, fail: failed, error: failed } }
|
|
41
|
+
- { from: export-check, on: outcome, map: { ok: pwa, fail: failed, error: failed } }
|
|
40
42
|
- { from: pwa, on: outcome, map: { ok: prepare, fail: failed, error: failed } }
|
|
41
43
|
- { from: prepare, on: outcome, map: { ok: upgrade, fail: failed, error: failed } }
|
|
42
44
|
- { from: upgrade, on: outcome, map: { ok: tui, fail: failed, error: failed } }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# TD1b — whole-repository audits run alone; record their results and draft a card on failure.
|
|
2
|
+
graph_id: nightly-audit
|
|
3
|
+
loop:
|
|
4
|
+
title: 야간 저장소 감사
|
|
5
|
+
description: 게이트에서 제외한 감사 다섯 파일을 단독으로 재고 원장과 실패 카드 초안을 남긴다
|
|
6
|
+
trigger:
|
|
7
|
+
events: [manual]
|
|
8
|
+
version: 1
|
|
9
|
+
entry_node: audit
|
|
10
|
+
terminal_nodes: [done, failed]
|
|
11
|
+
nodes:
|
|
12
|
+
- { node_id: audit, kind: gate, recipe: 'cmd:audit', max_visits: 1 }
|
|
13
|
+
- { node_id: record, kind: judge, recipe: 'cmd:record', max_visits: 1 }
|
|
14
|
+
- { node_id: done, kind: gate, max_visits: 1 }
|
|
15
|
+
- { node_id: failed, kind: gate, max_visits: 1 }
|
|
16
|
+
edges:
|
|
17
|
+
- { from: audit, on: outcome, map: { ok: record, fail: record, error: record } }
|
|
18
|
+
- { from: record, on: outcome, map: { ok: done, fail: failed, error: failed } }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elanous",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Self-healing coding harness where eyes, hands, and memory all turn on one sentence — it authors its own goals, implements them in isolated worktrees, and reviews its own work.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Elanvital AI",
|
|
@@ -55,7 +55,7 @@ function validate(markdown: string, kind: Kind): string {
|
|
|
55
55
|
if (!/^# [^\n#]+$/u.test(lines[0] ?? '') || !lines.slice(1).join('').trim()) return 'title or body missing';
|
|
56
56
|
const words = wordCount(markdown);
|
|
57
57
|
if (words < 15 || words > limits[kind]) return `length must be 15–${limits[kind]} words`;
|
|
58
|
-
if (/\[[^\]]*\]|\{\{[^}]*\}\}|<[^>]+>|(?:TODO|TBD|작성 예정|내용 입력|빈칸)/iu.test(markdown)) return 'unfilled placeholder';
|
|
58
|
+
if (/\[[^\]]*\](?!\()|\{\{[^}]*\}\}|<[^>]+>|(?:TODO|TBD|작성 예정|내용 입력|빈칸)/iu.test(markdown)) return 'unfilled placeholder';
|
|
59
59
|
if (/(?:게시|발행|발송|전송|결제)(?:\s*완료|했|됐|되었|하였)|\b(?:published|posted|sent|paid)\b/iu.test(markdown)) return 'unverified publication or transaction claim';
|
|
60
60
|
if (kind === 'exec-onepager' && sections.some(section => {
|
|
61
61
|
const match = new RegExp(`^## ${section}[ \\t]*\\r?\\n([\\s\\S]*?)(?=^## |$(?![\\s\\S]))`, 'mu').exec(markdown);
|
|
@@ -4,13 +4,14 @@ import { mkdirSync, realpathSync, writeFileSync } from 'node:fs';
|
|
|
4
4
|
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
5
5
|
import { debug } from '../../src/debug/log.js';
|
|
6
6
|
import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
|
|
7
|
-
import { buildReleaseManifest, type ReleaseLanding } from '../../src/release-loop/manifest.js';
|
|
7
|
+
import { buildReleaseManifest, parseNextMdNotes, type NextMdNote, type ReleaseLanding } from '../../src/release-loop/manifest.js';
|
|
8
8
|
import { readReleaseNotes, releaseNotesDir } from '../../src/release-loop/release-note.js';
|
|
9
9
|
import { queryRunningRuns } from '../../src/self-implement/running-runs.js';
|
|
10
10
|
import { loadFederatedRunLedger } from '../../src/self-implement/run-ledger.js';
|
|
11
11
|
|
|
12
12
|
const SEED = 'c1cc37478';
|
|
13
13
|
const CLI_DOC = 'release/public/docs/cli.md';
|
|
14
|
+
const NEXT_MD = 'release/next.md';
|
|
14
15
|
|
|
15
16
|
function git(args: string[], optional = false): string | null {
|
|
16
17
|
const result = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
@@ -61,6 +62,22 @@ function landingAt(sha: string, title: string): ReleaseLanding {
|
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
/** next.md lines at the cutoff, each tied to the last landing in range whose diff added that exact line. */
|
|
66
|
+
function nextMdNotes(cutoff: string, landings: ReleaseLanding[]): NextMdNote[] {
|
|
67
|
+
const text = git(['show', `${cutoff}:${NEXT_MD}`], true);
|
|
68
|
+
if (!text) return [];
|
|
69
|
+
const addedBy = new Map<string, string>();
|
|
70
|
+
for (const landing of landings) {
|
|
71
|
+
if (!landing.changedFiles.includes(NEXT_MD)) continue;
|
|
72
|
+
const diff = requiredGit(['show', '-m', '--first-parent', '--format=', '-U0', landing.sha, '--', NEXT_MD]);
|
|
73
|
+
for (const line of diff.split('\n')) if (line.startsWith('+') && !line.startsWith('+++')) addedBy.set(line.slice(1).trim(), landing.sha);
|
|
74
|
+
}
|
|
75
|
+
return parseNextMdNotes(text).map((note) => {
|
|
76
|
+
const sha = note.raw ? addedBy.get(note.raw) : undefined;
|
|
77
|
+
return { kind: note.kind, line: note.line, ...(sha ? { sha } : {}) };
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
64
81
|
function runningGoalPaths(): string[] {
|
|
65
82
|
const repo = process.cwd();
|
|
66
83
|
const paths: string[] = [];
|
|
@@ -119,10 +136,11 @@ export function main(args: string[] = process.argv.slice(2)): void {
|
|
|
119
136
|
const notes = readReleaseNotes(releaseNotesDir(instanceRoot));
|
|
120
137
|
debug.log('release.notes', 'read', { fragments: notes.size, problems: notes.problems });
|
|
121
138
|
const manifest = buildReleaseManifest({
|
|
122
|
-
version, baseline: { ref: baseline.ref, sha: baselineSha }, cutoff: { sha: cutoff }, landings, notes,
|
|
139
|
+
version, baseline: { ref: baseline.ref, sha: baselineSha }, cutoff: { sha: cutoff }, landings, notes, nextMd: nextMdNotes(cutoff, landings),
|
|
123
140
|
runningGoalPaths: runningGoalPaths(), publicCommandsBefore: commandsAt(baselineSha), publicCommandsAfter: commandsAt(cutoff),
|
|
124
141
|
});
|
|
125
142
|
const output = { ...manifest, baselineSource: baseline.source };
|
|
143
|
+
debug.log('release-loop.notes', 'fragments', { version, ...manifest.fragments });
|
|
126
144
|
const directory = join(instanceRoot, 'release', version);
|
|
127
145
|
mkdirSync(directory, { recursive: true });
|
|
128
146
|
writeFileSync(join(directory, 'manifest.json'), JSON.stringify(output, null, 2) + '\n');
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { existsSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { finishNode, nodeOutput, readGraphContext, runCommand, type CommandResult, type CommandRunner } from './node-verdict.js';
|
|
6
|
+
|
|
7
|
+
export interface ExportCheckResult extends Record<string, unknown> {
|
|
8
|
+
outcome: 'ok' | 'fail';
|
|
9
|
+
verdict: 'pass' | 'fail';
|
|
10
|
+
summary: string;
|
|
11
|
+
step: 'export' | 'build';
|
|
12
|
+
tail: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function failed(step: ExportCheckResult['step'], message: string, result?: CommandResult): ExportCheckResult {
|
|
16
|
+
const tail = (result ? result.stderr || result.stdout : message).trim().slice(-300);
|
|
17
|
+
return { outcome: 'fail', verdict: 'fail', summary: `${step} failed: ${message}${result ? ` (rc=${result.status})` : ''}`, step, tail };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Check the same public export and PWA build as release prepare, without cloning or writing to a public remote. */
|
|
21
|
+
export function runExportCheck(run: CommandRunner = runCommand, repoRoot = process.cwd()): ExportCheckResult {
|
|
22
|
+
const context = readGraphContext();
|
|
23
|
+
const commit = nodeOutput(context, 'version-release', 'commit');
|
|
24
|
+
if (context.outputs.gate?.outcome !== 'ok') return failed('export', 'gate did not pass');
|
|
25
|
+
const root = resolve(repoRoot);
|
|
26
|
+
const out = mkdtempSync(join(tmpdir(), 'elanous-export-check-'));
|
|
27
|
+
const sourceDir = join(out, 'source');
|
|
28
|
+
let added = false;
|
|
29
|
+
let step: ExportCheckResult['step'] = 'export';
|
|
30
|
+
let result: ExportCheckResult = failed(step, 'check incomplete');
|
|
31
|
+
try {
|
|
32
|
+
const modulesRoot = dirname(realpathSync(join(root, 'node_modules')));
|
|
33
|
+
const add = run('git', ['worktree', 'add', '-q', '--detach', sourceDir, commit], root);
|
|
34
|
+
if (add.status !== 0) result = failed('export', 'git worktree add', add);
|
|
35
|
+
else {
|
|
36
|
+
added = true;
|
|
37
|
+
const head = run('git', ['rev-parse', 'HEAD'], sourceDir);
|
|
38
|
+
if (head.status !== 0 || head.stdout.trim() !== commit) result = failed('export', 'cut commit mismatch', head);
|
|
39
|
+
else {
|
|
40
|
+
const version = (JSON.parse(readFileSync(join(sourceDir, 'package.json'), 'utf8')) as { version?: string }).version;
|
|
41
|
+
if (version !== context.input.version) result = failed('export', `package.json version ${version} != ${context.input.version}`);
|
|
42
|
+
else {
|
|
43
|
+
symlinkSync(join(modulesRoot, 'node_modules'), join(sourceDir, 'node_modules'), 'dir');
|
|
44
|
+
const exported = run('bun', ['scripts/public-export.ts', '--out', join(out, 'export')], sourceDir);
|
|
45
|
+
if (exported.status !== 0) result = failed('export', 'public export', exported);
|
|
46
|
+
else {
|
|
47
|
+
step = 'build';
|
|
48
|
+
const publicDir = join(out, 'export');
|
|
49
|
+
symlinkSync(join(modulesRoot, 'node_modules'), join(publicDir, 'node_modules'), 'dir');
|
|
50
|
+
const pwaModules = join(modulesRoot, 'apps', 'pwa', 'node_modules');
|
|
51
|
+
if (existsSync(pwaModules) && existsSync(join(publicDir, 'apps', 'pwa'))) symlinkSync(pwaModules, join(publicDir, 'apps', 'pwa', 'node_modules'), 'dir');
|
|
52
|
+
const built = run('bun', ['bin/elanous.mjs', 'nexus', 'build'], publicDir);
|
|
53
|
+
result = built.status === 0 && existsSync(join(publicDir, 'apps', 'pwa', 'out', 'index.html'))
|
|
54
|
+
? { outcome: 'ok', verdict: 'pass', summary: `public export and PWA build ${commit.slice(0, 12)}`, step: 'build', tail: '' }
|
|
55
|
+
: failed('build', 'PWA build or out/index.html missing', built);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
result = failed(step, error instanceof Error ? error.message : String(error));
|
|
62
|
+
} finally {
|
|
63
|
+
try {
|
|
64
|
+
if (added) {
|
|
65
|
+
const removed = run('git', ['worktree', 'remove', '--force', sourceDir], root);
|
|
66
|
+
if (removed.status !== 0) result = failed(step, 'git worktree remove', removed);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
result = failed(step, `git worktree remove: ${error instanceof Error ? error.message : String(error)}`);
|
|
70
|
+
} finally {
|
|
71
|
+
rmSync(out, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (import.meta.main) {
|
|
78
|
+
let version = '';
|
|
79
|
+
try {
|
|
80
|
+
version = readGraphContext().input.version;
|
|
81
|
+
process.exitCode = finishNode('export-check', version, runExportCheck());
|
|
82
|
+
} catch (error) {
|
|
83
|
+
process.exitCode = finishNode('export-check', version, failed('export', error instanceof Error ? error.message : String(error)));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -125,6 +125,14 @@ export const POD_MEMORY_SOURCE = 'docs/measurements/td1-whole-gate-mechanical-20
|
|
|
125
125
|
export const POD_SHARD_FILE_CAP = 27;
|
|
126
126
|
|
|
127
127
|
export const POD_SWEEP_INTEGRATION_ONLY: readonly string[] = ['scripts/install.test.ts'];
|
|
128
|
+
/** Whole-repository audits run alone in the nightly test-diet graph, not in release-gate shards. */
|
|
129
|
+
export const GATE_NIGHTLY_AUDITS: readonly string[] = [
|
|
130
|
+
'test/f12-sweep.test.ts', // Sweeps the whole repository; 7.8 GB even after TD1a.
|
|
131
|
+
'scripts/unwired-exports.test.ts', // Compiles and scans all exports; 9.9 GB.
|
|
132
|
+
'test/guardian/dispatch-surface-contract.test.ts', // Compiles repository-wide dispatch contracts; 8.3 GB.
|
|
133
|
+
'test/pwa-build-typecheck.test.ts', // Builds and typechecks the whole PWA; 4.2 GB.
|
|
134
|
+
'test/user-config-mcp.test.ts', // 2.1 GB peak; keep the gate below the 2 GB audit budget.
|
|
135
|
+
];
|
|
128
136
|
const tail40 = (output: string) => output.trimEnd().split(/\r?\n/).slice(-40).join('\n');
|
|
129
137
|
const lastStartedTestFile = (output: string, paths: string[]): string | undefined => {
|
|
130
138
|
let last: string | undefined;
|
|
@@ -211,9 +219,11 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
211
219
|
// CDP 시험은 `test:deterministic` 이 스스로 뺀다 — 조각에 그것만 남으면 bun «시험 없음» exit 1 을 «불완전»으로 읽었다(09-30 G1d 실측 둘).
|
|
212
220
|
// bun 의 탐색은 숨은 디렉터리(`.x/`)를 안 연다 — 사람의 `bun test` 가 한 번도 안 돌리는 빈 픽스처가 조각에 혼자 남아 «Ran 0 tests» 를 «불완전»으로 읽었다(09-30 G1e 5번 조각).
|
|
213
221
|
const assignable = files.filter((file) => !cdpPatterns.includes(file) && !POD_SWEEP_INTEGRATION_ONLY.includes(file)
|
|
214
|
-
&& !file.split('/').some((part) => part.startsWith('.')));
|
|
222
|
+
&& !GATE_NIGHTLY_AUDITS.includes(file) && !file.split('/').some((part) => part.startsWith('.')));
|
|
215
223
|
const integrationOnly = files.filter((file) => POD_SWEEP_INTEGRATION_ONLY.includes(file));
|
|
216
224
|
if (integrationOnly.length) debug.log('release-loop.gate', 'pod-sweep-integration-only', { files: integrationOnly });
|
|
225
|
+
const nightlyAudits = files.filter((file) => GATE_NIGHTLY_AUDITS.includes(file));
|
|
226
|
+
if (nightlyAudits.length) debug.log('release-loop.gate', 'pod-sweep-nightly-audit', { files: nightlyAudits });
|
|
217
227
|
if (!assignable.length) throw new Error('sweep incomplete: no tests ran');
|
|
218
228
|
const durations = pod.durationSource ? readFileDurations(pod.durationSource) : new Map<string, number>();
|
|
219
229
|
const memory = readFileMemory(join(tree, POD_MEMORY_SOURCE));
|
|
@@ -427,9 +437,10 @@ export function createGateRunner(repo: string, remote?: string, commandOverride?
|
|
|
427
437
|
const outputs: string[] = [];
|
|
428
438
|
let total = { pass: 0, fail: 0, errors: 0, ran: 0, files: 0 };
|
|
429
439
|
for (const group of groups) {
|
|
430
|
-
if (!group.paths.length || !files.some((f) => group.paths.some((p) => f === p || f.startsWith(`${p}/`)))) continue;
|
|
440
|
+
if (!group.paths.length || !files.some((f) => !GATE_NIGHTLY_AUDITS.includes(f) && group.paths.some((p) => f === p || f.startsWith(`${p}/`)))) continue;
|
|
431
441
|
const start = Date.now();
|
|
432
|
-
const groupIgnores =
|
|
442
|
+
const groupIgnores = [...new Set([...cdpPatterns, ...GATE_NIGHTLY_AUDITS])]
|
|
443
|
+
.filter((pattern) => files.includes(pattern) && group.paths.some((p) => pattern === p || pattern.startsWith(`${p}/`)))
|
|
433
444
|
.flatMap((pattern) => ['--path-ignore-patterns', pattern]);
|
|
434
445
|
const run = await command('bun', ['run', 'test:deterministic', ...groupIgnores, ...group.paths.map(asPath)], tree);
|
|
435
446
|
if (logDir) {
|
|
@@ -608,7 +619,10 @@ export async function judgeGate(opts: GateOptions, runner: GateRunner = createGa
|
|
|
608
619
|
};
|
|
609
620
|
let baseline: SweepFailures | undefined = trusted ? { failures: trusted.failures, errors: trusted.errors ?? [] } : undefined;
|
|
610
621
|
if (!baseline) {
|
|
611
|
-
|
|
622
|
+
// K9b — with no reusable ledger the baseline is swept on the same Pod pool as the cut, not on this host (0.2.6: an
|
|
623
|
+
// hour of local baseline after a 23-minute Pod cut).
|
|
624
|
+
const baseRun = await runner.sweep(await getBaseTree(), join(root, 'release', opts.version, 'gate-logs', 'baseline'),
|
|
625
|
+
opts.pod ? { ...opts.pod, durationSource: join(ledger, 'release', opts.baselineVersion, 'gate-logs', 'cut') } : undefined);
|
|
612
626
|
baseline = failuresOf(baseRun, 'baseline sweep');
|
|
613
627
|
}
|
|
614
628
|
for (const id of [...baseline.failures, ...baseline.errors, ...cut.failures, ...cut.errors]) fileOf(id);
|
|
@@ -57,6 +57,11 @@ export function errorResult(error: unknown): { outcome: 'error'; verdict: 'fail'
|
|
|
57
57
|
return { outcome: 'error', verdict: 'fail', summary: error instanceof Error ? error.message : String(error) };
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/** A cut whose notes would show users nothing fails the cutoff instead of shipping a «Plus N internal changes.» page. */
|
|
61
|
+
export function cutoffNotesEmpty(data: Record<string, unknown> | undefined): boolean {
|
|
62
|
+
return Array.isArray(data?.escalate) && (data.escalate as Array<{ kind?: string }>).some((item) => item?.kind === 'notes-empty');
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
// Existing cutoff/PWA/TUI programs have different output conventions; normalize them at the graph boundary.
|
|
61
66
|
if (import.meta.main) {
|
|
62
67
|
const node = process.argv[2];
|
|
@@ -78,7 +83,9 @@ if (import.meta.main) {
|
|
|
78
83
|
const baseline = data?.baseline as { sha?: string } | undefined;
|
|
79
84
|
const outcome: NodeOutcome = node === 'cutoff' ? run.status === 0 && data?.version === version && (data?.cutoff as { sha?: string } | undefined)?.sha === commit && typeof baseline?.sha === 'string' ? 'ok' : 'error'
|
|
80
85
|
: run.status === 0 && (verdict === 'pass' || verdict === 'flaky') ? 'ok' : run.status === 1 ? 'fail' : 'error';
|
|
81
|
-
|
|
86
|
+
if (node === 'cutoff' && outcome === 'ok' && cutoffNotesEmpty(data)) {
|
|
87
|
+
result = { ...data, outcome: 'fail', verdict: 'fail', summary: 'cutoff notes-empty — 사용자에게 보일 변경 줄이 0이다(release/next.md 와 PR 노트 조각을 확인하라)' };
|
|
88
|
+
} else result = { ...data, outcome, verdict: outcome === 'ok' ? verdict === 'flaky' ? 'flaky' : 'pass' : 'fail',
|
|
82
89
|
summary: outcome === 'ok' ? `${node} ${verdict === 'flaky' ? 'flaky' : 'pass'}` : `${node} ${data?.error || run.stderr.trim() || data?.verdict || 'failed'} (rc=${run.status})` };
|
|
83
90
|
} catch (error) { result = errorResult(error); }
|
|
84
91
|
process.exitCode = finishNode(node ?? 'unknown', version, result);
|
package/scripts/test-diet/lib.ts
CHANGED
|
@@ -51,6 +51,7 @@ export function judge(m: Measurement, caught90: number): Judged {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function ledgerPath(root: string): string { return join(root, 'test-diet', 'ledger.jsonl'); }
|
|
54
|
+
export function nightlyAuditLedgerPath(root: string): string { return join(root, 'test-diet', 'nightly-audit.jsonl'); }
|
|
54
55
|
|
|
55
56
|
export function lastLedgerLine(root: string): LedgerLine | null {
|
|
56
57
|
const path = ledgerPath(root);
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// TD2 graph nodes: pick → measure → record. Shadow only — measures alone on a remote host and drafts a card.
|
|
3
|
-
// bun scripts/test-diet/node.ts pick|measure|record
|
|
3
|
+
// bun scripts/test-diet/node.ts pick|measure|audit|record (test-diet or nightly-audit graph)
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
|
-
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { debug } from '../../src/debug/log.js';
|
|
8
8
|
import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
|
|
9
|
-
import {
|
|
9
|
+
import { GATE_NIGHTLY_AUDITS } from '../release-loop/gate-node.js';
|
|
10
|
+
import { appendLedger, costTable, judge, lastLedgerLine, nightlyAuditLedgerPath, pickRange, writeCardDraft, type Measurement } from './lib.js';
|
|
10
11
|
|
|
11
|
-
type Context = { input: Record<string, unknown>; outputs: Record<string, Record<string, unknown
|
|
12
|
+
type Context = { graphId?: string; input: Record<string, unknown>; outputs: Record<string, Record<string, unknown> | null> };
|
|
12
13
|
function context(): Context {
|
|
13
14
|
const at = process.env.ELANOUS_GRAPH_CONTEXT;
|
|
14
15
|
if (!at) throw new Error('ELANOUS_GRAPH_CONTEXT required');
|
|
15
16
|
const raw = JSON.parse(at.trimStart().startsWith('{') ? at : readFileSync(at, 'utf8')) as Partial<Context>;
|
|
16
|
-
return { input: raw.input ?? {}, outputs: raw.outputs ?? {} };
|
|
17
|
+
return { graphId: raw.graphId, input: raw.input ?? {}, outputs: raw.outputs ?? {} };
|
|
17
18
|
}
|
|
18
19
|
function emit(result: Record<string, unknown> & { outcome: 'ok' | 'fail' | 'error'; summary: string }): number {
|
|
19
20
|
console.log(JSON.stringify({ verdict: result.outcome === 'ok' ? 'pass' : 'fail', ...result }));
|
|
@@ -34,8 +35,8 @@ function pick(ctx: Context): number {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/** One remote run: shallow clone of the mirror, one install, each file alone with its peak memory. */
|
|
37
|
-
function measure(ctx: Context): number {
|
|
38
|
-
const picked = ctx.outputs.pick?.files;
|
|
38
|
+
function measure(ctx: Context, audit = false): number {
|
|
39
|
+
const picked = audit ? [...GATE_NIGHTLY_AUDITS] : ctx.outputs.pick?.files;
|
|
39
40
|
if (!Array.isArray(picked) || picked.length === 0) return emit({ outcome: 'fail', summary: 'nothing picked' });
|
|
40
41
|
const host = typeof ctx.input.remote === 'string' ? ctx.input.remote : 'node-b';
|
|
41
42
|
const mirror = typeof ctx.input.mirror === 'string' ? ctx.input.mirror : '~/mirror/elanous-agent.git';
|
|
@@ -59,18 +60,58 @@ function measure(ctx: Context): number {
|
|
|
59
60
|
// A failing file names its first error, so an environment gap (e.g. no Java on the host) is not read as a test defect.
|
|
60
61
|
' why=""; [ "$rc" -ne 0 ] && why=$(grep -v -E "^\\s*$|^bun test|^ *[0-9]+ \\||^error: *$" "$T/err" | grep -m1 -E "Unable to|Cannot find|not found|ENOENT|EACCES|rror" | tr "\\t" " " | cut -c1-160)',
|
|
61
62
|
' printf "M\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n" "$f" "$e" "${rss:-}" "$rc" "${pass:-}" "${fail:-}" "$why"',
|
|
62
|
-
|
|
63
|
+
"done <<'TEST_DIET_FILES'", ...picked, 'TEST_DIET_FILES',
|
|
63
64
|
].join('\n');
|
|
64
|
-
const run = spawnSync('ssh', ['-o', 'BatchMode=yes', host, 'bash', '-s'], { input: `${script}\n
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
const commit = /^COMMIT (\w+)/m.exec(run.stdout)?.[1] ?? '?';
|
|
65
|
+
const run = spawnSync('ssh', ['-o', 'BatchMode=yes', host, 'bash', '-s'], { input: `${script}\n`, encoding: 'utf8', timeout: 4 * 3600_000, maxBuffer: 16 * 1024 * 1024 });
|
|
66
|
+
const remoteError = run.status !== 0 ? `remote measure failed (rc=${run.status ?? 'no exit'}): ${String(run.error ?? run.stderr ?? '').trim().slice(0, 200)}` : undefined;
|
|
67
|
+
if (!audit && remoteError && !String(run.stdout).includes('\nM\t')) return emit({ outcome: 'error', summary: remoteError });
|
|
68
|
+
const commit = /^COMMIT (\w+)/m.exec(String(run.stdout))?.[1] ?? '?';
|
|
68
69
|
const measurements: Measurement[] = String(run.stdout).split('\n').filter((l) => l.startsWith('M\t')).map((l) => {
|
|
69
70
|
const [, file, secs, rss, rc, pass, fail, why] = l.split('\t');
|
|
70
71
|
const num = (v: string | undefined) => (v === undefined || v === '' ? null : Number(v));
|
|
71
72
|
return { file: file!, secs: Number(secs), rssMb: num(rss), rc: num(rc), pass: num(pass), fail: num(fail), ...(why ? { reason: why } : {}) };
|
|
72
73
|
});
|
|
73
|
-
|
|
74
|
+
const complete = measurements.length === picked.length && picked.every((file) => measurements.some((m) => m.file === file));
|
|
75
|
+
const summary = remoteError ?? `measured ${measurements.length}/${picked.length} on ${host} at ${commit.slice(0, 9)}`;
|
|
76
|
+
return emit({ outcome: audit ? complete && !remoteError ? 'ok' : 'error' : measurements.length ? 'ok' : 'error',
|
|
77
|
+
summary, host, commit, measurements, ...(remoteError ? { remoteError } : {}) });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function recordNightlyAudit(ctx: Context): number {
|
|
81
|
+
const m = ctx.outputs.audit;
|
|
82
|
+
const raw = Array.isArray(m?.measurements) ? m.measurements : [];
|
|
83
|
+
const measured = new Map<string, Measurement>();
|
|
84
|
+
for (const item of raw) {
|
|
85
|
+
if (!item || typeof item !== 'object' || !('file' in item) || typeof item.file !== 'string' || !GATE_NIGHTLY_AUDITS.includes(item.file)) continue;
|
|
86
|
+
const x = item as Partial<Measurement>;
|
|
87
|
+
if (measured.has(item.file) || typeof x.secs !== 'number' || !Number.isFinite(x.secs)
|
|
88
|
+
|| (x.rssMb !== null && (typeof x.rssMb !== 'number' || !Number.isFinite(x.rssMb)))
|
|
89
|
+
|| (x.rc !== null && (typeof x.rc !== 'number' || !Number.isInteger(x.rc)))
|
|
90
|
+
|| (x.pass !== null && (typeof x.pass !== 'number' || !Number.isInteger(x.pass)))
|
|
91
|
+
|| (x.fail !== null && (typeof x.fail !== 'number' || !Number.isInteger(x.fail)))) continue;
|
|
92
|
+
measured.set(item.file, x as Measurement);
|
|
93
|
+
}
|
|
94
|
+
const error = typeof m?.remoteError === 'string' ? m.remoteError
|
|
95
|
+
: m?.outcome === 'error' || m?.outcome === 'fail' || !m
|
|
96
|
+
? typeof m?.summary === 'string' ? m.summary : 'audit execution produced no result' : undefined;
|
|
97
|
+
const results = GATE_NIGHTLY_AUDITS.map((file, index) => {
|
|
98
|
+
const found = measured.get(file);
|
|
99
|
+
const measurement: Measurement = found ?? { file, secs: 0, rssMb: null, rc: null, pass: null, fail: null,
|
|
100
|
+
reason: `not measured: ${typeof m?.summary === 'string' ? m.summary : error ?? 'audit result missing'}` };
|
|
101
|
+
// Even a complete set of file outputs cannot prove a clean audit when the remote process failed afterward.
|
|
102
|
+
return judge(error && measured.size === GATE_NIGHTLY_AUDITS.length && index === 0 && found
|
|
103
|
+
? { ...found, rc: found.rc === 0 ? null : found.rc, reason: `${error}${found.reason ? `; ${found.reason}` : ''}` } : measurement, 1);
|
|
104
|
+
});
|
|
105
|
+
const line = { at: new Date().toISOString(), range: 'nightly-audit', start: 0, end: results.length - 1,
|
|
106
|
+
next: 0, total: results.length, commit: String(m?.commit ?? '?'), budgetSecs: 0, ...(error ? { error } : {}), results };
|
|
107
|
+
const root = effectiveInstanceRoot();
|
|
108
|
+
const path = nightlyAuditLedgerPath(root);
|
|
109
|
+
mkdirSync(join(root, 'test-diet'), { recursive: true });
|
|
110
|
+
appendFileSync(path, `${JSON.stringify(line)}\n`);
|
|
111
|
+
const card = writeCardDraft(root, line);
|
|
112
|
+
const failing = results.filter((r) => r.verdict === 'failing').length;
|
|
113
|
+
debug.log('test-diet', 'nightly-audit-recorded', { files: results.length, failing, card: card !== null });
|
|
114
|
+
return emit({ outcome: failing ? 'fail' : 'ok', summary: `nightly audit ${results.length} · failing ${failing}${card ? ' · card draft' : ''}`, failing, ledger: path, ...(card ? { card } : {}) });
|
|
74
115
|
}
|
|
75
116
|
|
|
76
117
|
function record(ctx: Context): number {
|
|
@@ -95,7 +136,8 @@ if (import.meta.main) {
|
|
|
95
136
|
const step = process.argv[2];
|
|
96
137
|
try {
|
|
97
138
|
const ctx = context();
|
|
98
|
-
process.exitCode = step === 'pick' ? pick(ctx) : step === 'measure' ? measure(ctx) : step === '
|
|
139
|
+
process.exitCode = step === 'pick' ? pick(ctx) : step === 'measure' ? measure(ctx) : step === 'audit' ? measure(ctx, true)
|
|
140
|
+
: step === 'record' ? (ctx.graphId === 'nightly-audit' || Object.hasOwn(ctx.outputs, 'audit') ? recordNightlyAudit(ctx) : record(ctx)) : emit({ outcome: 'error', summary: `unknown step: ${step}` });
|
|
99
141
|
} catch (error) {
|
|
100
142
|
process.exitCode = emit({ outcome: 'error', summary: error instanceof Error ? error.message : String(error) });
|
|
101
143
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { openSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { dlopen, FFIType } from 'bun:ffi';
|
|
4
|
+
import { claimSetupLinkToken } from './setup-link-tokens.js';
|
|
5
|
+
|
|
6
|
+
const [mode, dir, token, now] = process.argv.slice(2);
|
|
7
|
+
if (mode === 'claim') {
|
|
8
|
+
process.stdout.write(JSON.stringify(claimSetupLinkToken(token, { dir, now: Number(now) })));
|
|
9
|
+
} else if (mode === 'hold') {
|
|
10
|
+
const fd = openSync(join(dir, 'setup-link-tokens.json.lock'), 'r+');
|
|
11
|
+
const libc = dlopen(process.platform === 'darwin' ? '/usr/lib/libSystem.B.dylib' : 'libc.so.6', {
|
|
12
|
+
flock: { args: [FFIType.i32, FFIType.i32], returns: FFIType.i32 },
|
|
13
|
+
});
|
|
14
|
+
if (libc.symbols.flock(fd, 2) !== 0) throw new Error('failed to acquire lock');
|
|
15
|
+
process.stdout.write('locked\n');
|
|
16
|
+
await new Promise<void>(() => { setInterval(() => {}, 1000); });
|
|
17
|
+
} else {
|
|
18
|
+
throw new Error(`unknown fixture mode: ${mode}`);
|
|
19
|
+
}
|