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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Supervised group coordinator: registry state machine for grouped delegation.
|
|
2
2
|
// Pure logic (no DSH imports) — the mount layer (index.js/tool.js) feeds it
|
|
3
3
|
// session events and injects the effectors (sendMessage/interrupt/timers).
|
|
4
|
+
import { isTerminalStatus, parseTerminalStatus } from '../shared/terminal-evidence.js'
|
|
4
5
|
|
|
5
6
|
export const SUPERVISION_CONTRACT = `
|
|
6
7
|
|
|
@@ -30,15 +31,6 @@ export const DEFAULT_SUPERVISION = {
|
|
|
30
31
|
/** Bounded wait for the last settlement notice before the fallback delivery. */
|
|
31
32
|
export const SIGNAL_FALLBACK_MS = 1000
|
|
32
33
|
|
|
33
|
-
/** Parse a child's final assistant text into a terminal status, or null. */
|
|
34
|
-
export function parseTerminalStatus(text) {
|
|
35
|
-
if (typeof text !== 'string' || text.length === 0) return null
|
|
36
|
-
const match = /^STATUS:[ \t]*(completed|blocked)[ \t]*$/m.exec(text)
|
|
37
|
-
if (!match) return null
|
|
38
|
-
const reportMatch = /^REPORT:[ \t]*([\s\S]*)$/m.exec(text.slice(match.index))
|
|
39
|
-
return { status: match[1], report: (reportMatch?.[1] ?? '').trim() }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
34
|
/**
|
|
43
35
|
* Canonical member record shape: eight fields, fixed order. The single source
|
|
44
36
|
* every construction site converges on (registerMember, hydrate, rehydrate).
|
|
@@ -55,26 +47,31 @@ export function createGroupRecord(name, { sealed = false, settled = false, membe
|
|
|
55
47
|
}
|
|
56
48
|
|
|
57
49
|
/**
|
|
58
|
-
* Single exit for the
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
50
|
+
* Single exit for the untracked-catalog predicate: catalog children the
|
|
51
|
+
* supervision registry does not track AND no one-shot/continuable spawn fact
|
|
52
|
+
* claims. The row shape is { id, label, mode } (mode is passed through
|
|
53
|
+
* verbatim: DSH 0.2.1 reports every local child as 'continuable' and may also
|
|
54
|
+
* report 'external', so the catalog mode no longer discriminates lanes — the
|
|
55
|
+
* durable spawn facts do).
|
|
56
|
+
* `isTracked(id)` is the caller's registry lookup. `spawnFactOf(id)` returns
|
|
57
|
+
* the durable delegate/spawn fact for a weir-spawned child (lane included):
|
|
58
|
+
* one-shot and plain-continuable children must never be resurrected as
|
|
59
|
+
* supervision orphans, while a supervised child normally IS tracked and a
|
|
60
|
+
* supervised child missing from the fact chain stays visible as an orphan
|
|
61
|
+
* (never hidden). Only a fact-less orphan (not spawned by this weir build)
|
|
62
|
+
* keeps the promoted/recovered semantics.
|
|
63
|
+
* @param {object[]} entries - DSH catalog children
|
|
64
|
+
* @param {(id: string) => boolean} isTracked
|
|
65
|
+
* @param {(id: string) => { lane?: string } | undefined} [spawnFactOf]
|
|
69
66
|
*/
|
|
70
|
-
export function untrackedCatalogEntries(entries, isTracked) {
|
|
67
|
+
export function untrackedCatalogEntries(entries, isTracked, spawnFactOf) {
|
|
71
68
|
const untracked = []
|
|
72
69
|
for (const entry of entries ?? []) {
|
|
73
70
|
if (!entry || typeof entry !== 'object') continue
|
|
74
|
-
const mode = entry.mode === undefined ? 'continuable' : entry.mode
|
|
75
|
-
if (mode !== 'continuable') continue
|
|
76
71
|
if (isTracked(entry.id)) continue
|
|
77
|
-
|
|
72
|
+
const lane = spawnFactOf?.(entry.id)?.lane
|
|
73
|
+
if (lane === 'one-shot' || lane === 'continuable') continue
|
|
74
|
+
untracked.push({ id: entry.id, label: entry.label ?? '', mode: entry.mode })
|
|
78
75
|
}
|
|
79
76
|
return untracked
|
|
80
77
|
}
|
|
@@ -89,7 +86,8 @@ export function untrackedCatalogEntries(entries, isTracked) {
|
|
|
89
86
|
* @param {(delayMs: number, fn: () => void) => void} deps.schedule - delayed retry scheduler
|
|
90
87
|
* @param {(reason: string) => void} [deps.onAudit]
|
|
91
88
|
* @param {(fact: object) => void} [deps.onFact] - structured supervision facts (durability)
|
|
92
|
-
|
|
89
|
+
* @param {(text: string) => void} [deps.notifyParent] - deliver a parent-facing signal (timer-deferred followup)
|
|
90
|
+
* @param {(childId: string) => { lane?: string } | undefined} [deps.spawnFactOf] - durable delegate/spawn fact for one child id (lane decides orphan resurrection; see untrackedCatalogEntries)
|
|
93
91
|
*/
|
|
94
92
|
export function createGroupCoordinator(deps, config = {}) {
|
|
95
93
|
const cfg = { ...DEFAULT_SUPERVISION, ...config }
|
|
@@ -190,9 +188,9 @@ export function createGroupCoordinator(deps, config = {}) {
|
|
|
190
188
|
}
|
|
191
189
|
}
|
|
192
190
|
|
|
193
|
-
/** Catalog cross-check:
|
|
191
|
+
/** Catalog cross-check: catalog children this registry does not track (spawn-fact aware). */
|
|
194
192
|
function untrackedAgainstCatalog(entries) {
|
|
195
|
-
return untrackedCatalogEntries(entries, (id) => children.has(id))
|
|
193
|
+
return untrackedCatalogEntries(entries, (id) => children.has(id), deps.spawnFactOf)
|
|
196
194
|
}
|
|
197
195
|
|
|
198
196
|
function noteAssistantText(childId, text) {
|
package/src/delegate/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Weir delegate plugin: category registry + curated agents + the delegate
|
|
2
2
|
// tool. Plain ESM, ctx-only. Composition root: all policy lives in the sibling
|
|
3
3
|
// modules (settings-overlay / target-resolver / supervision-tools /
|
|
4
|
-
// supervision-mount
|
|
4
|
+
// supervision-mount); apply() only constructs and wires them. The terminal-
|
|
5
|
+
// evidence cold readers live in src/shared/terminal-evidence.js (shared with
|
|
6
|
+
// the worktree plugin).
|
|
5
7
|
import { CURATED_AGENTS } from './agents.js'
|
|
6
8
|
import { createSettingsOverlay } from './settings-overlay.js'
|
|
7
9
|
import { createTargetResolver } from './target-resolver.js'
|
|
@@ -11,11 +13,12 @@ import { skillSelectionFor } from '../capabilities/skill-selection-plugin.js'
|
|
|
11
13
|
import { createResumeTool, createTerminateTool } from './supervision-tools.js'
|
|
12
14
|
import { mountSupervision } from './supervision-mount.js'
|
|
13
15
|
import { createAudit } from '../shared/audit.js'
|
|
14
|
-
import { FALLBACK_TABLES } from '
|
|
16
|
+
import { FALLBACK_TABLES } from './whitelist-defaults.js'
|
|
15
17
|
import { createDelegateTool } from './tool.js'
|
|
16
18
|
import { attachWorktreeModeGuard } from './worktree-mode.js'
|
|
17
19
|
import { DOCTRINE_SECTION_ORDER } from '../core/doctrine.js'
|
|
18
20
|
import { isDelegatedChild } from '../shared/child-scope.js'
|
|
21
|
+
import { createChildComposition } from './child-composition.js'
|
|
19
22
|
import {
|
|
20
23
|
DELEGATE_TARGETS_SECTION_NAME,
|
|
21
24
|
DELEGATE_TARGETS_SECTION_ORDER_OFFSET,
|
|
@@ -95,6 +98,20 @@ function apply(ctx, config = {}) {
|
|
|
95
98
|
onAdaptersUpdated: (fn) => ctx.on('llm/adapters-updated', fn),
|
|
96
99
|
})
|
|
97
100
|
|
|
101
|
+
// Creation-window child composition (DSH 0.2.1 removed the request-level
|
|
102
|
+
// persona/toolFilter): the shim applies the reserved spawn's composition in
|
|
103
|
+
// the child's agent/created window and replays it from the audit channel on
|
|
104
|
+
// cold resume. One instance per plugin context; dispose unregisters it.
|
|
105
|
+
const composition = createChildComposition({
|
|
106
|
+
ctx,
|
|
107
|
+
audit,
|
|
108
|
+
logger: ctx.logger,
|
|
109
|
+
restrictableNames: () => ctx.tools.view?.(undefined)?.restrictableNames,
|
|
110
|
+
// Feed the supervision catalog cross-check the same durable fact without a
|
|
111
|
+
// file re-read (spawn-fact lane decides orphan resurrection).
|
|
112
|
+
onSpawn: mount.noteSpawnFact,
|
|
113
|
+
})
|
|
114
|
+
|
|
98
115
|
ctx.tools.register(
|
|
99
116
|
createDelegateTool({
|
|
100
117
|
resolveTarget: targetResolver.resolveTarget,
|
|
@@ -112,6 +129,7 @@ function apply(ctx, config = {}) {
|
|
|
112
129
|
// names, so the child deny list names only tools this composition
|
|
113
130
|
// actually registers (tools.restrict() rejects unknown deny names).
|
|
114
131
|
restrictableNames: () => ctx.tools.view?.(undefined)?.restrictableNames,
|
|
132
|
+
composition,
|
|
115
133
|
}),
|
|
116
134
|
)
|
|
117
135
|
|
|
@@ -163,6 +181,7 @@ function apply(ctx, config = {}) {
|
|
|
163
181
|
return () => {
|
|
164
182
|
offModeGuard()
|
|
165
183
|
mount.dispose()
|
|
184
|
+
composition.dispose()
|
|
166
185
|
}
|
|
167
186
|
}
|
|
168
187
|
|
|
@@ -2,27 +2,44 @@
|
|
|
2
2
|
// restart. Pure logic — the mount layer feeds it parsed audit records and the
|
|
3
3
|
// DSH catalog; no DSH imports, no fs.
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { createMemberRecord, createGroupRecord, untrackedCatalogEntries } from './group-coordinator.js'
|
|
6
|
+
import { parseTerminalStatus, isTerminalStatus } from '../shared/terminal-evidence.js'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Rebuild supervision state by replaying structured audit facts and
|
|
9
10
|
* cross-checking the DSH subagent catalog.
|
|
10
11
|
*
|
|
12
|
+
* Two fact channels ride the same audit file: the supervision facts
|
|
13
|
+
* (`weir/supervision/<kind>`) and the child-composition spawn facts
|
|
14
|
+
* (`weir/delegate/spawn`, which carry the lane). The spawn facts decide which
|
|
15
|
+
* catalog children are supervision orphans — DSH 0.2.1 reports every local
|
|
16
|
+
* child as mode 'continuable', so the catalog mode can no longer tell a
|
|
17
|
+
* one-shot child from a supervised one.
|
|
18
|
+
*
|
|
11
19
|
* @param {object} input
|
|
12
20
|
* @param {string} input.parentId - the parent session id (record filter key)
|
|
13
21
|
* @param {object[]} input.records - parsed audit JSONL records (already tail-read; may contain other sessions/types)
|
|
14
22
|
* @param {object[]} input.catalogChildren - DSH catalog entries ({ id, label?, mode? }); best-effort
|
|
15
|
-
* @returns {{ children: object[], groups: object[], untracked: object[], confidence: 'full'|'partial', factsSeen: number }}
|
|
23
|
+
* @returns {{ children: object[], groups: object[], untracked: object[], spawnFacts: object[], confidence: 'full'|'partial', factsSeen: number }}
|
|
16
24
|
*/
|
|
17
25
|
export function rehydrateSupervision({ parentId, records, catalogChildren }) {
|
|
18
26
|
const children = new Map()
|
|
19
27
|
const groups = new Map()
|
|
28
|
+
/** @type {Map<string, { childId: string, lane?: string }>} */
|
|
29
|
+
const spawnFacts = new Map()
|
|
20
30
|
let factsSeen = 0
|
|
21
31
|
|
|
22
32
|
for (const record of records ?? []) {
|
|
23
33
|
if (!record || typeof record !== 'object') continue
|
|
24
34
|
if (record.session !== undefined && record.session !== null && record.session !== parentId) continue
|
|
25
35
|
const type = typeof record.type === 'string' ? record.type : ''
|
|
36
|
+
if (type === 'weir/delegate/spawn') {
|
|
37
|
+
const fact = record.data
|
|
38
|
+
if (fact && typeof fact === 'object' && typeof fact.childId === 'string' && fact.childId.length > 0) {
|
|
39
|
+
spawnFacts.set(fact.childId, { childId: fact.childId, lane: typeof fact.lane === 'string' ? fact.lane : undefined })
|
|
40
|
+
}
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
26
43
|
if (!type.startsWith('weir/supervision/')) continue
|
|
27
44
|
const fact = record.data
|
|
28
45
|
if (!fact || typeof fact !== 'object' || typeof fact.kind !== 'string') continue
|
|
@@ -36,13 +53,16 @@ export function rehydrateSupervision({ parentId, records, catalogChildren }) {
|
|
|
36
53
|
group.settled = group.sealed === true && group.memberIds.length > 0 && terminal
|
|
37
54
|
}
|
|
38
55
|
|
|
39
|
-
// Catalog cross-check:
|
|
40
|
-
|
|
56
|
+
// Catalog cross-check: only fact-less orphans remain untracked (the spawn
|
|
57
|
+
// facts identify the one-shot/continuable children this registry must never
|
|
58
|
+
// resurrect, and keep a supervised child whose fact chain is broken visible).
|
|
59
|
+
const untracked = untrackedCatalogEntries(catalogChildren, (id) => children.has(id), (id) => spawnFacts.get(id))
|
|
41
60
|
|
|
42
61
|
return {
|
|
43
62
|
children: [...children.values()],
|
|
44
63
|
groups: [...groups.values()],
|
|
45
64
|
untracked,
|
|
65
|
+
spawnFacts: [...spawnFacts.values()],
|
|
46
66
|
confidence: factsSeen > 0 ? 'full' : 'partial',
|
|
47
67
|
factsSeen,
|
|
48
68
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Read-only shell guard core: the single canonical home of every cross-shell
|
|
2
2
|
// policy the bash and pwsh adapters share — the whitelist tables (one
|
|
3
3
|
// representation, consumed by the guard adapters, delegate/index.js, and
|
|
4
|
-
//
|
|
4
|
+
// whitelist-defaults.js), the git gate, the GIT_CONFIG_* environment
|
|
5
5
|
// smuggle refusal, the recursion budget, the redirect sink policy, and the
|
|
6
6
|
// per-executable verdict tail. Pure functions, no ctx access.
|
|
7
7
|
//
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// the three & roles, alias expansion), so the scanners are not merged.
|
|
11
11
|
|
|
12
12
|
/** Canonical whitelist tables, organized by the five published keys so
|
|
13
|
-
*
|
|
13
|
+
* whitelist-defaults.js derives FALLBACK_TABLES with zero translation.
|
|
14
14
|
* Entries moved verbatim from the former DEFAULT_ROBASH (robash-guard.js) and
|
|
15
15
|
* DEFAULT_ROBASH_PWSH (robash-guard-pwsh.js); pwsh entries keep their original
|
|
16
16
|
* casing (the pwsh adapter lowercases at lookup) so the shipped
|