rvlib-shipkit 0.38.0 → 1.0.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 +371 -16
- package/README.md +26 -14
- package/package.json +2 -2
- package/src/assets/gen/comfyts-gen.ts +27 -10
- package/src/assets/gen/generate-roll.ts +1 -1
- package/src/assets/kit-config.ts +6 -6
- package/src/assets/run-assets.ts +14 -10
- package/src/assets/server/studio-server.ts +6 -5
- package/src/check.ts +343 -0
- package/src/{rules/SK001-package-json-shape.ts → checks/SK001-package-json-shape.check.ts} +44 -46
- package/src/checks/SK002-contracts-fulfillness.check.ts +24 -0
- package/src/checks/SK003-claude-md-shape.check.ts +66 -0
- package/src/checks/SK004-gitignore-policy.check.ts +309 -0
- package/src/{rules/SK005-rvlib-versions.ts → checks/SK005-rvlib-versions.check.ts} +46 -32
- package/src/{rules/SK006-npm-publish-safety.ts → checks/SK006-npm-publish-safety.check.ts} +25 -24
- package/src/{rules/SK007-github-visibility.ts → checks/SK007-github-visibility.check.ts} +20 -14
- package/src/{rules/SK008-reviewer-agent.ts → checks/SK008-reviewer-agent.check.ts} +29 -14
- package/src/{rules/SK009-commit-ai-tells.ts → checks/SK009-commit-ai-tells.check.ts} +24 -21
- package/src/checks/SK010-undeclared-unit.check.ts +111 -0
- package/src/{rules/SK011-sibling-unit-ranges.ts → checks/SK011-sibling-unit-ranges.check.ts} +21 -20
- package/src/{rules/SK012-config-barrel-import.ts → checks/SK012-config-barrel-import.check.ts} +18 -23
- package/src/{rules/SK013-one-way-in-policy.ts → checks/SK013-one-way-in-policy.check.ts} +58 -50
- package/src/{rules/SK014-prose-ste.ts → checks/SK014-prose-ste.check.ts} +27 -13
- package/src/{rules/SK015-nested-repo.ts → checks/SK015-nested-repo.check.ts} +15 -12
- package/src/checks/SK016-legacy-check-shapes.check.ts +182 -0
- package/src/checks/SK017-vscode-hub-task.check.ts +197 -0
- package/src/checks/SK018-test-files-run.check.ts +28 -0
- package/src/checks/SK019-tests-run-in-units.check.ts +76 -0
- package/src/checks/SK020-self-spawning-check.check.ts +147 -0
- package/src/checks/contracts.check.ts +20 -0
- package/src/cli/cmd_Asks.ts +3 -2
- package/src/cli/cmd_Assets.ts +2 -2
- package/src/cli/cmd_Bump.ts +1 -1
- package/src/cli/cmd_Check.ts +6 -6
- package/src/cli/cmd_Checks.ts +95 -0
- package/src/cli/cmd_Ci.ts +48 -13
- package/src/cli/cmd_Commands.ts +2 -6
- package/src/cli/cmd_ConfigKeys.ts +69 -0
- package/src/cli/cmd_Contracts.ts +1 -1
- package/src/cli/cmd_Fleet.ts +6 -2
- package/src/cli/cmd_Hooks.ts +1 -1
- package/src/cli/cmd_Keys.ts +43 -18
- package/src/cli/cmd_Mv.ts +2 -2
- package/src/cli/cmd_Prose.ts +10 -1
- package/src/cli/cmd_Releases.ts +2 -2
- package/src/cli/cmd_Serve.ts +1 -1
- package/src/cli/cmd_Start.ts +6 -6
- package/src/cli/cmd_Status.ts +25 -0
- package/src/cli/cmd_Tui.ts +2 -2
- package/src/cli.ts +7 -4
- package/src/collections/actions.ts +4 -4
- package/src/collections/checks.ts +258 -0
- package/src/collections/collection-types.ts +254 -1
- package/src/collections/comfy.ts +23 -0
- package/src/collections/md-body.ts +14 -0
- package/src/collections/pings.ts +38 -12
- package/src/collections/posts.ts +19 -3
- package/src/collections/providers.ts +198 -91
- package/src/collections/reflections.ts +41 -0
- package/src/collections/state-rules.ts +73 -0
- package/src/collections/test-time.ts +288 -0
- package/src/collections/tests.ts +181 -0
- package/src/collections/wikis.ts +66 -0
- package/src/comfy/comfy-panel.ts +292 -0
- package/src/contracts/apply-contracts.ts +17 -12
- package/src/contracts/contract-types.ts +16 -4
- package/src/contracts/contracts-engine.ts +78 -42
- package/src/contracts/manifests/discord.contract.ts +6 -6
- package/src/contracts/manifests/identity.contract.ts +3 -3
- package/src/contracts/manifests/itch.contract.ts +12 -15
- package/src/contracts/manifests/social.contract.ts +5 -5
- package/src/contracts/manifests/steam.contract.ts +16 -16
- package/src/contracts/run-contracts.ts +4 -3
- package/src/core/attach.ts +96 -0
- package/src/core/canonical-scripts.ts +25 -0
- package/src/core/check-ctx.ts +204 -14
- package/src/core/check-file-names.ts +112 -0
- package/src/core/check-pass.ts +84 -0
- package/src/core/check-runner.ts +796 -0
- package/src/core/config-keys.ts +256 -0
- package/src/core/config-rewrite.ts +77 -0
- package/src/core/discover-checks.ts +166 -90
- package/src/core/discover-legacy-checks.ts +26 -0
- package/src/core/doc-block.ts +13 -0
- package/src/core/floor-resolve.ts +264 -0
- package/src/core/floor.ts +20 -137
- package/src/core/git-bin.ts +24 -0
- package/src/core/git-root.ts +108 -0
- package/src/core/instance.ts +195 -0
- package/src/core/jobs.ts +118 -0
- package/src/core/layout.ts +52 -0
- package/src/core/legacy-shapes.ts +207 -0
- package/src/core/lib-root.ts +5 -0
- package/src/core/locked-write.ts +110 -39
- package/src/core/machine-commit.ts +5 -4
- package/src/core/migrate-layout.ts +557 -0
- package/src/core/motherhome.ts +2 -8
- package/src/core/nesting.ts +4 -12
- package/src/core/one-way-in-policy.ts +73 -17
- package/src/core/outcome-words.ts +45 -0
- package/src/core/package-manager.ts +86 -0
- package/src/core/parallel.ts +21 -0
- package/src/core/process-tree.ts +44 -0
- package/src/core/raw-access.ts +93 -0
- package/src/core/read-set.ts +152 -0
- package/src/core/run-check.ts +155 -213
- package/src/core/run-ci.ts +153 -189
- package/src/core/run-fix.ts +96 -0
- package/src/core/run-fixers.ts +53 -30
- package/src/core/self-update.ts +9 -3
- package/src/core/slots.ts +83 -0
- package/src/core/spawn-timeout.ts +34 -3
- package/src/core/when-block.ts +401 -0
- package/src/core/when.ts +135 -0
- package/src/core/write-status.ts +5 -2
- package/src/hooks/leak-guard.ts +10 -8
- package/src/hooks/one-way-in-guard.ts +13 -5
- package/src/hooks/root-identity.ts +2 -1
- package/src/hooks/run-hooks.ts +35 -23
- package/src/init-repo.ts +39 -23
- package/src/ledger/check-stats.ts +155 -0
- package/src/ledger/check-table.ts +179 -0
- package/src/ledger/db.ts +255 -0
- package/src/ledger/gate-checks.ts +433 -0
- package/src/ledger/git-key.ts +116 -77
- package/src/ledger/git-scan.ts +96 -35
- package/src/ledger/ledger.ts +116 -42
- package/src/ledger/live-runs.ts +111 -0
- package/src/ledger/live-timeline.ts +97 -0
- package/src/ledger/repo-view.ts +73 -0
- package/src/ledger/run-log.ts +448 -0
- package/src/ledger/run-timeline.ts +173 -0
- package/src/ledger/store.ts +23 -12
- package/src/ledger/suite-log.ts +161 -0
- package/src/ledger/toolchain-identity.ts +7 -1
- package/src/ledger/world-cache.ts +111 -0
- package/src/mv/mv-md.ts +16 -6
- package/src/problems/extract.ts +182 -0
- package/src/problems/problem-board.ts +37 -0
- package/src/problems/problem-line.ts +77 -0
- package/src/prose/prose-view.ts +90 -0
- package/src/prose/run-prose.ts +60 -19
- package/src/prose/ste.ts +140 -24
- package/src/reflections/reflections-queue.ts +81 -0
- package/src/release/git-facts.ts +15 -9
- package/src/release/run-bump.ts +6 -5
- package/src/release/run-release.ts +25 -11
- package/src/release/run-releases.ts +2 -2
- package/src/release/unit-gate.ts +7 -54
- package/src/release/unit-resolve.ts +282 -0
- package/src/release/units.ts +33 -217
- package/src/repo-config.ts +155 -85
- package/src/rules/rule.ts +36 -96
- package/src/rules/untrack-generated.ts +5 -4
- package/src/scaffold/files/vscode-tasks.json +10 -31
- package/src/scaffold/jsonc-spans.ts +113 -0
- package/src/scaffold/project-scaffold.ts +16 -43
- package/src/scan.ts +98 -0
- package/src/serve/gate-trigger.ts +148 -0
- package/src/serve/health-schedule.ts +102 -0
- package/src/serve/hub-app/chart-view.ts +179 -0
- package/src/serve/hub-app/check-view.tsx +345 -0
- package/src/serve/hub-app/check-words.ts +164 -0
- package/src/serve/hub-app/checks-svc.ts +280 -0
- package/src/serve/hub-app/clock-svc.ts +33 -0
- package/src/serve/hub-app/col-card.tsx +23 -39
- package/src/serve/hub-app/cols-svc.ts +44 -20
- package/src/serve/hub-app/comfy-svc.ts +171 -0
- package/src/serve/hub-app/comfy-view.tsx +81 -0
- package/src/serve/hub-app/dur.ts +41 -0
- package/src/serve/hub-app/hash-route.ts +121 -0
- package/src/serve/hub-app/header-bar.tsx +117 -0
- package/src/serve/hub-app/health-svc.ts +23 -28
- package/src/serve/hub-app/help.tsx +29 -0
- package/src/serve/hub-app/hub-app.tsx +122 -119
- package/src/serve/hub-app/hub-st.ts +115 -42
- package/src/serve/hub-app/hub-types.ts +117 -2
- package/src/serve/hub-app/hub.css +534 -192
- package/src/serve/hub-app/index.html +2 -0
- package/src/serve/hub-app/live-svc.ts +174 -0
- package/src/serve/hub-app/md.ts +15 -0
- package/src/serve/hub-app/media-svc.ts +4 -1
- package/src/serve/hub-app/media-view.tsx +15 -0
- package/src/serve/hub-app/next-run.ts +68 -0
- package/src/serve/hub-app/project-gutter.css +65 -0
- package/src/serve/hub-app/project-gutter.tsx +128 -0
- package/src/serve/hub-app/projects-svc.ts +226 -0
- package/src/serve/hub-app/prose-hits-st.ts +124 -0
- package/src/serve/hub-app/prose-hits-view.tsx +176 -0
- package/src/serve/hub-app/prose-hits.css +21 -0
- package/src/serve/hub-app/run-strip.ts +47 -0
- package/src/serve/hub-app/runs-tabs.ts +24 -0
- package/src/serve/hub-app/test-view.tsx +107 -0
- package/src/serve/hub-app/tests-svc.ts +62 -0
- package/src/serve/hub-app/tests-view.tsx +238 -0
- package/src/serve/hub-app/time-ago.tsx +34 -0
- package/src/serve/hub-app/timeline-chart.tsx +274 -0
- package/src/serve/hub-app/timeline-geometry.ts +314 -0
- package/src/serve/hub-app/timeline-svc.ts +62 -0
- package/src/serve/hub-app/timeline-view.tsx +245 -0
- package/src/serve/hub-app/tree-build.ts +410 -0
- package/src/serve/hub-app/tree-row.tsx +42 -0
- package/src/serve/hub-app/tree-svc.ts +174 -0
- package/src/serve/hub-app/wikis-view.tsx +53 -0
- package/src/serve/other-repos.ts +79 -0
- package/src/serve/project-gutter-route.ts +350 -0
- package/src/serve/project-gutter.ts +449 -0
- package/src/serve/run-serve.ts +245 -16
- package/src/serve/same-origin.ts +14 -0
- package/src/serve/serve-hub.ts +213 -18
- package/src/shipkit.ts +19 -12
- package/src/smoke/run-smoke.ts +3 -2
- package/src/start-repo.ts +75 -36
- package/src/suite/judge-suites.ts +216 -18
- package/src/suite/kept-timings.ts +58 -0
- package/src/suite/runner-shapes.ts +88 -0
- package/src/suite/suite-cli.ts +147 -24
- package/src/suite/suite-cpu-preload.ts +92 -0
- package/src/suite/test-units.ts +243 -0
- package/src/ts/config.ts +4 -69
- package/src/ts/jsonc.ts +69 -0
- package/src/ts/lex.ts +143 -0
- package/src/ts/rename.ts +73 -10
- package/src/ts/source-graph.ts +28 -8
- package/src/ts/tsconfig-projects.ts +6 -97
- package/src/ts/tsconfig-resolve.ts +108 -0
- package/src/tui/build-steps-panel.ts +61 -0
- package/src/tui/checks-panel.ts +24 -16
- package/src/tui/run-tui.ts +2 -2
- package/src/tui/tui-panel.ts +5 -4
- package/src/wiki/graph-colors.ts +68 -0
- package/src/wiki/graph-mount.ts +7 -9
- package/src/wiki/graph-page.ts +42 -25
- package/src/wiki/graph-positions.ts +105 -0
- package/src/wiki/run-wiki.ts +1 -1
- package/src/wiki/serve-graph.ts +33 -3
- package/src/cli/cmd_Rules.ts +0 -51
- package/src/cli/cmd_Units.ts +0 -82
- package/src/collections/graphs.ts +0 -32
- package/src/contracts/contracts-once.ts +0 -43
- package/src/core/check-suite.ts +0 -302
- package/src/core/repair-contract-dirs.ts +0 -136
- package/src/core/task-runner.ts +0 -339
- package/src/ledger/gate-units.ts +0 -138
- package/src/ledger/unit-table.ts +0 -105
- package/src/rules/SK002-contracts-fulfillness.ts +0 -24
- package/src/rules/SK003-claude-md-shape.ts +0 -70
- package/src/rules/SK004-gitignore-policy.ts +0 -238
- package/src/rules/SK010-undeclared-release-unit.ts +0 -127
- package/src/rules/rule-registry.ts +0 -64
- package/src/rules/run-fix.ts +0 -72
- package/src/tui/tasks-panel.ts +0 -60
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
// HubSt — the ONE root store (build/app-state-tree: one central tree,
|
|
2
2
|
// instantiated once at boot, services with backrefs, exposed as
|
|
3
3
|
// window.app). Owns cross-service state: selection, the severity filter
|
|
4
|
-
// (an ADDRESS: /?f=needs · /?f=red), hash
|
|
5
|
-
//
|
|
4
|
+
// (an ADDRESS: /?f=needs · /?f=red), and the hash router: every page and
|
|
5
|
+
// every tab is a selection, every selection has an address (hash-route.ts),
|
|
6
|
+
// and setSel is the one place both move together.
|
|
7
|
+
import { RUNS_ID } from '../../collections/collection-types.ts'
|
|
6
8
|
import { makeAutoObservable } from 'mobx'
|
|
9
|
+
import { ClockSvc } from './clock-svc.ts'
|
|
7
10
|
import { ColsSvc } from './cols-svc.ts'
|
|
11
|
+
import { canonicalSel, currentHash, hashFor, parseHash, selOf, type HashSel } from './hash-route.ts'
|
|
12
|
+
import { ComfySvc } from './comfy-svc.ts'
|
|
8
13
|
import { HealthSvc } from './health-svc.ts'
|
|
14
|
+
import { LiveSvc } from './live-svc.ts'
|
|
9
15
|
import { MediaSvc } from './media-svc.ts'
|
|
16
|
+
import { TimelineSvc } from './timeline-svc.ts'
|
|
17
|
+
import { TreeSvc } from './tree-svc.ts'
|
|
18
|
+
import { ChecksSvc } from './checks-svc.ts'
|
|
19
|
+
import { ProjectsSvc } from './projects-svc.ts'
|
|
20
|
+
import { TestsSvc } from './tests-svc.ts'
|
|
21
|
+
import type { Resource } from './hub-types.ts'
|
|
10
22
|
|
|
11
|
-
export type Sel =
|
|
12
|
-
| { t: 'asset'; id: string }
|
|
13
|
-
| { t: 'cat'; cat: string }
|
|
14
|
-
| { t: 'col'; id: string }
|
|
15
|
-
| { t: 'item'; col: string; id: string }
|
|
16
|
-
| { t: 'status' }
|
|
17
|
-
| null
|
|
23
|
+
export type Sel = HashSel | null
|
|
18
24
|
|
|
19
25
|
/** one cmd+j target — run() fires the SAME action clicking would */
|
|
20
26
|
export type Jump = { id: string; label: string; section: string; run: () => void }
|
|
@@ -28,9 +34,23 @@ const parseFilter = (search: string): Filter => {
|
|
|
28
34
|
|
|
29
35
|
export class HubSt {
|
|
30
36
|
name = ''
|
|
37
|
+
/** where this repo sits on disk, from /hub.json: what makes a source
|
|
38
|
+
* path on a page a link that opens his editor */
|
|
39
|
+
root = ''
|
|
40
|
+
/** the one second tick every age on the page reads (clock-svc.ts) */
|
|
41
|
+
clock = new ClockSvc()
|
|
31
42
|
media = new MediaSvc(this)
|
|
32
43
|
cols = new ColsSvc(this)
|
|
44
|
+
tree = new TreeSvc(this)
|
|
33
45
|
health = new HealthSvc(this)
|
|
46
|
+
checks = new ChecksSvc(this)
|
|
47
|
+
comfy = new ComfySvc(this)
|
|
48
|
+
timeline = new TimelineSvc(this)
|
|
49
|
+
/** the runs in flight, whoever started them (live-svc.ts) */
|
|
50
|
+
live = new LiveSvc(this)
|
|
51
|
+
projects = new ProjectsSvc(this)
|
|
52
|
+
/** the pages behind the test groups of the tree (tests-svc.ts) */
|
|
53
|
+
tests = new TestsSvc(this)
|
|
34
54
|
sel: Sel = null
|
|
35
55
|
filter: Filter = parseFilter(location.search)
|
|
36
56
|
/** sidebar search — live substring filter over asset + collection rows */
|
|
@@ -41,21 +61,30 @@ export class HubSt {
|
|
|
41
61
|
private booted = false
|
|
42
62
|
|
|
43
63
|
constructor() {
|
|
44
|
-
makeAutoObservable<this, 'booted'>(this, { media: false, cols: false, health: false, booted: false })
|
|
64
|
+
makeAutoObservable<this, 'booted'>(this, { media: false, cols: false, tree: false, health: false, checks: false, comfy: false, timeline: false, live: false, projects: false, tests: false, booted: false })
|
|
45
65
|
}
|
|
46
66
|
|
|
47
67
|
boot(): void {
|
|
48
68
|
void fetch('/hub.json')
|
|
49
|
-
.then((r) => r.json() as Promise<{ name: string }>)
|
|
50
|
-
.then((h) => { this.
|
|
69
|
+
.then((r) => r.json() as Promise<{ name: string; root?: string }>)
|
|
70
|
+
.then((h) => { this.setHub(h.name, h.root ?? '') })
|
|
51
71
|
.catch(() => {})
|
|
72
|
+
this.clock.start()
|
|
52
73
|
this.media.start()
|
|
53
74
|
this.cols.start()
|
|
75
|
+
this.live.start()
|
|
76
|
+
void this.checks.loadGate()
|
|
54
77
|
void this.health.load()
|
|
78
|
+
// back, forward, a pasted link and a hand edited hash all arrive
|
|
79
|
+
// here; applyHash is idempotent, so the two events firing together
|
|
80
|
+
// for one move cost nothing
|
|
55
81
|
window.addEventListener('hashchange', () => this.applyHash())
|
|
82
|
+
window.addEventListener('popstate', () => this.applyHash())
|
|
83
|
+
this.applyHash()
|
|
56
84
|
}
|
|
57
|
-
private
|
|
85
|
+
private setHub(n: string, root: string): void {
|
|
58
86
|
this.name = n
|
|
87
|
+
this.root = root
|
|
59
88
|
document.title = `${n} · hub`
|
|
60
89
|
}
|
|
61
90
|
|
|
@@ -102,6 +131,8 @@ export class HubSt {
|
|
|
102
131
|
out.push({ id: `cat:${cat}`, label: cat, section: 'media', run: () => this.showCat(cat) })
|
|
103
132
|
for (const a of this.media.assets)
|
|
104
133
|
out.push({ id: `asset:${a.id}`, label: a.label, section: a.cat, run: () => this.selectAsset(a.id) })
|
|
134
|
+
// the runs page is a page, not a resource, so no collection lists it
|
|
135
|
+
out.push({ id: 'page:runs', label: 'runs', section: 'page', run: () => this.cols.select('runs', RUNS_ID) })
|
|
105
136
|
for (const col of this.cols.sidebarCols) {
|
|
106
137
|
const health = col.id === 'health'
|
|
107
138
|
out.push({ id: `col:${col.id}`, label: col.title, section: 'section', run: () => (health ? this.showStatus() : this.showCol(col.id)) })
|
|
@@ -125,49 +156,91 @@ export class HubSt {
|
|
|
125
156
|
}
|
|
126
157
|
|
|
127
158
|
// ── selection + hash deep-links ───────────────────────────────────────
|
|
128
|
-
selectAsset(id: string
|
|
129
|
-
this.
|
|
130
|
-
if (writeHash) this.setHash(id)
|
|
159
|
+
selectAsset(id: string): void {
|
|
160
|
+
this.setSel({ t: 'asset', id })
|
|
131
161
|
void this.media.select(id)
|
|
132
162
|
}
|
|
133
|
-
showCat(cat: string
|
|
134
|
-
this.
|
|
163
|
+
showCat(cat: string): void {
|
|
164
|
+
this.setSel({ t: 'cat', cat })
|
|
135
165
|
this.media.openCats.add(cat)
|
|
136
|
-
if (writeHash) this.setHash(`cat-${cat}`)
|
|
137
166
|
void this.media.fillCat()
|
|
138
167
|
}
|
|
139
168
|
showStatus(): void {
|
|
140
|
-
this.
|
|
169
|
+
this.setSel({ t: 'status' })
|
|
141
170
|
void this.health.load()
|
|
142
171
|
}
|
|
172
|
+
/** where the test checks' time goes: the `tests` group (null) or one test
|
|
173
|
+
* check's group. Fetched as the page opens, never on the poll */
|
|
174
|
+
showTests(check: string | null): void {
|
|
175
|
+
this.setSel({ t: 'tests', check })
|
|
176
|
+
void this.tests.load(check)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** the ONE place a selection is written, so the url always describes what
|
|
180
|
+
* is on screen. A new page is a history entry, so back returns to the
|
|
181
|
+
* page before it. The same address is never pushed twice: applyHash
|
|
182
|
+
* lands here too, with the hash already naming this selection */
|
|
183
|
+
setSel(sel: Sel): void {
|
|
184
|
+
this.sel = sel
|
|
185
|
+
const h = hashFor(sel)
|
|
186
|
+
if (h == null) return
|
|
187
|
+
const cur = parseHash(currentHash())
|
|
188
|
+
const next = parseHash(h)
|
|
189
|
+
// the tool set rides after the asset id (media-svc syncHash), so an
|
|
190
|
+
// address is the same page whatever tools it carries
|
|
191
|
+
if (cur.kind === next.kind && cur.col === next.col && cur.id === next.id) return
|
|
192
|
+
history.pushState(null, '', `#${h}`)
|
|
193
|
+
}
|
|
194
|
+
/** one tree row, opened: an asset goes to the atelier, everything else to
|
|
195
|
+
* its own item card. A gate check has a page of its own now, so nothing
|
|
196
|
+
* lands on the raw wall of text unless it is asked for by name */
|
|
197
|
+
openResource(r: Resource): void {
|
|
198
|
+
const assetId = r.id.replace(/^media:/, '')
|
|
199
|
+
if (r.collection === 'media' && this.media.assets.some((a) => a.id === assetId)) {
|
|
200
|
+
this.selectAsset(assetId)
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
this.cols.select(r.collection, r.id)
|
|
204
|
+
}
|
|
205
|
+
|
|
143
206
|
/** collection view — one card per instance (health has StatusCard instead) */
|
|
144
207
|
showCol(id: string): void {
|
|
145
|
-
this.
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
208
|
+
this.setSel({ t: 'col', id })
|
|
209
|
+
}
|
|
210
|
+
/** open whatever a selection names, through the same calls a click makes */
|
|
211
|
+
go(sel: HashSel): void {
|
|
212
|
+
switch (sel.t) {
|
|
213
|
+
case 'asset': return this.selectAsset(sel.id)
|
|
214
|
+
case 'cat': return this.showCat(sel.cat)
|
|
215
|
+
case 'col': return this.showCol(sel.id)
|
|
216
|
+
case 'item': return this.cols.select(sel.col, sel.id)
|
|
217
|
+
case 'status': return this.showStatus()
|
|
218
|
+
case 'tests': return this.showTests(sel.check)
|
|
219
|
+
}
|
|
149
220
|
}
|
|
221
|
+
/** the url decides the page: a reload, back, forward and a pasted link
|
|
222
|
+
* all land here, and only a hash naming something else moves the view */
|
|
150
223
|
applyHash(): void {
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
this.media.pendingTools = list
|
|
165
|
-
this.selectAsset(h, false)
|
|
166
|
-
} else if (this.media.curId === h && list != null) {
|
|
167
|
-
// same asset, new tool set (a pasted share link) — apply NOW; a
|
|
224
|
+
const p = parseHash(currentHash())
|
|
225
|
+
const named = selOf(p)
|
|
226
|
+
if (named == null) return
|
|
227
|
+
// an address naming what this build opens under another address is
|
|
228
|
+
// rewritten in place: a replace, so back never lands on the stale one
|
|
229
|
+
const sel = canonicalSel(named)
|
|
230
|
+
if (sel !== named) history.replaceState(null, '', `#${hashFor(sel)}`)
|
|
231
|
+
// media addresses resolve only once the first heartbeat listed the
|
|
232
|
+
// assets (afterFirstBeat calls back)
|
|
233
|
+
if (sel.t === 'asset' && !this.media.assets.some((a) => a.id === sel.id)) return
|
|
234
|
+
if (sel.t === 'cat' && !this.media.assets.some((a) => a.cat === sel.cat)) return
|
|
235
|
+
if (sel.t === 'asset' && this.media.curId === sel.id) {
|
|
236
|
+
// same asset, new tool set (a pasted share link): apply NOW, a
|
|
168
237
|
// parked pendingTools would hijack the next selection instead
|
|
169
|
-
this.media.applyTab(
|
|
238
|
+
if (p.tools != null) this.media.applyTab(p.tools)
|
|
239
|
+
return
|
|
170
240
|
}
|
|
241
|
+
if (hashFor(sel) === hashFor(this.sel)) return
|
|
242
|
+
if (sel.t === 'asset') this.media.pendingTools = p.tools
|
|
243
|
+
this.go(sel)
|
|
171
244
|
}
|
|
172
245
|
/** first heartbeat has the asset list — only then can a hash resolve */
|
|
173
246
|
afterFirstBeat(): void {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Wire types the hub app reads — mirrors of the server shapes
|
|
2
2
|
// (studio-server.ts, collection-types.ts). Kept structural on purpose: the
|
|
3
3
|
// page renders what the API sends, the file is the truth.
|
|
4
|
+
import type { ResourceType, SuiteFacts, TestFacts, TestRun } from '../../collections/collection-types.ts'
|
|
4
5
|
|
|
5
6
|
export type SideAsset = {
|
|
6
7
|
id: string
|
|
@@ -57,9 +58,118 @@ export type QueueState = {
|
|
|
57
58
|
|
|
58
59
|
export type Candidate = { id: string; label: string; hint?: string }
|
|
59
60
|
export type Artifact = { copy?: string; url?: string; steps?: string[] }
|
|
60
|
-
|
|
61
|
+
/** the resource kind, never the collection: one folder holds several kinds.
|
|
62
|
+
* The list lives where the providers that emit it live, so a kind can never
|
|
63
|
+
* be known on one side of the wire only. Type only, so nothing server side
|
|
64
|
+
* reaches the bundle */
|
|
65
|
+
export type { ResourceType, SuiteFacts, TestFacts, TestRun }
|
|
66
|
+
|
|
67
|
+
export type CheckStatus = 'pass' | 'warn' | 'fail' | 'skip'
|
|
68
|
+
|
|
69
|
+
/** one outcome of one check, as the page draws it */
|
|
70
|
+
export type RecentRun = { at: number; ms: number; status: CheckStatus; replayed: boolean }
|
|
71
|
+
|
|
72
|
+
// the page reads the SERVER's words for these, type-only so nothing of the
|
|
73
|
+
// engine reaches the bundle: two declarations of one vocabulary is how a
|
|
74
|
+
// switch ends up writing a word the other half does not know
|
|
75
|
+
import type { WhenAt, WhenSource } from '../../core/when.ts'
|
|
76
|
+
import type { CheckFrom } from '../../check.ts'
|
|
77
|
+
export type { CheckFrom, WhenAt, WhenSource }
|
|
78
|
+
|
|
79
|
+
/** a gate check's declaration and its numbers (collections/collection-types.ts
|
|
80
|
+
* CheckFacts is the source; this is the wire mirror the page reads) */
|
|
81
|
+
export type CheckFacts = {
|
|
82
|
+
checkId: string
|
|
83
|
+
/** the check's one line description (the shape: check.ts
|
|
84
|
+
* descriptionProblem). Every inventory row carries one */
|
|
85
|
+
description: string
|
|
86
|
+
/** the wire lines of its last run, rendered as inline markdown */
|
|
87
|
+
lastLines: string[]
|
|
88
|
+
gate: boolean
|
|
89
|
+
/** a build step: the gate runs it, the health pass does not */
|
|
90
|
+
build: boolean
|
|
91
|
+
blocking: boolean | null
|
|
92
|
+
advisory: boolean
|
|
93
|
+
optIn: boolean
|
|
94
|
+
when: WhenAt
|
|
95
|
+
whenReason: string | null
|
|
96
|
+
whenSource: WhenSource
|
|
97
|
+
file: string | null
|
|
98
|
+
doc: string | null
|
|
99
|
+
cmd: string[] | null
|
|
100
|
+
script?: { name: string; body: string } | null
|
|
101
|
+
deps: string[] | null
|
|
102
|
+
from: CheckFrom
|
|
103
|
+
group: string | null
|
|
104
|
+
inputs?: string[]
|
|
105
|
+
ttl?: string
|
|
106
|
+
never?: string
|
|
107
|
+
timeoutMs: number
|
|
108
|
+
status: CheckStatus | null
|
|
109
|
+
replayed: boolean
|
|
110
|
+
lastMs: number | null
|
|
111
|
+
lastAt: number | null
|
|
112
|
+
avgMs: number | null
|
|
113
|
+
samples: number
|
|
114
|
+
slowestMs: number | null
|
|
115
|
+
failures: number
|
|
116
|
+
/** when it was last measured rather than replayed, and what that said */
|
|
117
|
+
measuredAt?: number | null
|
|
118
|
+
measuredStatus?: CheckStatus | null
|
|
119
|
+
/** a world probe only: when its remembered answer runs out */
|
|
120
|
+
keepsUntil?: number | null
|
|
121
|
+
recent?: RecentRun[]
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** the hub's daily health pass timer, as the resources feed sends it
|
|
125
|
+
* (serve/health-schedule.ts). null = this hub runs no timer */
|
|
126
|
+
export type Schedule = { everyMs: number; lastPassAt: number | null; nextAt: number; running: boolean }
|
|
127
|
+
|
|
128
|
+
/** one declared slow suite, with the case test-speed doctrine demands */
|
|
129
|
+
export type SlowSuite = { file: string; catches: string; whyNotFast: string }
|
|
130
|
+
|
|
131
|
+
/** the managed block in repo.config.ts, as the page sees it. `hash` is what
|
|
132
|
+
* the next write hands back, so a write can never land on top of an edit the
|
|
133
|
+
* page never saw. `dirty` is the file waiting for a commit */
|
|
134
|
+
export type GateBlock = {
|
|
135
|
+
path: string
|
|
136
|
+
hash: string
|
|
137
|
+
state: 'missing-file' | 'missing-block' | 'stale' | 'current'
|
|
138
|
+
when: Record<string, string>
|
|
139
|
+
tests: { budgetMs?: number; slow?: SlowSuite[]; serial?: { file: string; why: string }[] }
|
|
140
|
+
declaredOutside: boolean
|
|
141
|
+
dirty: boolean
|
|
142
|
+
/** the prose words block inside `prose: {` (core/when-block.ts) */
|
|
143
|
+
wordsState?: 'missing-file' | 'missing-block' | 'stale' | 'current' | 'no-prose'
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** one check finishing, as the run stream sends it */
|
|
147
|
+
export type CheckEvent = {
|
|
148
|
+
id: string
|
|
149
|
+
name: string
|
|
150
|
+
status: CheckStatus
|
|
151
|
+
ms: number
|
|
152
|
+
replayed: boolean
|
|
153
|
+
blocking: boolean | null
|
|
154
|
+
advisory: boolean
|
|
155
|
+
lines: { kind: string; text: string }[]
|
|
156
|
+
}
|
|
157
|
+
/** the colour of the tree label: red broken · warn taste pending · ok
|
|
158
|
+
* passing on a check that ran · idle the neutral default · quiet archived or out of play */
|
|
159
|
+
export type ResourceState = 'red' | 'warn' | 'ok' | 'idle' | 'quiet'
|
|
160
|
+
export type Resource = {
|
|
61
161
|
id: string
|
|
162
|
+
collection: string
|
|
163
|
+
type: ResourceType
|
|
164
|
+
/** a slash path: the truth file, or a virtual root named for the type */
|
|
165
|
+
path: string
|
|
166
|
+
virtual?: boolean
|
|
167
|
+
title: string
|
|
168
|
+
state: ResourceState
|
|
62
169
|
text: string
|
|
170
|
+
/** the ONE short fact the tree shows in its note slot (an ask its kind, a
|
|
171
|
+
* secret present or missing, a post its venue, an asset its roll count) */
|
|
172
|
+
slot?: string
|
|
63
173
|
severity?: 'red' | 'yellow'
|
|
64
174
|
href?: string
|
|
65
175
|
artifact?: Artifact
|
|
@@ -70,5 +180,10 @@ export type ColInstance = {
|
|
|
70
180
|
/** the truth file's markdown BODY (frontmatter stripped) — clamped card
|
|
71
181
|
* in the grid, full in the item view */
|
|
72
182
|
md?: string
|
|
183
|
+
/** gate checks only: what it is, and what it last cost */
|
|
184
|
+
check?: CheckFacts
|
|
185
|
+
/** test files only: where it runs and what it last cost */
|
|
186
|
+
test?: TestFacts
|
|
73
187
|
}
|
|
74
|
-
export type
|
|
188
|
+
export type ColMeta = { id: string; title: string; media: string }
|
|
189
|
+
export type Col = ColMeta & { instances: Resource[] }
|