rvlib-shipkit 2.2.0 → 2.3.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 +38 -0
- package/package.json +1 -1
- package/src/agent-time/mask.ts +43 -0
- package/src/agent-time/render.ts +187 -0
- package/src/agent-time/report.ts +335 -0
- package/src/agent-time/shape.ts +271 -0
- package/src/agent-time/signals.ts +84 -0
- package/src/agent-time/store.ts +379 -0
- package/src/agent-time/timeline.ts +218 -0
- package/src/agent-time/turns.ts +135 -0
- package/src/cli/cmd_Commands.ts +5 -0
- package/src/cli/cmd_Review.ts +948 -0
- package/src/cli/cmd_Time.ts +112 -0
- package/src/cli/cmd_Trailer.ts +259 -6
- package/src/cli/kit/verb.ts +14 -4
- package/src/cli.ts +6 -4
- package/src/collections/collection-types.ts +6 -1
- package/src/collections/providers.ts +3 -0
- package/src/collections/review.ts +70 -0
- package/src/core/layout.ts +2 -0
- package/src/reflect/prompt-corpus.ts +15 -119
- package/src/reflect/transcript.ts +254 -0
- package/src/review/anim.ts +228 -0
- package/src/review/auto.ts +141 -0
- package/src/review/format.ts +150 -0
- package/src/review/http.ts +23 -0
- package/src/review/marks.ts +43 -0
- package/src/review/media.ts +45 -0
- package/src/review/model.ts +854 -0
- package/src/review/project.ts +110 -0
- package/src/review/role.ts +48 -0
- package/src/review/routes.ts +228 -0
- package/src/review/store.ts +1002 -0
- package/src/review/threads.ts +237 -0
- package/src/review/trailer-desk.ts +385 -0
- package/src/review/trailer-model.ts +183 -0
- package/src/review/trailer-routes.ts +136 -0
- package/src/review/unit.ts +165 -0
- package/src/review/watchers.ts +54 -0
- package/src/serve/embed.ts +35 -0
- package/src/serve/hub-app/activity-view.tsx +1 -1
- package/src/serve/hub-app/activity.css +0 -4
- package/src/serve/hub-app/dock-view.tsx +5 -4
- package/src/serve/hub-app/hash-route.ts +28 -1
- package/src/serve/hub-app/header-bar.tsx +3 -1
- package/src/serve/hub-app/home-st.ts +10 -2
- package/src/serve/hub-app/home-strip.tsx +3 -2
- package/src/serve/hub-app/home.html +1 -0
- package/src/serve/hub-app/hub-app.tsx +80 -11
- package/src/serve/hub-app/hub.css +45 -13
- package/src/serve/hub-app/icons.tsx +9 -0
- package/src/serve/hub-app/index.html +1 -0
- package/src/serve/hub-app/insights-view.tsx +4 -3
- package/src/serve/hub-app/keys.ts +14 -10
- package/src/serve/hub-app/layout-st.ts +63 -2
- package/src/serve/hub-app/planned-view.tsx +3 -2
- package/src/serve/hub-app/planned.css +0 -1
- package/src/serve/hub-app/project-list.css +22 -4
- package/src/serve/hub-app/project-list.tsx +41 -8
- package/src/serve/hub-app/projects-svc.ts +4 -0
- package/src/serve/hub-app/repo-sections.ts +15 -3
- package/src/serve/hub-app/repo-st.ts +45 -3
- package/src/serve/hub-app/review/clip-st.ts +208 -0
- package/src/serve/hub-app/review/kind-view.tsx +171 -0
- package/src/serve/hub-app/review/kit.tsx +113 -0
- package/src/serve/hub-app/review/review-answer.tsx +239 -0
- package/src/serve/hub-app/review/review-board.tsx +46 -0
- package/src/serve/hub-app/review/review-list.tsx +156 -0
- package/src/serve/hub-app/review/review-page.tsx +101 -0
- package/src/serve/hub-app/review/review-st.ts +779 -0
- package/src/serve/hub-app/review/review-views.tsx +503 -0
- package/src/serve/hub-app/review/trailer-page.tsx +416 -0
- package/src/serve/hub-app/review/trailer-st.ts +602 -0
- package/src/serve/hub-app/review/trailer-timeline.tsx +207 -0
- package/src/serve/hub-app/review.css +329 -0
- package/src/serve/hub-app/theme-st.ts +56 -0
- package/src/serve/hub-app/tree-build.ts +4 -0
- package/src/serve/hub-app/tree-row.tsx +1 -1
- package/src/serve/hub-app/tree-svc.ts +4 -0
- package/src/serve/hub-runtime.ts +5 -3
- package/src/serve/same-origin.ts +5 -1
- package/src/serve/serve-hub.ts +8 -0
- package/src/shipkit-files.ts +9 -5
- package/src/trailer/adapter.ts +58 -3
- package/src/trailer/build.ts +300 -41
- package/src/trailer/ffmpeg.ts +22 -0
- package/src/trailer/footage.ts +109 -40
- package/src/trailer/grammar.ts +444 -69
- package/src/trailer/graph.ts +199 -14
- package/src/trailer/holes.ts +72 -0
- package/src/trailer/load-unit.ts +20 -3
- package/src/trailer/look.ts +17 -3
- package/src/trailer/passage.ts +129 -0
- package/src/trailer/plan.ts +80 -21
- package/src/trailer/prune.ts +193 -0
- package/src/trailer/score/compose.ts +240 -0
- package/src/trailer/score/dsp.ts +272 -0
- package/src/trailer/score/palette.ts +188 -0
- package/src/trailer/score/pattern.ts +91 -0
- package/src/trailer/score/score.ts +214 -0
- package/src/trailer/score/sound.ts +112 -0
- package/src/trailer/score/synth.ts +361 -0
- package/src/trailer/states.ts +76 -0
- package/src/trailer/stitch.ts +92 -9
- package/src/trailer/titles.ts +123 -18
- package/src/trailer/vocab.ts +23 -4
- package/src/trailer/words.ts +254 -0
package/src/serve/hub-runtime.ts
CHANGED
|
@@ -58,6 +58,7 @@ import { hubHandler, type CheckTap, type HubDeps, type HubHandler } from './serv
|
|
|
58
58
|
import type { projectGutter } from './project-gutter-route.ts'
|
|
59
59
|
import { defaultHubPort } from './hub-port.ts'
|
|
60
60
|
import { LAYOUT } from '../core/layout.ts'
|
|
61
|
+
import { storeDir, storeStamp } from '../review/store.ts'
|
|
61
62
|
export { defaultHubPort }
|
|
62
63
|
|
|
63
64
|
export type ServeIo = { print: (l: string) => void; printErr: (l: string) => void }
|
|
@@ -347,9 +348,10 @@ export async function resolveHubDeps(root: string, boot: RepoConfig, io: ServeIo
|
|
|
347
348
|
graphs,
|
|
348
349
|
studio,
|
|
349
350
|
refresh,
|
|
350
|
-
// the config
|
|
351
|
-
//
|
|
352
|
-
|
|
351
|
+
// the config, the run record and the review store (gitignored, its
|
|
352
|
+
// own watch counts its writes): what the warm rows and the runs page
|
|
353
|
+
// read besides the tracked files the watch sees
|
|
354
|
+
stamp: () => `${configStamp(root)}|${record === '' ? '' : recordStamp(record)}|${storeStamp(storeDir(root))}`,
|
|
353
355
|
runCli,
|
|
354
356
|
// the run happens IN THIS PROCESS, so every check result reaches the
|
|
355
357
|
// page as it finishes. A shelled run could only ever deliver one wall
|
package/src/serve/same-origin.ts
CHANGED
|
@@ -10,5 +10,9 @@ export function sameOrigin(req: Request): boolean {
|
|
|
10
10
|
if (site != null && site !== 'same-origin' && site !== 'none') return false
|
|
11
11
|
const origin = req.headers.get('origin')
|
|
12
12
|
if (origin == null) return true
|
|
13
|
-
|
|
13
|
+
// behind a proxy that frames the page under its own origin (pkm-multi's admin), the host the browser asked is the
|
|
14
|
+
// proxy's, which it passes on. A browser cannot forge the header: a page of another site that sets it is held at
|
|
15
|
+
// its preflight, which this server never answers
|
|
16
|
+
const host = req.headers.get('x-forwarded-host') ?? new URL(req.url).host
|
|
17
|
+
try { return new URL(origin).host === host } catch { return false }
|
|
14
18
|
}
|
package/src/serve/serve-hub.ts
CHANGED
|
@@ -32,6 +32,8 @@ import { sameOrigin } from './same-origin.ts'
|
|
|
32
32
|
import { LAYOUT } from '../core/layout.ts'
|
|
33
33
|
import { WarmCell } from './warm-cell.ts'
|
|
34
34
|
import { readmeRoutes } from './readme-route.ts'
|
|
35
|
+
import { reviewRoutes } from '../review/routes.ts'
|
|
36
|
+
import { embedRoute } from './embed.ts'
|
|
35
37
|
|
|
36
38
|
export { sameOrigin }
|
|
37
39
|
|
|
@@ -338,6 +340,12 @@ export function hubHandler(d: HubDeps, o: { base?: string; projects?: Gutter } =
|
|
|
338
340
|
// the empty page shows the README, its images served from the repo
|
|
339
341
|
const readme = await readmeRoutes(d.root, path)
|
|
340
342
|
if (readme != null) return readme
|
|
343
|
+
// the review or trailer page alone, for another tool's frame (embed.ts)
|
|
344
|
+
const embed = await embedRoute(path)
|
|
345
|
+
if (embed != null) return embed
|
|
346
|
+
// the one feedback store and the trailer view (review/routes.ts)
|
|
347
|
+
const review = await reviewRoutes(d.root, req, path)
|
|
348
|
+
if (review != null) return review
|
|
341
349
|
if (path === '/api/status.json') {
|
|
342
350
|
const p = join(d.root, LAYOUT.status)
|
|
343
351
|
return Response.json({ statusMd: existsSync(p) ? await Bun.file(p).text() : null })
|
package/src/shipkit-files.ts
CHANGED
|
@@ -8,15 +8,19 @@
|
|
|
8
8
|
// on the home page
|
|
9
9
|
// trailer({...}) what `sk trailer` cannot read from a file: the
|
|
10
10
|
// sounds the repo resolves by id (trailer/adapter.ts)
|
|
11
|
+
// review({...}) the repo's parts of the review store: its subject
|
|
12
|
+
// kinds, topics, sources, auto rules, the dispatcher
|
|
13
|
+
// (review/unit.ts)
|
|
11
14
|
//
|
|
12
15
|
// the one constraint a reader breaks first: every kind is IMPORTED by the
|
|
13
16
|
// process that reads it (discovery, pm's config child, the daemon), so a file
|
|
14
17
|
// keeps its top level cheap and puts heavy work inside a function.
|
|
15
18
|
import { check, type CheckDef } from './check.ts'
|
|
19
|
+
import { review, type AutoRule, type KindDef, type ReviewDef, type ReviewSource, type ReviewUnit } from './review/unit.ts'
|
|
16
20
|
import { trailer, type TrailerDef, type TrailerUnit } from './trailer/adapter.ts'
|
|
17
21
|
|
|
18
|
-
export { check, trailer }
|
|
19
|
-
export type { TrailerDef, TrailerUnit }
|
|
22
|
+
export { check, review, trailer }
|
|
23
|
+
export type { AutoRule, KindDef, ReviewDef, ReviewSource, ReviewUnit, TrailerDef, TrailerUnit }
|
|
20
24
|
|
|
21
25
|
/** one button beside a global process: a command, or a function of the file */
|
|
22
26
|
export type ProcessAction = {
|
|
@@ -73,7 +77,7 @@ export type WidgetDef = {
|
|
|
73
77
|
export type GlobalProcessUnit = GlobalProcessDef & { kind: 'globalProcess' }
|
|
74
78
|
export type WidgetUnit = WidgetDef & { kind: 'widget' }
|
|
75
79
|
|
|
76
|
-
export const UNIT_KINDS = ['globalProcess', 'widget', 'trailer'] as const
|
|
80
|
+
export const UNIT_KINDS = ['globalProcess', 'widget', 'trailer', 'review'] as const
|
|
77
81
|
|
|
78
82
|
const KEBAB = /^[a-z0-9][a-z0-9-]*$/
|
|
79
83
|
const words = (v: unknown): boolean => Array.isArray(v) && v.length > 0 && v.every((w) => typeof w === 'string')
|
|
@@ -127,9 +131,9 @@ export function widget(d: WidgetDef): WidgetUnit {
|
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
/** the kind a default export says it is: a unit, else a check */
|
|
130
|
-
export function unitKind(d: unknown):
|
|
134
|
+
export function unitKind(d: unknown): (typeof UNIT_KINDS)[number] | 'check' {
|
|
131
135
|
const k = (d as { kind?: unknown } | null)?.kind
|
|
132
|
-
return k
|
|
136
|
+
return UNIT_KINDS.includes(k as (typeof UNIT_KINDS)[number]) ? (k as (typeof UNIT_KINDS)[number]) : 'check'
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
export type { CheckDef }
|
package/src/trailer/adapter.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
// what a repo adds to the trailer core, all optional. Filming is never here:
|
|
2
|
-
// film rows (vocab.ts). A `trailer({...})` unit in any `<name>.shipkit.ts`
|
|
3
|
-
//
|
|
1
|
+
// what a repo adds to the trailer core, all optional (wiki build/trailer.md, The trailer unit). Filming is never here:
|
|
2
|
+
// a film line calls the project CLI's film rows (vocab.ts). A `trailer({...})` unit in any `<name>.shipkit.ts`
|
|
3
|
+
// resolves the sounds that are not files, names the paths a take's world is, checks the content the language cannot
|
|
4
|
+
// know, refines one film line's take, and turns on the guards that read the repo's own words. Discovered like every
|
|
5
|
+
// unit file (load-unit.ts)
|
|
6
|
+
import type { TakeLength } from './grammar.ts'
|
|
4
7
|
|
|
5
8
|
export interface TrailerSounds {
|
|
6
9
|
/** a music id to an audio file of at least `seconds`, cached by the repo */
|
|
@@ -11,13 +14,65 @@ export interface TrailerSounds {
|
|
|
11
14
|
voice?(text: string): Promise<string>
|
|
12
15
|
}
|
|
13
16
|
|
|
17
|
+
/** a film line of the project CLI as the unit sees it: its words as written, the text of each `@<file>` word */
|
|
18
|
+
export interface TrailerFilmLine {
|
|
19
|
+
line: number
|
|
20
|
+
/** the shot or footage block it films */
|
|
21
|
+
shot: string
|
|
22
|
+
argv: string[]
|
|
23
|
+
output: 'still' | 'clip'
|
|
24
|
+
files: Record<string, string>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** what `check` reads: the cut's film lines and the sounds it names by id */
|
|
28
|
+
export interface TrailerCheckInput {
|
|
29
|
+
file: string
|
|
30
|
+
dir: string
|
|
31
|
+
size: [number, number]
|
|
32
|
+
fps: number
|
|
33
|
+
films: TrailerFilmLine[]
|
|
34
|
+
/** each music cue that names an id; `opening`: the header's, the one the cut starts on */
|
|
35
|
+
music: { line: number; id: string; take?: string; from: number; opening: boolean }[]
|
|
36
|
+
sfx: { line: number; id: string }[]
|
|
37
|
+
voices: { line: number; text: string }[]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** an error at its line; `warn`: said, never blocking */
|
|
41
|
+
export interface TrailerFinding {
|
|
42
|
+
line: number
|
|
43
|
+
message: string
|
|
44
|
+
warn?: true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** one film line's take over its row's defaults: its version, how long it films, a fixed world, what its key reads */
|
|
48
|
+
export interface TakeAnswer {
|
|
49
|
+
version?: number | string
|
|
50
|
+
length?: TakeLength
|
|
51
|
+
/** the take's world for good (`rev:<commit>`): never stale */
|
|
52
|
+
world?: string
|
|
53
|
+
/** what the key reads instead of the words */
|
|
54
|
+
recipe?: unknown
|
|
55
|
+
}
|
|
56
|
+
|
|
14
57
|
export interface TrailerDef {
|
|
15
58
|
sound?: TrailerSounds
|
|
59
|
+
/** the paths a take's world is (`['src', 'public']`); default the whole tree, trailer/ and .shipkit/ left out */
|
|
60
|
+
stamp?: string[]
|
|
61
|
+
/** in process, before filming, in a few ms: the content the language cannot know */
|
|
62
|
+
check?(c: TrailerCheckInput): TrailerFinding[] | Promise<TrailerFinding[]>
|
|
63
|
+
/** one film line's take, when its words change what its row says */
|
|
64
|
+
take?(f: TrailerFilmLine & { version: number | string | null; length: TakeLength }): TakeAnswer | undefined
|
|
65
|
+
/** the `states` a film prints: parts a cut may land on (`ignore`), parts a shot never opens or ends on (`underWay`) */
|
|
66
|
+
states?: { ignore?: string[]; underWay?: string[] }
|
|
67
|
+
/** a clip take that drops its picture for a few frames is filmed again once, then refused (holes.ts) */
|
|
68
|
+
holes?: boolean
|
|
16
69
|
}
|
|
17
70
|
|
|
18
71
|
export type TrailerUnit = TrailerDef & { kind: 'trailer' }
|
|
19
72
|
|
|
20
73
|
export function trailer(d: TrailerDef): TrailerUnit {
|
|
21
74
|
for (const [k, f] of Object.entries(d.sound ?? {})) if (typeof f !== 'function') throw new Error(`trailer: sound.${k} is a function returning an audio file`)
|
|
75
|
+
for (const k of ['check', 'take'] as const) if (d[k] !== undefined && typeof d[k] !== 'function') throw new Error(`trailer: ${k} is a function`)
|
|
76
|
+
if (d.stamp !== undefined && (!Array.isArray(d.stamp) || d.stamp.some((p) => typeof p !== 'string' || p === '' || p.startsWith('/')))) throw new Error('trailer: stamp is a list of repo relative paths')
|
|
22
77
|
return { ...d, kind: 'trailer' }
|
|
23
78
|
}
|