rvlib-shipkit 1.3.0 → 1.5.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 +105 -0
- package/README.md +17 -17
- package/package.json +3 -2
- package/src/asks/asks-queue.ts +4 -2
- package/src/assets/kits/identity-kit.ts +15 -13
- package/src/assets/run-assets.ts +12 -2
- package/src/check.ts +73 -98
- package/src/checks/SK001-package-json-shape.check.ts +26 -4
- package/src/checks/SK002-contracts-fulfillness.check.ts +4 -0
- package/src/checks/SK003-claude-md-shape.check.ts +5 -1
- package/src/checks/SK004-gitignore-policy.check.ts +7 -4
- package/src/checks/SK005-rvlib-versions.check.ts +53 -21
- package/src/checks/SK006-npm-publish-safety.check.ts +4 -0
- package/src/checks/SK007-github-visibility.check.ts +4 -2
- package/src/checks/SK008-reviewer-agent.check.ts +6 -4
- package/src/checks/SK009-commit-ai-tells.check.ts +94 -74
- package/src/checks/SK010-undeclared-unit.check.ts +4 -0
- package/src/checks/SK011-sibling-unit-ranges.check.ts +4 -0
- package/src/checks/SK012-config-barrel-import.check.ts +5 -1
- package/src/checks/SK013-one-way-in-policy.check.ts +7 -3
- package/src/checks/SK014-prose-ste.check.ts +20 -6
- package/src/checks/SK015-nested-repo.check.ts +4 -2
- package/src/checks/SK016-legacy-check-shapes.check.ts +23 -16
- package/src/checks/SK017-vscode-hub-task.check.ts +22 -7
- package/src/checks/SK018-test-files-run.check.ts +6 -2
- package/src/checks/SK019-tests-run-in-units.check.ts +8 -4
- package/src/checks/SK020-self-spawning-check.check.ts +4 -0
- package/src/checks/SK022-machine-runs-the-pin.check.ts +6 -4
- package/src/checks/SK024-identity-colors.check.ts +5 -3
- package/src/checks/SK025-release-drift.check.ts +4 -5
- package/src/checks/SK026-asks-autoclose.check.ts +4 -4
- package/src/checks/SK027-agent-wiki-links.check.ts +34 -9
- package/src/checks/SK028-readme.check.ts +10 -2
- package/src/checks/SK029-explicit-check-files.check.ts +95 -0
- package/src/cli/cmd_Asks.ts +5 -5
- package/src/cli/cmd_Assets.ts +7 -7
- package/src/cli/cmd_Bump.ts +12 -11
- package/src/cli/cmd_Check.ts +8 -7
- package/src/cli/cmd_Checks.ts +7 -6
- package/src/cli/cmd_Ci.ts +12 -11
- package/src/cli/cmd_Commands.ts +16 -13
- package/src/cli/cmd_ConfigKeys.ts +7 -6
- package/src/cli/cmd_Contracts.ts +3 -3
- package/src/cli/cmd_CrossRepoActivity.ts +10 -6
- package/src/cli/cmd_Fleet.ts +9 -7
- package/src/cli/cmd_GlobalProcesses.ts +116 -4
- package/src/cli/cmd_Home.ts +23 -17
- package/src/cli/cmd_Hooks.ts +6 -5
- package/src/cli/cmd_Init.ts +5 -4
- package/src/cli/cmd_Keys.ts +8 -7
- package/src/cli/cmd_Mv.ts +7 -6
- package/src/cli/cmd_Needs.ts +4 -3
- package/src/cli/cmd_Overview.ts +4 -3
- package/src/cli/cmd_Pb.ts +2 -2
- package/src/cli/cmd_Planned.ts +6 -5
- package/src/cli/cmd_Prose.ts +5 -5
- package/src/cli/cmd_Reflect.ts +7 -7
- package/src/cli/cmd_Release.ts +6 -5
- package/src/cli/cmd_Releases.ts +5 -4
- package/src/cli/cmd_Serve.ts +4 -3
- package/src/cli/cmd_Smoke.ts +5 -4
- package/src/cli/cmd_Start.ts +7 -6
- package/src/cli/cmd_Status.ts +4 -3
- package/src/cli/cmd_Tui.ts +3 -2
- package/src/cli/cmd_When.ts +71 -0
- package/src/cli/cmd_Wiki.ts +4 -4
- package/src/cli.ts +7 -2
- package/src/collections/checks.ts +2 -0
- package/src/collections/collection-types.ts +24 -4
- package/src/collections/providers.ts +6 -2
- package/src/contracts/apply-contracts.ts +9 -8
- package/src/contracts/contract-types.ts +8 -2
- package/src/contracts/contracts-engine.ts +34 -13
- package/src/contracts/manifests/identity.contract.ts +6 -5
- package/src/contracts/manifests/social.contract.ts +4 -2
- package/src/contracts/manifests/steam.contract.ts +7 -3
- package/src/contracts/web-surface.ts +59 -0
- package/src/core/budget.ts +19 -9
- package/src/core/canonical-scripts.ts +1 -1
- package/src/core/check-runner.ts +63 -25
- package/src/core/config-rewrite.ts +37 -24
- package/src/core/discover-checks.ts +31 -7
- package/src/core/layout.ts +2 -0
- package/src/core/legacy-shapes.ts +39 -10
- package/src/core/motherhome.ts +88 -66
- package/src/core/one-way-in-policy.ts +2 -2
- package/src/core/outcome-words.ts +18 -2
- package/src/core/port-check-cli.ts +52 -0
- package/src/core/port-check-file.ts +295 -0
- package/src/core/port-check-files.ts +31 -0
- package/src/core/retention.ts +0 -14
- package/src/core/run-check.ts +14 -14
- package/src/core/run-ci.ts +11 -7
- package/src/core/run-fix.ts +30 -23
- package/src/core/run-fixers.ts +42 -5
- package/src/core/runs-matrix.ts +179 -0
- package/src/core/runs.ts +242 -0
- package/src/core/update-policy.ts +20 -0
- package/src/core/when-block.ts +29 -30
- package/src/core/when.ts +41 -103
- package/src/core/wire.ts +34 -9
- package/src/fleet/scan-fleet.ts +20 -4
- package/src/fleet/update-fleet.ts +6 -6
- package/src/home/activity-shape.ts +4 -1
- package/src/home/activity.ts +22 -15
- package/src/home/gui-app/ShipkitGui.swift +144 -25
- package/src/home/gui-app.ts +93 -30
- package/src/home/home-launchd.ts +30 -6
- package/src/home/home-routes.ts +14 -2
- package/src/home/home-start.ts +33 -5
- package/src/home/hubs.ts +5 -5
- package/src/home/machine-stores.ts +4 -2
- package/src/home/open-app.ts +23 -10
- package/src/home/pm-config.ts +15 -11
- package/src/home/pm-inputs.ts +76 -0
- package/src/home/pm.ts +11 -3
- package/src/home/process-rows.ts +23 -6
- package/src/home/resources.ts +67 -15
- package/src/home/run-daemon.ts +6 -1
- package/src/home/run-pm.ts +30 -5
- package/src/home/serve-web.ts +2 -2
- package/src/home/supervise.ts +24 -1
- package/src/home/widgets.ts +32 -3
- package/src/hooks/commit-message.ts +2 -3
- package/src/hooks/run-hooks.ts +60 -6
- package/src/init-repo.ts +6 -6
- package/src/ledger/gate-checks.ts +115 -61
- package/src/ledger/git-key.ts +5 -1
- package/src/ledger/ledger.ts +5 -5
- package/src/ledger/store.ts +11 -0
- package/src/ledger/toolchain-identity.ts +45 -27
- package/src/ledger/world-cache.ts +17 -15
- package/src/plan/repo-source.ts +18 -39
- package/src/release/run-release.ts +5 -0
- package/src/repo-config.ts +36 -56
- package/src/rules/rule.ts +2 -2
- package/src/scaffold/files/agent-coding.md +1 -1
- package/src/scaffold/files/agent-index.md +1 -1
- package/src/scaffold/files/verify-skill.md +2 -2
- package/src/serve/hub-app/activity-st.ts +5 -4
- package/src/serve/hub-app/activity-view.tsx +4 -4
- package/src/serve/hub-app/admin-view.tsx +13 -11
- package/src/serve/hub-app/check-view.tsx +66 -46
- package/src/serve/hub-app/check-words.ts +1 -11
- package/src/serve/hub-app/checks-svc.ts +16 -36
- package/src/serve/hub-app/col-tables-view.tsx +131 -0
- package/src/serve/hub-app/col-tables.ts +115 -0
- package/src/serve/hub-app/cols-svc.ts +33 -4
- package/src/serve/hub-app/dock-st.ts +3 -2
- package/src/serve/hub-app/dock-view.tsx +36 -0
- package/src/serve/hub-app/dock.css +7 -1
- package/src/serve/hub-app/float-cards.tsx +30 -0
- package/src/serve/hub-app/floating.tsx +41 -4
- package/src/serve/hub-app/git-st.ts +42 -0
- package/src/serve/hub-app/git-view.tsx +61 -0
- package/src/serve/hub-app/hash-route.ts +45 -1
- package/src/serve/hub-app/header-bar.tsx +62 -72
- package/src/serve/hub-app/health-svc.ts +3 -2
- package/src/serve/hub-app/home-st.ts +15 -3
- package/src/serve/hub-app/home-strip.css +69 -19
- package/src/serve/hub-app/home-strip.tsx +192 -118
- package/src/serve/hub-app/home.html +1 -0
- package/src/serve/hub-app/hub-app.tsx +21 -5
- package/src/serve/hub-app/hub-types.ts +11 -5
- package/src/serve/hub-app/hub.css +88 -44
- package/src/serve/hub-app/icons.tsx +15 -0
- package/src/serve/hub-app/index.html +1 -0
- package/src/serve/hub-app/keys.ts +11 -8
- package/src/serve/hub-app/live-svc.ts +3 -2
- package/src/serve/hub-app/machine-st.ts +34 -49
- package/src/serve/hub-app/palette-st.ts +5 -5
- package/src/serve/hub-app/palette-view.tsx +1 -1
- package/src/serve/hub-app/plan-view.tsx +51 -0
- package/src/serve/hub-app/planned-st.ts +9 -4
- package/src/serve/hub-app/processes-view.tsx +38 -0
- package/src/serve/hub-app/project-list.tsx +3 -3
- package/src/serve/hub-app/projects-svc.ts +15 -10
- package/src/serve/hub-app/prose-hits-st.ts +3 -2
- package/src/serve/hub-app/reach.ts +36 -0
- package/src/serve/hub-app/readme-svc.ts +3 -2
- package/src/serve/hub-app/repo-sections.ts +117 -0
- package/src/serve/hub-app/repo-st.ts +47 -10
- package/src/serve/hub-app/runs-tabs.ts +1 -1
- package/src/serve/hub-app/sidebar.tsx +12 -37
- package/src/serve/hub-app/timeline-svc.ts +3 -2
- package/src/serve/hub-app/timeline-view.tsx +14 -11
- package/src/serve/hub-app/tree-build.ts +149 -155
- package/src/serve/hub-app/tree-row.tsx +39 -9
- package/src/serve/hub-app/tree-svc.ts +70 -49
- package/src/serve/hub-app/when-view.tsx +89 -0
- package/src/serve/hub-app/when.css +17 -0
- package/src/serve/hub-runtime.ts +3 -16
- package/src/serve/project-gutter.ts +1 -2
- package/src/serve/run-serve.ts +1 -1
- package/src/serve/serve-hub.ts +4 -14
- package/src/serve/warm-cell.ts +49 -16
- package/src/suite/judge-suites.ts +42 -17
- package/src/suite/suite-cli.ts +5 -8
- package/src/wiki/lint-md.ts +2 -0
- package/src/wiki/scan-md.ts +37 -10
- package/src/serve/hub-app/processes-svc.ts +0 -63
- package/src/serve/hub-app/repo-sections.tsx +0 -61
- package/src/serve/repo-processes.ts +0 -89
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// SK022 machine runs the pin (build/shipkit.md): on a machine with a house
|
|
1
|
+
// SK022 machine runs the pin (build/shipkit/home.md): on a machine with a house
|
|
2
2
|
// every shipkit runs the house copy, whatever a repo installed, so a repo's
|
|
3
3
|
// rvlib-shipkit pin is a minimum. It warns when the repo asks for a version
|
|
4
4
|
// newer than the one this process runs: a rule or an api that pin relies on
|
|
@@ -24,11 +24,13 @@ export const machineRunsThePin = check({
|
|
|
24
24
|
blocking: false,
|
|
25
25
|
title: 'machine runs the pin',
|
|
26
26
|
description: 'the shipkit this machine runs is at least the version this repo pins',
|
|
27
|
-
owner: 'build/shipkit.md',
|
|
27
|
+
owner: 'build/shipkit/home.md',
|
|
28
|
+
runs: { onPreCommit: false, onCi: false, onFull: true, onRelease: true, onHealth: true, onSave: 'moved', onClock: false },
|
|
28
29
|
// the pin, the install (gitignored) and the version this machine runs,
|
|
29
30
|
// which is no file of the repo
|
|
30
|
-
inputs: ['package.json'],
|
|
31
|
-
|
|
31
|
+
cache: { by: 'files', inputs: ['package.json'], key: (env) => `${LIB_VERSION}|installed=${fileStamp(join(env.root, 'node_modules', NAME, 'package.json'))}` },
|
|
32
|
+
fix: 'none',
|
|
33
|
+
applies: 'always',
|
|
32
34
|
run: (c) => {
|
|
33
35
|
const pkg = c.json<Pkg>('package.json')
|
|
34
36
|
const spec = pkg?.devDependencies?.[NAME] ?? pkg?.dependencies?.[NAME]
|
|
@@ -18,9 +18,11 @@ export const identityColors = check({
|
|
|
18
18
|
title: 'identity colors',
|
|
19
19
|
description: 'repo.config.ts declares identity colours: colorLight and colorDark, two hex',
|
|
20
20
|
owner: 'build/shipkit/built-in-checks.md',
|
|
21
|
+
runs: { onPreCommit: false, onCi: false, onFull: false, onRelease: false, onHealth: true, onSave: 'moved', onClock: false },
|
|
21
22
|
// the config, and the installed lib that says whether it knows the key
|
|
22
|
-
inputs: [CONFIG_FILE],
|
|
23
|
-
|
|
23
|
+
cache: { by: 'files', inputs: [CONFIG_FILE], key: (env) => `installed=${fileStamp(join(env.root, INSTALLED_CONFIG_SRC))}` },
|
|
24
|
+
fix: 'manual',
|
|
25
|
+
applies: 'always',
|
|
24
26
|
run: (c) => {
|
|
25
27
|
const text = c.read(CONFIG_FILE)
|
|
26
28
|
if (text == null) return c.note(`no ${CONFIG_FILE}`)
|
|
@@ -32,7 +34,7 @@ export const identityColors = check({
|
|
|
32
34
|
if (why != null) return c.warn(`${CONFIG_FILE}: ${why}`, FIX)
|
|
33
35
|
c.ok(`identity ${id!.colorLight} on light, ${id!.colorDark} on dark`)
|
|
34
36
|
},
|
|
35
|
-
|
|
37
|
+
repair: async (c) => {
|
|
36
38
|
const text = c.read(CONFIG_FILE)
|
|
37
39
|
if (text == null) return { changed: false, summary: `no ${CONFIG_FILE}` }
|
|
38
40
|
const have = identityOfText(text)
|
|
@@ -41,11 +41,10 @@ export const releaseDrift = check({
|
|
|
41
41
|
title: 'release drift',
|
|
42
42
|
description: 'every unit this repo releases matches npm and its push remote',
|
|
43
43
|
owner: 'build/shipkit/built-in-checks.md',
|
|
44
|
-
|
|
45
|
-
ttl: '20h',
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
cacheKey: (env) => releasedUnits(env.root, env.config).map((u) => `${u.id}@${u.version}`).join(','),
|
|
44
|
+
runs: { onPreCommit: false, onCi: false, onFull: false, onRelease: false, onHealth: true, onSave: false, onClock: { every: (last) => (last?.status === 'pass' ? ['20h', '28h'] : '4h'), inactive: 'wait' } },
|
|
45
|
+
cache: { by: 'ttl', span: '20h', key: (env) => releasedUnits(env.root, env.config).map((u) => `${u.id}@${u.version}`).join(',') },
|
|
46
|
+
fix: 'none',
|
|
47
|
+
applies: (env) => (releasedUnits(env.root, env.config).length === 0 ? 'this repo releases nothing' : null),
|
|
49
48
|
run: async (c) => {
|
|
50
49
|
const ids = new Set(releasedUnits(c.root, c.config).map((u) => u.id))
|
|
51
50
|
if (ids.size === 0) return void c.lines.push({ kind: 'skip', text: 'this repo releases nothing: no npm root, no release config, no units' })
|
|
@@ -14,11 +14,11 @@ export const asksAutoclose = check({
|
|
|
14
14
|
title: 'asks auto close',
|
|
15
15
|
description: 'no open ask whose own probe passes stays in the queue',
|
|
16
16
|
owner: 'build/shipkit/built-in-checks.md',
|
|
17
|
-
|
|
18
|
-
never: "runs each open ask's own probe, a shell command that reads the world",
|
|
19
|
-
|
|
17
|
+
runs: { onPreCommit: false, onCi: false, onFull: false, onRelease: false, onHealth: true, onSave: false, onClock: { every: ['20h', '28h'], inactive: 'wait' } },
|
|
18
|
+
cache: { by: 'never', why: "runs each open ask's own probe, a shell command that reads the world" },
|
|
19
|
+
fix: 'none',
|
|
20
20
|
// it only probes an ask that carries one, and archives one marked done
|
|
21
|
-
|
|
21
|
+
applies: (env) => {
|
|
22
22
|
const dir = join(env.root, env.config.asks?.dir ?? LAYOUT.asks)
|
|
23
23
|
if (!existsSync(dir)) return 'no asks queue'
|
|
24
24
|
return listAsks(dir).some((a) => a.check != null || a.status === 'done') ? null : 'no open ask carries a probe'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// SK027 agent wiki links (build/shipkit/built-in-checks.md): a repo's agent/
|
|
2
2
|
// IS an md wiki (entry index.md, the CLAUDE.md include), so an orphan page or
|
|
3
|
-
// a dangling ref there fails. A
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
import { existsSync } from 'fs'
|
|
7
|
-
import { join } from 'path'
|
|
3
|
+
// a dangling ref there fails. A link that leaves agent/ but stays in the repo
|
|
4
|
+
// is checked on disk; a pointer out of the repo (a house wiki) is backticked,
|
|
5
|
+
// never a bare → or @. A repo without agent/index.md skips.
|
|
6
|
+
import { existsSync, readFileSync } from 'fs'
|
|
7
|
+
import { basename, join } from 'path'
|
|
8
8
|
import { check } from '../check.ts'
|
|
9
9
|
import { lintMd } from '../wiki/lint-md.ts'
|
|
10
10
|
|
|
@@ -14,15 +14,40 @@ export const agentWikiLinks = check({
|
|
|
14
14
|
title: 'agent wiki links',
|
|
15
15
|
description: 'every agent/ page is linked from somewhere, and every agent/ link resolves',
|
|
16
16
|
owner: 'meta/agent-folder.md',
|
|
17
|
+
runs: { onPreCommit: false, onCi: true, onFull: true, onRelease: true, onHealth: true, onSave: 'moved', onClock: false },
|
|
17
18
|
// the md lint walks agent/ on disk rather than through `c`: agent/ is all it reads
|
|
18
|
-
inputs: ['agent'],
|
|
19
|
+
cache: { by: 'files', inputs: ['agent'], key: null },
|
|
20
|
+
fix: 'none',
|
|
21
|
+
applies: 'always',
|
|
19
22
|
run: (c) => {
|
|
20
23
|
if (!existsSync(join(c.root, 'agent/index.md'))) return void c.lines.push({ kind: 'skip', text: 'no agent/ wiki in this repo' })
|
|
21
|
-
const lint = lintMd({ root: join(c.root, 'agent'), index: 'index.md' })
|
|
22
|
-
|
|
23
|
-
for (const
|
|
24
|
+
const lint = lintMd({ root: join(c.root, 'agent'), index: 'index.md', boundary: c.root })
|
|
25
|
+
const linked = lint.pages.filter((p) => !lint.orphans.includes(p))
|
|
26
|
+
for (const f of lint.orphans) {
|
|
27
|
+
const by = namingPage(c.root, f, linked)
|
|
28
|
+
const where = by != null ? `${by}, which already names it (turn that mention into the link)` : 'agent/index.md or the page of its topic'
|
|
29
|
+
c.fail(`agent/${f}: orphan, unreachable from agent/index.md: add a markdown link to it from ${where}; delete it only if the page is dead`)
|
|
30
|
+
}
|
|
31
|
+
for (const d of lint.dangling) c.fail(`agent/${d.from}: dangling ref → ${d.token}, target not found on disk: fix the path or delete the pointer (a pointer out of this repo, into a house wiki or another repo, goes in backticks)`)
|
|
24
32
|
if (!c.failed) c.ok('agent/ has no orphans and no dangling refs')
|
|
25
33
|
},
|
|
26
34
|
})
|
|
27
35
|
|
|
36
|
+
/** the linked page whose text already names an orphan (its path, its file
|
|
37
|
+
* name, or a glob its file name matches), the one to turn into a link */
|
|
38
|
+
function namingPage(root: string, orphan: string, pages: string[]): string | null {
|
|
39
|
+
const name = basename(orphan)
|
|
40
|
+
const stem = name.replace(/\.md$/, '')
|
|
41
|
+
for (const p of pages) {
|
|
42
|
+
const text = readFileSync(join(root, 'agent', p), 'utf8')
|
|
43
|
+
if (text.includes(orphan) || text.includes(name) || text.includes(`${stem}.`) || text.includes(`${stem} `)) return `agent/${p}`
|
|
44
|
+
for (const m of text.matchAll(/[\w.-]*\*[\w.*-]*/g)) {
|
|
45
|
+
const g = m[0]
|
|
46
|
+
if (g.replace(/[*.]/g, '').length < 3) continue
|
|
47
|
+
if (new Bun.Glob(g).match(name) || new Bun.Glob(`${g}.md`).match(name)) return `agent/${p}`
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
28
53
|
export default agentWikiLinks
|
|
@@ -52,21 +52,29 @@ const REQUIREMENTS: Requirement[] = [
|
|
|
52
52
|
const why = found.map((f) => (f as { bad: string }).bad)
|
|
53
53
|
return {
|
|
54
54
|
warn: `${README}: screenshot: ${why.length === 0 ? 'no image at all' : `no image resolves (${why.join(', ')})`}`,
|
|
55
|
-
fix:
|
|
55
|
+
fix: `add a screenshot to README.md: , a file in the repo, or an https url; ${OFF}`,
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
},
|
|
59
59
|
]
|
|
60
60
|
|
|
61
|
+
/** the other way out, for a repo that cannot show one: the rule off, with the
|
|
62
|
+
* reason `defineRepo` requires (core/when.ts) */
|
|
63
|
+
const OFF = `or, when this repo cannot show one, turn the rule off with the reason: off: { SK028: '<why this repo shows no screenshot>' } in repo.config.ts, inside its shipkit gate block`
|
|
64
|
+
|
|
61
65
|
export const readme = check({
|
|
62
66
|
id: 'SK028',
|
|
63
67
|
blocking: false,
|
|
64
68
|
title: 'readme',
|
|
65
69
|
description: 'README.md exists and shows at least one screenshot',
|
|
66
70
|
owner: 'build/shipkit/built-in-checks.md',
|
|
71
|
+
runs: { onPreCommit: false, onCi: false, onFull: false, onRelease: false, onHealth: true, onSave: 'moved', onClock: false },
|
|
72
|
+
cache: { by: 'reads' },
|
|
73
|
+
fix: 'none',
|
|
74
|
+
applies: 'always',
|
|
67
75
|
run: (c) => {
|
|
68
76
|
const md = c.read(README)
|
|
69
|
-
if (md == null) return c.warn(`${README}: exists: no ${README} at the repo root`,
|
|
77
|
+
if (md == null) return c.warn(`${README}: exists: no ${README} at the repo root`, `write README.md: what the repo is, and a screenshot of it; ${OFF}`)
|
|
70
78
|
c.ok(`${README} exists`)
|
|
71
79
|
for (const r of REQUIREMENTS) {
|
|
72
80
|
const f = r.test(c, md)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// SK029 explicit check files (build/shipkit/runs.md owns the declaration):
|
|
2
|
+
// every check file of the repo declares runs, cache, fix and applies, with
|
|
3
|
+
// no retired key. A file that does not does not load, and discovery shows
|
|
4
|
+
// it as one failing row. The repair ports it with the values the retired
|
|
5
|
+
// keys resolved to (core/port-check-file.ts), so the check keeps running
|
|
6
|
+
// where it ran, and the ci fix pass applies it before the gate reads the
|
|
7
|
+
// files: a repo carried across by its first `shipkit ci`. The same holds for
|
|
8
|
+
// the config: a retired `when` (only its `off:<why>` entries still load) and
|
|
9
|
+
// `ruleExempt` become `off` entries in the managed block.
|
|
10
|
+
import { join } from 'path'
|
|
11
|
+
import { check, type FixResult } from '../check.ts'
|
|
12
|
+
import { unportedCheckFiles } from '../core/port-check-files.ts'
|
|
13
|
+
import type { PortRun } from '../core/port-check-cli.ts'
|
|
14
|
+
import type { ConfigPlan, ConfigRewrite } from '../core/config-rewrite.ts'
|
|
15
|
+
import type { RepoConfig } from '../repo-config.ts'
|
|
16
|
+
|
|
17
|
+
/** the write half, run as its own process: it walks import closures on disk */
|
|
18
|
+
const PORT_CLI = join(import.meta.dir, '../core/port-check-cli.ts')
|
|
19
|
+
/** the config half, run as its own process: it loads repo.config.ts */
|
|
20
|
+
const CONFIG_REWRITE = join(import.meta.dir, '../core/config-rewrite.ts')
|
|
21
|
+
|
|
22
|
+
/** the retired config keys this repo still carries, and the `off` entries
|
|
23
|
+
* they become. defineRepo already refused every `when` word but `off:<why>` */
|
|
24
|
+
export function retiredOff(c: RepoConfig): { keys: string[]; off: Record<string, string> } {
|
|
25
|
+
const off: Record<string, string> = {}
|
|
26
|
+
for (const [id, raw] of Object.entries(c.when ?? {})) off[id] = raw.trim().replace(/^off:?/, '').trim()
|
|
27
|
+
for (const [id, why] of Object.entries(c.ruleExempt ?? {})) off[id] ??= why
|
|
28
|
+
const keys = [...(c.when != null ? ['when'] : []), ...(c.ruleExempt != null ? ['ruleExempt'] : [])]
|
|
29
|
+
return { keys, off }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const explicitCheckFiles = check({
|
|
33
|
+
id: 'SK029',
|
|
34
|
+
title: 'explicit check files',
|
|
35
|
+
description: 'every check file declares runs, cache, fix and applies, and the config says only off',
|
|
36
|
+
owner: 'build/shipkit/runs.md',
|
|
37
|
+
blocking: true,
|
|
38
|
+
runs: { onPreCommit: false, onCi: true, onFull: true, onRelease: true, onHealth: true, onSave: 'moved', onClock: false },
|
|
39
|
+
// the listing of check files and their sources, read through `c`
|
|
40
|
+
cache: { by: 'reads' },
|
|
41
|
+
// the port is mechanical: every value it writes is what the retired keys
|
|
42
|
+
// resolved to, so the fix pass applies it without asking
|
|
43
|
+
fix: 'ci',
|
|
44
|
+
applies: 'always',
|
|
45
|
+
run: (c) => {
|
|
46
|
+
const files = unportedCheckFiles(c)
|
|
47
|
+
const cfg = retiredOff(c.config)
|
|
48
|
+
if (files.length === 0 && cfg.keys.length === 0) return c.ok('every check file declares runs, cache, fix and applies, and the config says only off')
|
|
49
|
+
for (const f of files) c.fail(`${f.rel} still declares the retired shape (${f.keys.join(', ')}), so it does not load`)
|
|
50
|
+
if (cfg.keys.length > 0) c.fail(`repo.config.ts still carries ${cfg.keys.join(' and ')}: a repo only turns a check off, as off: { <id>: '<why>' }`)
|
|
51
|
+
c.fail(`${files.length + (cfg.keys.length > 0 ? 1 : 0)} file(s) to port`, 'shipkit check --fix SK029 ports each one with the values it ran on, and `shipkit ci` does it in its fix pass')
|
|
52
|
+
},
|
|
53
|
+
repair: async (c): Promise<FixResult> => {
|
|
54
|
+
const files = unportedCheckFiles(c)
|
|
55
|
+
const cfg = retiredOff(c.config)
|
|
56
|
+
if (files.length === 0 && cfg.keys.length === 0) return { changed: false, summary: 'every check file is explicit already, and the config says only off' }
|
|
57
|
+
const did: string[] = []
|
|
58
|
+
const hand: string[] = []
|
|
59
|
+
if (files.length > 0) {
|
|
60
|
+
const r = await c.exec([process.execPath, PORT_CLI, c.root, ...files.map((f) => f.rel)], { cwd: c.root, timeoutMs: 60_000 })
|
|
61
|
+
try {
|
|
62
|
+
const run = JSON.parse(r.out.trim().split('\n').at(-1) ?? '') as PortRun
|
|
63
|
+
if (run.did.length > 0) did.push(`ported ${run.did.join('; ')}`)
|
|
64
|
+
hand.push(...run.hand)
|
|
65
|
+
} catch {
|
|
66
|
+
hand.push(`the port did not answer (exit ${r.code}: ${r.out.trim().slice(0, 160)}): port ${files.map((f) => f.rel).join(', ')} by hand (build/shipkit/runs.md)`)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (cfg.keys.length > 0) {
|
|
70
|
+
// `when` sits inside the managed block, so it goes first and the
|
|
71
|
+
// block describes the config again before the entries land
|
|
72
|
+
const plan: ConfigPlan = {
|
|
73
|
+
off: cfg.off,
|
|
74
|
+
drop: [
|
|
75
|
+
...(c.config.when != null ? [{ key: 'when', why: 'its off entries are `off` now', phase: 'first' as const }] : []),
|
|
76
|
+
...(c.config.ruleExempt != null ? [{ key: 'ruleExempt', why: 'its exemptions are `off` now', phase: 'afterOff' as const }] : []),
|
|
77
|
+
],
|
|
78
|
+
name: c.config.name,
|
|
79
|
+
}
|
|
80
|
+
const r = await c.exec([process.execPath, CONFIG_REWRITE, c.root, JSON.stringify(plan)], { cwd: c.root, timeoutMs: 60_000 })
|
|
81
|
+
try {
|
|
82
|
+
const out = JSON.parse(r.out.trim().split('\n').at(-1) ?? '') as ConfigRewrite
|
|
83
|
+
did.push(...out.did)
|
|
84
|
+
hand.push(...out.hand)
|
|
85
|
+
if (out.restored != null) hand.push(`repo.config.ts was left as it was: ${out.restored}`)
|
|
86
|
+
} catch {
|
|
87
|
+
hand.push(`the repo.config.ts rewrite did not answer (exit ${r.code}): write off: ${JSON.stringify(cfg.off)} by hand and drop ${cfg.keys.join(', ')}`)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const summary = [did.length > 0 ? did.join('; ') : 'nothing ported', ...(hand.length > 0 ? [`${hand.length} by hand: ${hand.join(' | ')}`] : [])].join('. ')
|
|
91
|
+
return { changed: did.length > 0, summary }
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
export default explicitCheckFiles
|
package/src/cli/cmd_Asks.ts
CHANGED
|
@@ -15,7 +15,7 @@ export class AsksCommand extends Command {
|
|
|
15
15
|
static override usage = Command.Usage({
|
|
16
16
|
category: 'Asks',
|
|
17
17
|
description: 'list open asks — the per-repo human action queue',
|
|
18
|
-
examples: [['list open asks', '
|
|
18
|
+
examples: [['list open asks', 'sk asks']],
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
async execute(): Promise<number> {
|
|
@@ -37,7 +37,7 @@ export class AsksCheckCommand extends Command {
|
|
|
37
37
|
static override usage = Command.Usage({
|
|
38
38
|
category: 'Asks',
|
|
39
39
|
description: 'probe every open ask and archive the ones whose check now passes',
|
|
40
|
-
examples: [['probe + auto-close', '
|
|
40
|
+
examples: [['probe + auto-close', 'sk asks check']],
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
async execute(): Promise<number> {
|
|
@@ -59,9 +59,9 @@ export class AskNewCommand extends Command {
|
|
|
59
59
|
category: 'Asks',
|
|
60
60
|
description: 'create a new ask file in the queue',
|
|
61
61
|
examples: [
|
|
62
|
-
['minimal', '
|
|
63
|
-
['with a reason', '
|
|
64
|
-
['with metadata', '
|
|
62
|
+
['minimal', 'sk ask "rotate the API token"'],
|
|
63
|
+
['with a reason', 'sk ask "buy the domain" --why "landing page is blocked on it"'],
|
|
64
|
+
['with metadata', 'sk ask "buy the domain" --kind action --blocks deploy --check "dig +short example.com"'],
|
|
65
65
|
],
|
|
66
66
|
})
|
|
67
67
|
|
package/src/cli/cmd_Assets.ts
CHANGED
|
@@ -19,8 +19,8 @@ export class AssetsFillCommand extends Command {
|
|
|
19
19
|
category: 'Assets',
|
|
20
20
|
description: 'top rolls up to N per asset (canvas or comfy), sparsest-first',
|
|
21
21
|
examples: [
|
|
22
|
-
['every asset up to 8 rolls', '
|
|
23
|
-
['only two categories', '
|
|
22
|
+
['every asset up to 8 rolls', 'sk assets fill 8'],
|
|
23
|
+
['only two categories', 'sk assets fill 8 icons sprites'],
|
|
24
24
|
],
|
|
25
25
|
})
|
|
26
26
|
|
|
@@ -43,7 +43,7 @@ export class AssetsAddCommand extends Command {
|
|
|
43
43
|
static override usage = Command.Usage({
|
|
44
44
|
category: 'Assets',
|
|
45
45
|
description: 'N more rolls per asset (canvas or comfy), regardless of what it has',
|
|
46
|
-
examples: [['3 fresh rolls everywhere', '
|
|
46
|
+
examples: [['3 fresh rolls everywhere', 'sk assets add 3']],
|
|
47
47
|
})
|
|
48
48
|
|
|
49
49
|
n = Option.String({ required: true })
|
|
@@ -66,8 +66,8 @@ export class AssetsGenCommand extends Command {
|
|
|
66
66
|
category: 'Assets',
|
|
67
67
|
description: 'one-shot rolls for a single asset (canvas or comfy)',
|
|
68
68
|
examples: [
|
|
69
|
-
['one roll', '
|
|
70
|
-
['five rolls', '
|
|
69
|
+
['one roll', 'sk assets gen hero'],
|
|
70
|
+
['five rolls', 'sk assets gen hero --n 5'],
|
|
71
71
|
],
|
|
72
72
|
})
|
|
73
73
|
|
|
@@ -86,7 +86,7 @@ export class AssetsIdentityCommand extends Command {
|
|
|
86
86
|
static override usage = Command.Usage({
|
|
87
87
|
category: 'Assets',
|
|
88
88
|
description: 'render favicon/logo/OG from .shipkit/identity/brand.ts into public/',
|
|
89
|
-
examples: [['regenerate the identity outputs', '
|
|
89
|
+
examples: [['regenerate the identity outputs', 'sk assets identity']],
|
|
90
90
|
})
|
|
91
91
|
|
|
92
92
|
async execute(): Promise<number> {
|
|
@@ -100,7 +100,7 @@ export class AssetsCheckCommand extends Command {
|
|
|
100
100
|
static override usage = Command.Usage({
|
|
101
101
|
category: 'Assets',
|
|
102
102
|
description: 'kit loads, kinds valid, cflow workflows load, drafts present, identity outputs present',
|
|
103
|
-
examples: [['health-check the asset pipeline', '
|
|
103
|
+
examples: [['health-check the asset pipeline', 'sk assets check']],
|
|
104
104
|
})
|
|
105
105
|
|
|
106
106
|
async execute(): Promise<number> {
|
package/src/cli/cmd_Bump.ts
CHANGED
|
@@ -9,18 +9,19 @@ export class BumpCommand extends Command {
|
|
|
9
9
|
|
|
10
10
|
static override usage = Command.Usage({
|
|
11
11
|
category: 'Gate',
|
|
12
|
-
description: 'ship a version
|
|
12
|
+
description: 'ship a version: merge, changelog, bump, gate, tag, push, release',
|
|
13
|
+
details: 'ship a version in one word: bumps a unit (default the repo root), run from a feature branch it merges into the release branch first, then promotes the CHANGELOG Unreleased section, bumps package.json, runs the gate and every prepublish script, commits, tags, pushes, and cuts the release. Any failure before the version commit rolls the merge back and returns you to your branch.',
|
|
13
14
|
examples: [
|
|
14
|
-
['a bugfix release of the repo itself', '
|
|
15
|
-
['a feature release', '
|
|
16
|
-
['a breaking release', '
|
|
17
|
-
['one sub-unit (ids: shipkit releases)', '
|
|
18
|
-
['a whole mixed batch in ONE gate, each unit at the kind its heading declares', '
|
|
19
|
-
['every unit carrying Unreleased notes, all at the same kind', '
|
|
20
|
-
['one unit, kind from its own heading', '
|
|
21
|
-
['rehearse the whole thing', '
|
|
22
|
-
['bump and commit, release later', '
|
|
23
|
-
['from a feature branch, refuse rather than merge', '
|
|
15
|
+
['a bugfix release of the repo itself', 'sk bump patch'],
|
|
16
|
+
['a feature release', 'sk bump minor'],
|
|
17
|
+
['a breaking release', 'sk bump major'],
|
|
18
|
+
['one sub-unit (ids: shipkit releases)', 'sk bump minor rvlib-shipkit'],
|
|
19
|
+
['a whole mixed batch in ONE gate, each unit at the kind its heading declares', 'sk bump --all'],
|
|
20
|
+
['every unit carrying Unreleased notes, all at the same kind', 'sk bump patch --all'],
|
|
21
|
+
['one unit, kind from its own heading', 'sk bump rvlib-shipkit'],
|
|
22
|
+
['rehearse the whole thing', 'sk bump minor --dry-run'],
|
|
23
|
+
['bump and commit, release later', 'sk bump patch --no-release'],
|
|
24
|
+
['from a feature branch, refuse rather than merge', 'sk bump patch --no-merge'],
|
|
24
25
|
],
|
|
25
26
|
})
|
|
26
27
|
|
package/src/cli/cmd_Check.ts
CHANGED
|
@@ -14,14 +14,15 @@ export class CheckCommand extends Command {
|
|
|
14
14
|
|
|
15
15
|
static override usage = Command.Usage({
|
|
16
16
|
category: 'Health',
|
|
17
|
-
description: 'every check except the build steps
|
|
17
|
+
description: 'every check except the build steps: the slower health surface',
|
|
18
|
+
details: 'every check except the build steps. `shipkit ci` runs these too and is what you normally want. --fix applies check autofixes',
|
|
18
19
|
examples: [
|
|
19
|
-
['run (cached where valid)', '
|
|
20
|
-
['bust every cache layer', '
|
|
21
|
-
['apply every rule autofix, re-lint', '
|
|
22
|
-
['fix one rule', '
|
|
23
|
-
['report-only: self-maintaining rules never write', '
|
|
24
|
-
['machine-readable', '
|
|
20
|
+
['run (cached where valid)', 'sk check'],
|
|
21
|
+
['bust every cache layer', 'sk check --fresh'],
|
|
22
|
+
['apply every rule autofix, re-lint', 'sk check --fix'],
|
|
23
|
+
['fix one rule', 'sk check --fix SK004'],
|
|
24
|
+
['report-only: self-maintaining rules never write', 'sk check --frozen'],
|
|
25
|
+
['machine-readable', 'sk check --json'],
|
|
25
26
|
],
|
|
26
27
|
})
|
|
27
28
|
|
package/src/cli/cmd_Checks.ts
CHANGED
|
@@ -21,13 +21,14 @@ export class ChecksCommand extends Command {
|
|
|
21
21
|
// widened so the hidden alias below can drop it: no usage, no help entry
|
|
22
22
|
static override usage: Usage | undefined = Command.Usage({
|
|
23
23
|
category: 'Health',
|
|
24
|
-
description: 'every gate check on one table:
|
|
24
|
+
description: 'every gate check on one table: source, blocking or warning, cache',
|
|
25
|
+
details: 'every gate check on one table: where it comes from, whether it blocks or only warns, whether the gate runs it or only `shipkit check`, and how it caches. Reports, never gates',
|
|
25
26
|
examples: [
|
|
26
|
-
['the whole inventory', '
|
|
27
|
-
['the big markdown table, written to a file', '
|
|
28
|
-
['only the ones the gate never runs', '
|
|
29
|
-
['everything that repairs itself, with its owner', '
|
|
30
|
-
['machine-readable', '
|
|
27
|
+
['the whole inventory', 'sk checks'],
|
|
28
|
+
['the big markdown table, written to a file', 'sk checks --out STATUS.full.md'],
|
|
29
|
+
['only the ones the gate never runs', 'sk checks --proactive'],
|
|
30
|
+
['everything that repairs itself, with its owner', 'sk checks --fixable'],
|
|
31
|
+
['machine-readable', 'sk checks --json'],
|
|
31
32
|
],
|
|
32
33
|
})
|
|
33
34
|
|
package/src/cli/cmd_Ci.ts
CHANGED
|
@@ -13,18 +13,19 @@ export class CiCommand extends Command {
|
|
|
13
13
|
|
|
14
14
|
static override usage = Command.Usage({
|
|
15
15
|
category: 'Gate',
|
|
16
|
-
description: 'THE
|
|
16
|
+
description: 'THE gate: repairs what a machine can, then runs every check. Run this, not the parts',
|
|
17
|
+
details: 'THE command. Repairs what a machine can (formatter, imports, repo shape), then runs every check the gate asks for, through one DAG. A check that declares blocking:false warns instead of failing. Run this instead of anything else.',
|
|
17
18
|
examples: [
|
|
18
|
-
['full gate, mechanical fixes applied', '
|
|
19
|
-
['gate without the repair pass (checks can still write)', '
|
|
20
|
-
['leave repo config files alone', '
|
|
21
|
-
['stop at the first failure', '
|
|
22
|
-
['one check + its dep closure', '
|
|
23
|
-
['every check declaring one group', '
|
|
24
|
-
['run everything, take nothing from the cache', '
|
|
25
|
-
['include an opt in check', '
|
|
26
|
-
['in the background, read it back with shipkit status', '
|
|
27
|
-
['every line, the ones nobody acts on included', '
|
|
19
|
+
['full gate, mechanical fixes applied', 'sk ci'],
|
|
20
|
+
['gate without the repair pass (checks can still write)', 'sk ci --no-fix'],
|
|
21
|
+
['leave repo config files alone', 'sk ci --no-fix-rules'],
|
|
22
|
+
['stop at the first failure', 'sk ci --bail'],
|
|
23
|
+
['one check + its dep closure', 'sk ci --only typecheck'],
|
|
24
|
+
['every check declaring one group', 'sk ci --only wiki'],
|
|
25
|
+
['run everything, take nothing from the cache', 'sk ci --fresh'],
|
|
26
|
+
['include an opt in check', 'sk ci --with up:itch'],
|
|
27
|
+
['in the background, read it back with shipkit status', 'sk ci --detach'],
|
|
28
|
+
['every line, the ones nobody acts on included', 'sk ci --verbose'],
|
|
28
29
|
],
|
|
29
30
|
})
|
|
30
31
|
|
package/src/cli/cmd_Commands.ts
CHANGED
|
@@ -23,6 +23,10 @@ export type Definition = {
|
|
|
23
23
|
options?: { definition?: string; description?: string | null }[] | null
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/** the longest description the index shows: one short line. The rest goes in
|
|
27
|
+
* the command's `details`, which --help prints */
|
|
28
|
+
export const DESCRIPTION_MAX = 100
|
|
29
|
+
|
|
26
30
|
// clipanion renders a value placeholder as `#0`, which nobody can type
|
|
27
31
|
const clean = (s: string | null | undefined): string => (s ?? '').trim().replace(/\s+/g, ' ').replace(/ #\d+\b/g, ' <value>')
|
|
28
32
|
|
|
@@ -34,9 +38,9 @@ const clean = (s: string | null | undefined): string => (s ?? '').trim().replace
|
|
|
34
38
|
export function commandRows(plain: Definition[], detailed: Definition[] = []): CommandRow[] {
|
|
35
39
|
const flagsByPath = new Map(detailed.map((d) => [d.path, d.options ?? []]))
|
|
36
40
|
return plain
|
|
37
|
-
.filter((d) => !/^shipkit (--help|-h|--version|-v)$/.test(d.path))
|
|
41
|
+
.filter((d) => !/^(shipkit|sk) (--help|-h|--version|-v)$/.test(d.path))
|
|
38
42
|
.map((d) => ({
|
|
39
|
-
path: d.path.replace(/^shipkit /, ''),
|
|
43
|
+
path: d.path.replace(/^(shipkit|sk) /, ''),
|
|
40
44
|
category: clean(d.category) || 'Other',
|
|
41
45
|
// verbatim from the CLI so the doc cannot say something it does not
|
|
42
46
|
description: clean(d.description),
|
|
@@ -49,21 +53,19 @@ export function commandRows(plain: Definition[], detailed: Definition[] = []): C
|
|
|
49
53
|
.sort((a, b) => a.category.localeCompare(b.category) || a.path.localeCompare(b.path))
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
/** the markdown block
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* `--help` first, and both are the waste this page exists to remove. */
|
|
56
|
+
/** the markdown block, loaded into every agent's context at start: per
|
|
57
|
+
* command its invocation with every flag, one line of description, then its
|
|
58
|
+
* examples. What a flag does and the long text are `sk <command> --help`. */
|
|
56
59
|
export function renderMarkdown(rows: CommandRow[]): string {
|
|
57
60
|
const out: string[] = []
|
|
58
61
|
let cat = ''
|
|
59
62
|
for (const r of rows) {
|
|
60
63
|
if (r.category !== cat) { cat = r.category; out.push(`\n### ${cat}\n`) }
|
|
61
|
-
const sig = r.usage.replace(/^\$0/, '
|
|
64
|
+
const sig = r.usage.replace(/^\$0/, 'sk').trim() || `sk ${r.path}`
|
|
62
65
|
const flags = r.options.map((o) => `[${o.definition}]`).join(' ')
|
|
63
66
|
// one line per bullet: a description on its own indented line reads as
|
|
64
67
|
// hard-wrapped prose to the house lint
|
|
65
68
|
out.push(`- \`${sig}${flags === '' ? '' : ` ${flags}`}\` — ${r.description}`)
|
|
66
|
-
for (const o of r.options) if (o.description !== '') out.push(` - \`${o.definition}\` ${o.description}`)
|
|
67
69
|
for (const [label, cmd] of r.examples) out.push(` - ${label}: \`${cmd}\``)
|
|
68
70
|
}
|
|
69
71
|
return out.join('\n').trim()
|
|
@@ -82,12 +84,13 @@ export class CommandsCommand extends Command {
|
|
|
82
84
|
|
|
83
85
|
static override usage = Command.Usage({
|
|
84
86
|
category: 'Health',
|
|
85
|
-
description: 'every command this binary registers, as markdown or json
|
|
87
|
+
description: 'every command this binary registers, as markdown or json',
|
|
88
|
+
details: 'every command this binary registers, as markdown or json — the source a docs page is generated FROM, never hand-copied',
|
|
86
89
|
examples: [
|
|
87
|
-
['markdown index', '
|
|
88
|
-
['machine-readable', '
|
|
89
|
-
['write into a docs page between the markers', '
|
|
90
|
-
['fail if that page is stale (lint mode)', '
|
|
90
|
+
['markdown index', 'sk commands'],
|
|
91
|
+
['machine-readable', 'sk commands --json'],
|
|
92
|
+
['write into a docs page between the markers', 'sk commands --out wiki/build/shipkit-cli.md'],
|
|
93
|
+
['fail if that page is stale (lint mode)', 'sk commands --out wiki/build/shipkit-cli.md --check'],
|
|
91
94
|
],
|
|
92
95
|
})
|
|
93
96
|
|
|
@@ -19,13 +19,14 @@ export class ConfigKeysCommand extends Command {
|
|
|
19
19
|
|
|
20
20
|
static override usage = Command.Usage({
|
|
21
21
|
category: 'Health',
|
|
22
|
-
description: 'every repo.config.ts key and
|
|
22
|
+
description: 'every repo.config.ts key and check field with its doc, from the types',
|
|
23
|
+
details: 'every repo.config.ts key and every check field with its doc, read from the types — the source a config reference page is generated FROM',
|
|
23
24
|
examples: [
|
|
24
|
-
['markdown reference', '
|
|
25
|
-
['machine-readable', '
|
|
26
|
-
['write into a docs page between the markers', '
|
|
27
|
-
['fail if that page is stale (lint mode)', '
|
|
28
|
-
['name the keys carrying no doc comment', '
|
|
25
|
+
['markdown reference', 'sk config-keys'],
|
|
26
|
+
['machine-readable', 'sk config-keys --json'],
|
|
27
|
+
['write into a docs page between the markers', 'sk config-keys --out wiki/build/shipkit/config-keys.md'],
|
|
28
|
+
['fail if that page is stale (lint mode)', 'sk config-keys --out wiki/build/shipkit/config-keys.md --check'],
|
|
29
|
+
['name the keys carrying no doc comment', 'sk config-keys --undocumented'],
|
|
29
30
|
],
|
|
30
31
|
})
|
|
31
32
|
|
package/src/cli/cmd_Contracts.ts
CHANGED
|
@@ -10,9 +10,9 @@ export class ContractsCommand extends Command {
|
|
|
10
10
|
category: 'Gate',
|
|
11
11
|
description: 'release-contract fulfillness, fast and filesystem-only — deploy checks dep on it',
|
|
12
12
|
examples: [
|
|
13
|
-
['all applicable contracts', '
|
|
14
|
-
['one venue', '
|
|
15
|
-
['machine-readable', '
|
|
13
|
+
['all applicable contracts', 'sk contracts'],
|
|
14
|
+
['one venue', 'sk contracts --venue itch'],
|
|
15
|
+
['machine-readable', 'sk contracts --json'],
|
|
16
16
|
],
|
|
17
17
|
})
|
|
18
18
|
|
|
@@ -60,7 +60,10 @@ export function renderActivity(a: ActivityAnswer, cap: number): string[] {
|
|
|
60
60
|
for (const r of [...busy, ...quiet]) {
|
|
61
61
|
const branch = r.branch ?? (r.detached == null ? '' : `detached ${r.detached}`)
|
|
62
62
|
out.push(`${r.name} ${dot(r)} ${branch} (${upstreamWords(r)})`)
|
|
63
|
-
|
|
63
|
+
for (const c of r.failing ?? []) {
|
|
64
|
+
out.push(` ${c.status === 'fail' ? '✗' : '!'} ${c.id}${c.at == null ? '' : ` (${ageShort(c.at, a.now)})`}`)
|
|
65
|
+
for (const l of c.lines) out.push(` ${l}`)
|
|
66
|
+
}
|
|
64
67
|
if (r.error != null) out.push(` git failed: ${r.error}`)
|
|
65
68
|
const dirt = r.error == null ? dirtWords(r) : ''
|
|
66
69
|
if (dirt !== '') {
|
|
@@ -82,12 +85,13 @@ export class CrossRepoActivityCommand extends Command {
|
|
|
82
85
|
|
|
83
86
|
static override usage = Command.Usage({
|
|
84
87
|
category: 'Home',
|
|
85
|
-
description: 'the activity page
|
|
88
|
+
description: 'the activity page as text: every house repo, its git state and recent commits',
|
|
89
|
+
details: 'the activity page in the console: every house repo (archived ones left out), its checks, branch, upstream, uncommitted work and commits in a window. The same computation the page reads, local git only, no daemon needed',
|
|
86
90
|
examples: [
|
|
87
|
-
['the last 30 minutes, 3 commits per repo, as the page opens', '
|
|
88
|
-
['the same, by the page name', '
|
|
89
|
-
['the last 3 hours, up to 10 commits per repo', '
|
|
90
|
-
['the route\'s exact payload', '
|
|
91
|
+
['the last 30 minutes, 3 commits per repo, as the page opens', 'sk cross-repo-activity'],
|
|
92
|
+
['the same, by the page name', 'sk activity'],
|
|
93
|
+
['the last 3 hours, up to 10 commits per repo', 'sk cross-repo-activity --max-age 3h --max-commit 10'],
|
|
94
|
+
['the route\'s exact payload', 'sk cross-repo-activity --max-age 30m --json'],
|
|
91
95
|
],
|
|
92
96
|
})
|
|
93
97
|
|