weir-harness 1.2.0 → 1.2.2
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/cordis.patch.yml +0 -2
- package/lib/client.blackboard-model.js +172 -56
- package/lib/client.capability-manager.js +0 -1
- package/lib/client.capability-model.js +378 -31
- package/lib/client.chain-model.js +80 -0
- package/lib/client.disabled-categories-editor.js +22 -0
- package/lib/client.edit-lock-maintenance.js +239 -246
- package/lib/client.edit-lock-panel.js +110 -0
- package/lib/client.hash-edit-model.js +48 -0
- package/lib/client.js +267 -1549
- package/lib/client.lsp-model.js +92 -0
- package/lib/client.lsp-panel.js +11 -16
- package/lib/client.lsp-toggle.js +18 -0
- package/lib/client.notify-permissions.js +112 -20
- package/lib/client.notify-web.js +14 -11
- package/lib/client.robash-model.js +26 -0
- package/lib/client.settings-page.js +287 -17
- package/lib/client.worktree-model.js +225 -0
- package/package.json +5 -2
- package/src/blackboard/durable.js +12 -0
- package/src/blackboard/index.js +2 -2
- package/src/blackboard/kernel.js +23 -6
- package/src/blackboard/notify.js +10 -3
- package/src/blackboard/remote.js +31 -13
- package/src/blackboard/storage.js +13 -5
- package/src/capabilities/apply-engine.js +189 -101
- package/src/capabilities/defaults-transaction.js +136 -1
- package/src/capabilities/lifecycle-snapshot.js +83 -204
- package/src/capabilities/mcp-admission.js +1 -23
- package/src/capabilities/mcp-drain.js +30 -19
- package/src/capabilities/mcp-facade.js +23 -3
- package/src/capabilities/preset-library.js +247 -0
- package/src/capabilities/preset-package.js +212 -1
- package/src/capabilities/same-name-policy.js +3 -41
- package/src/capabilities/selection-notify.js +324 -21
- package/src/capabilities/skill-office-adapter.js +7 -1
- package/src/capabilities/skill-selection-plugin.js +315 -729
- package/src/capabilities/store/checked-contract.d.ts +5 -0
- package/src/capabilities/store/fs-adapter.js +52 -0
- package/src/capabilities/store/lock.js +86 -0
- package/src/capabilities/store/paths.js +5 -0
- package/src/capabilities/store/store.js +105 -5
- package/src/creative-guide/guide.js +1 -1
- package/src/delegate/child-composition.js +258 -0
- package/src/delegate/group-coordinator.js +25 -27
- package/src/delegate/index.js +21 -2
- package/src/delegate/rehydrate.js +24 -4
- package/src/delegate/robash-guard-core.js +2 -2
- package/src/delegate/spawn-adapter.js +214 -100
- package/src/delegate/status-tool.js +9 -6
- package/src/delegate/supervision-mount.js +35 -6
- package/src/delegate/tool.js +29 -4
- package/src/{shared → delegate}/whitelist-defaults.js +2 -2
- package/src/edit-lock/admin-ledger.js +8 -11
- package/src/edit-lock/admin-recovery.js +2 -1
- package/src/edit-lock/admission.js +12 -2
- package/src/edit-lock/binding-guidance.js +28 -10
- package/src/edit-lock/binding-machine.js +312 -0
- package/src/edit-lock/derived-facts.js +67 -0
- package/src/edit-lock/index.js +44 -244
- package/src/edit-lock/inspect.js +113 -1
- package/src/edit-lock/lifecycle.js +8 -5
- package/src/edit-lock/limits.js +61 -0
- package/src/edit-lock/maintenance.js +5 -2
- package/src/edit-lock/manager.js +6 -2
- package/src/edit-lock/operation-history.js +1 -1
- package/src/edit-lock/peer-client.js +9 -2
- package/src/edit-lock/peer-transport.js +7 -1
- package/src/edit-lock/remote.js +11 -4
- package/src/edit-lock/state.js +2 -4
- package/src/edit-lock/view.js +10 -11
- package/src/lsp/admin.js +2 -24
- package/src/lsp/index.js +1 -1
- package/src/lsp/manager.js +1 -1
- package/src/notify/permissions-admin.js +1 -1
- package/src/{lsp/child-process.js → process/index.js} +23 -6
- package/src/settings/env-admin.js +1 -1
- package/src/settings/index.js +1 -1
- package/src/settings/sections.js +0 -54
- package/src/shared/audit.js +12 -0
- package/src/shared/child-scope.js +3 -1
- package/src/shared/http-json.js +28 -0
- package/src/{delegate/audit-readers.js → shared/terminal-evidence.js} +34 -4
- package/src/worktree/errors.js +3 -0
- package/src/worktree/index.js +1 -2
- package/src/worktree/lane-core.js +641 -0
- package/src/worktree/lane-views.js +147 -0
- package/src/worktree/lane-workflows.js +853 -0
- package/src/worktree/lanes.js +24 -1513
- package/src/worktree/runner.js +5 -4
- package/src/capabilities/content-pin.js +0 -88
- package/src/capabilities/content-refresh.js +0 -331
- package/src/capabilities/distribution-manifest.js +0 -78
- package/src/capabilities/isolated-exec.js +0 -106
- package/src/capabilities/publisher.js +0 -129
- package/src/capabilities/skill-admission.js +0 -181
- package/src/capabilities/update-lifecycle.js +0 -106
- package/src/edit-lock/remote-service.js +0 -28
- package/src/worktree/contract-guidance.test.js +0 -100
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Lane read views: actionsFor / view / safeMode / diffOf / board / summaryOf.
|
|
2
|
+
// Read-only over the ledger (repo.ledger.read()); refresh is reused from the
|
|
3
|
+
// core, so the read path keeps its existing reconciliation side effects
|
|
4
|
+
// (expired-watch pruning and orphan-card declines still audit there). This
|
|
5
|
+
// module itself adds no writes.
|
|
6
|
+
import { existsSync } from 'node:fs'
|
|
7
|
+
import { WorktreeError } from './errors.js'
|
|
8
|
+
import { CHECKABLE, LANDABLE_FROM, TRANSIENT, isActive, nextFor } from './state.js'
|
|
9
|
+
import { watchFacts } from './watches.js'
|
|
10
|
+
import { hasExclude } from './exclude.js'
|
|
11
|
+
import { renderBoard } from './prompts.js'
|
|
12
|
+
|
|
13
|
+
/** @param {ReturnType<typeof import('./lane-core.js').createLaneCore>} core */
|
|
14
|
+
export function createLaneViews(core) {
|
|
15
|
+
const { deps, git, approveModeSafe, approveModeSourceSafe, cwdOf, repoFor, repoCached, laneOf, refresh, readConfig } = core
|
|
16
|
+
|
|
17
|
+
// ─── views ────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
/** Legal actions per lane for the panel (disabled ones carry the reason). @param {any} lane */
|
|
20
|
+
function actionsFor(lane) {
|
|
21
|
+
const deny = (/** @type {string} */ reason) => ({ enabled: false, reason })
|
|
22
|
+
const allow = { enabled: true }
|
|
23
|
+
const exists = !['cleaned'].includes(lane.state) && !(lane.state === 'abandoned' && lane.cleanup?.mode !== 'keep')
|
|
24
|
+
return {
|
|
25
|
+
diff: lane.state === 'preparing' ? deny('setup is still running') : allow,
|
|
26
|
+
check: !CHECKABLE.includes(lane.state) ? deny(`not available while ${lane.state}`) : lane.boundChild ? deny('a worker is running in this lane') : allow,
|
|
27
|
+
land: !LANDABLE_FROM.includes(lane.state) ? deny(`only a landable lane can be merged (now ${lane.state})`) : lane.baseMoved ? deny(`the main worktree is not on ${lane.base.branch}`) : allow,
|
|
28
|
+
clean: ['landed', 'kept'].includes(lane.state) || (lane.state === 'abandoned' && lane.cleanup?.mode === 'keep') ? allow : deny('cleanup applies after merging'),
|
|
29
|
+
abandon: isActive(lane) ? (lane.boundChild ? deny('a worker is running in this lane') : allow) : deny(`already ${lane.state}`),
|
|
30
|
+
setup: lane.state === 'setup-failed' ? allow : deny('setup only reruns after a failure'),
|
|
31
|
+
copyPath: exists ? allow : deny('the worktree was removed'),
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Full read-only view for the GUI panel.
|
|
37
|
+
* @param {any} session
|
|
38
|
+
* @param {{ mode?: boolean, approve?: string | null, approveSource?: 'session' | 'global' }} [options] - cold-read override: a boolean
|
|
39
|
+
* `mode` replaces the live projection read (a pseudo session folded from
|
|
40
|
+
* the persisted log by sessionQuery has no live projection cells); `approve`
|
|
41
|
+
* and `approveSource` carry the cold-folded auto-approve override the same
|
|
42
|
+
* way (null = no override → the global default answers).
|
|
43
|
+
*/
|
|
44
|
+
async function view(session, options) {
|
|
45
|
+
const viewMode = () => (typeof options?.mode === 'boolean' ? options.mode : safeMode(session))
|
|
46
|
+
const viewApproveMode = () => (options && typeof options.approve === 'string' ? options.approve : approveModeSafe(session))
|
|
47
|
+
const viewApproveModeSource = () => (options && (options.approveSource === 'session' || options.approveSource === 'global') ? options.approveSource : approveModeSourceSafe(session))
|
|
48
|
+
let repo
|
|
49
|
+
try {
|
|
50
|
+
repo = await repoFor(cwdOf(session))
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const known = error instanceof WorktreeError
|
|
53
|
+
return { available: false, mode: viewMode(), approveMode: viewApproveMode(), approveModeSource: viewApproveModeSource(), error: known ? error.toJSON() : { code: 'ERROR', message: String(/** @type {any} */ (error)?.message ?? error) } }
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const { mainBranch, unmanaged } = await refresh(repo)
|
|
57
|
+
const ledger = repo.ledger.read()
|
|
58
|
+
/** @type {any} */
|
|
59
|
+
let verification
|
|
60
|
+
try {
|
|
61
|
+
const repoConfig = readConfig(repo)
|
|
62
|
+
verification = { enabled: repoConfig.check.length > 0, commands: repoConfig.check.map((entry) => entry.name), setup: repoConfig.setup }
|
|
63
|
+
} catch (error) {
|
|
64
|
+
verification = { enabled: true, commands: [], error: String(/** @type {any} */ (error)?.message ?? error) }
|
|
65
|
+
}
|
|
66
|
+
const lanes = []
|
|
67
|
+
for (const lane of [...ledger.lanes].reverse()) {
|
|
68
|
+
const exists = existsSync(lane.path)
|
|
69
|
+
let counts = null
|
|
70
|
+
let stat = null
|
|
71
|
+
if ((await git.branchExists(repo.mainRoot, lane.branch).catch(() => false))) {
|
|
72
|
+
counts = await git.aheadBehind(repo.mainRoot, lane.base.branch, lane.branch).catch(() => null)
|
|
73
|
+
stat = await git.diffStat(repo.mainRoot, lane.base.branch, lane.branch).catch(() => null)
|
|
74
|
+
}
|
|
75
|
+
lanes.push({
|
|
76
|
+
...lane,
|
|
77
|
+
history: (lane.history ?? []).slice(-12),
|
|
78
|
+
exists,
|
|
79
|
+
ahead: counts?.ahead ?? null,
|
|
80
|
+
behind: counts?.behind ?? null,
|
|
81
|
+
stat,
|
|
82
|
+
next: nextFor(lane),
|
|
83
|
+
transient: TRANSIENT.includes(lane.state),
|
|
84
|
+
...watchFacts(ledger.watches, lane.id),
|
|
85
|
+
actions: actionsFor(lane),
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
available: true,
|
|
90
|
+
mode: viewMode(),
|
|
91
|
+
approveMode: viewApproveMode(),
|
|
92
|
+
approveModeSource: viewApproveModeSource(),
|
|
93
|
+
ownedBySession: lanes.filter((lane) => lane.ownerSession === session?.id).map((lane) => lane.id),
|
|
94
|
+
repo: { mainRoot: repo.mainRoot, root: repo.root, rootPath: repo.rootPath, branch: mainBranch, gitVersion: repo.version?.join('.') ?? null, exclude: hasExclude(repo.commonDir, repo.root), verification },
|
|
95
|
+
lanes,
|
|
96
|
+
unmanaged,
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const known = error instanceof WorktreeError
|
|
100
|
+
return { available: false, mode: viewMode(), approveMode: viewApproveMode(), approveModeSource: viewApproveModeSource(), error: known ? error.toJSON() : { code: 'ERROR', message: String(/** @type {any} */ (error)?.message ?? error) } }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** @param {any} session */
|
|
105
|
+
function safeMode(session) {
|
|
106
|
+
try {
|
|
107
|
+
return deps.modeOf(session) === true
|
|
108
|
+
} catch {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** @param {any} session @param {string} laneId */
|
|
114
|
+
async function diffOf(session, laneId) {
|
|
115
|
+
const repo = await repoFor(cwdOf(session))
|
|
116
|
+
const lane = laneOf(repo, laneId)
|
|
117
|
+
if (lane.land?.commit) return git.diff(repo.mainRoot, `${lane.land.commit}^1`, lane.land.commit)
|
|
118
|
+
return git.diff(repo.mainRoot, lane.base.branch, lane.branch)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Runtime-context board (sync; empty until the repo resolved once). @param {any} session */
|
|
122
|
+
function board(session) {
|
|
123
|
+
const repo = repoCached(session)
|
|
124
|
+
const mode = safeMode(session)
|
|
125
|
+
if (!repo) return mode ? renderBoard({ lanes: [], mode }) : ''
|
|
126
|
+
try {
|
|
127
|
+
const ledger = repo.ledger.read()
|
|
128
|
+
return renderBoard({ lanes: ledger.lanes, watches: ledger.watches, mode })
|
|
129
|
+
} catch {
|
|
130
|
+
return ''
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Lane ids this session owns / active counts for quick status. @param {any} session */
|
|
135
|
+
function summaryOf(session) {
|
|
136
|
+
const repo = repoCached(session)
|
|
137
|
+
if (!repo) return null
|
|
138
|
+
try {
|
|
139
|
+
const lanes = repo.ledger.read().lanes.filter((/** @type {any} */ lane) => lane.ownerSession === session?.id)
|
|
140
|
+
return { active: lanes.filter(isActive).length, awaiting: lanes.filter((/** @type {any} */ lane) => lane.state === 'awaiting-approval').length }
|
|
141
|
+
} catch {
|
|
142
|
+
return null
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return { actionsFor, view, diffOf, board, summaryOf }
|
|
147
|
+
}
|