@mstar-harness/dsh 3.6.3 → 3.7.1
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/README.i18n.yaml +2 -2
- package/README.md +8 -8
- package/README.zh.md +7 -5
- package/dist/client/panel/PanelView.d.ts +8 -11
- package/dist/client/panel/TabNav.d.ts +2 -2
- package/dist/client/panel/graph/event-log.d.ts +5 -9
- package/dist/client/panel/graph/project-graph.d.ts +53 -72
- package/dist/client/panel/graph/schema.d.ts +31 -37
- package/dist/client/panel/locale.d.ts +19 -19
- package/dist/client/panel/pages/AgentCanvasPage.d.ts +40 -58
- package/dist/client/panel/pages/EventLogPage.d.ts +6 -6
- package/dist/client/panel/pages/IterationInfoSection.d.ts +9 -11
- package/dist/client/panel/pages/IterationTaskPage.d.ts +3 -3
- package/dist/client/panel/plan-sort.d.ts +3 -6
- package/dist/client/panel/state-section.d.ts +1 -1
- package/dist/client/panel/zones/Legend.d.ts +2 -2
- package/dist/client/panel/zones/ProjectRollup.d.ts +1 -2
- package/dist/client/panel/zones/TaskBoard.d.ts +1 -2
- package/dist/gates/_shared.d.ts +24 -16
- package/dist/gates/adapter.d.ts +6 -9
- package/dist/gates/agent-flow.d.ts +49 -59
- package/dist/gates/agent-personas.d.ts +1 -2
- package/dist/gates/catalog.d.ts +2 -5
- package/dist/gates/dispatch.d.ts +9 -11
- package/dist/gates/fallbacks-advisory.d.ts +55 -18
- package/dist/gates/fallbacks-probe.d.ts +2 -2
- package/dist/gates/fallbacks-seeds.d.ts +1 -1
- package/dist/gates/fallbacks-structural.d.ts +1 -1
- package/dist/gates/goal-bridge.d.ts +6 -9
- package/dist/gates/role-persona.d.ts +123 -7
- package/dist/gates/skill-lint.d.ts +19 -2
- package/dist/gates/system-prompt.d.ts +7 -11
- package/dist/gates/tools.d.ts +1 -1
- package/dist/gates/workflow-ledger.d.ts +21 -28
- package/dist/gates/workflow-policy.d.ts +15 -19
- package/dist/gates/workflow-selection.d.ts +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +472 -183
- package/dist/types.d.ts +4 -7
- package/harness-commands/iteration-drive.md +6 -6
- package/harness-commands/iteration-loop.md +7 -7
- package/harness-commands/iteration-start.md +8 -8
- package/harness-skills/mstar-coding-behavior/SKILL.md +3 -20
- package/harness-skills/mstar-dispatch-gates/SKILL.md +7 -13
- package/harness-skills/mstar-dispatch-gates/references/leaf-executor-checklist.md +1 -1
- package/harness-skills/mstar-harness-core/SKILL.md +16 -53
- package/harness-skills/mstar-host/references/zcode.md +7 -0
- package/harness-skills/mstar-iteration/SKILL.md +32 -318
- package/harness-skills/mstar-iteration/references/command-shared-invariants.md +1 -1
- package/harness-skills/mstar-iteration/references/phase-1-prepare.md +155 -0
- package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +113 -3
- package/harness-skills/mstar-iteration/references/phase5-helper-discovery.md +1 -1
- package/harness-skills/mstar-roles/SKILL.md +14 -12
- package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +5 -6
- package/harness-skills/mstar-roles/references/architect.md +1 -1
- package/harness-skills/mstar-roles/references/code-reviewer.md +11 -1
- package/harness-skills/mstar-roles/references/frontend-dev.md +1 -1
- package/harness-skills/mstar-roles/references/fullstack-dev-shared.md +1 -1
- package/harness-skills/mstar-roles/references/ops-engineer.md +1 -1
- package/harness-skills/mstar-roles/references/product-manager.md +1 -1
- package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +4 -0
- package/harness-skills/mstar-roles/references/project-manager.md +6 -4
- package/harness-skills/mstar-roles/references/prompt-engineer.md +1 -1
- package/harness-skills/mstar-roles/references/qa-engineer.md +1 -1
- package/harness-skills/mstar-roles/references/qc-specialist-shared.md +1 -1
- package/harness-skills/mstar-roles/references/writing-specialist.md +1 -1
- package/harness-skills/mstar-sdd/references/file-handoffs.md +40 -7
- package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +9 -0
- package/harness-skills/mstar-sdd/references/implementer-prompt.md +9 -0
- package/harness-skills/mstar-sdd/references/task-reviewer-prompt.md +7 -0
- package/package.json +1 -1
package/dist/gates/catalog.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface CatalogCacheEntry {
|
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* The apply-scoped `harnessDir → cache key` reverse map + invalidation
|
|
17
|
-
* closure
|
|
17
|
+
* closure : the
|
|
18
18
|
* catalog cache is keyed by {@link EXPLICIT_CACHE_KEY} or the session cwd,
|
|
19
19
|
* while ledger records (dispatch/settle) identify the affected workspace by
|
|
20
20
|
* `{HARNESS_DIR}` — the reverse map bridges the two so a ledger change
|
|
@@ -96,10 +96,7 @@ export declare function buildCatalogSources(ctx: Context, harnessDir: string | n
|
|
|
96
96
|
* workspace root and TTL-refreshed — Config `catalogTtlMs`).
|
|
97
97
|
* @param ttlMs - catalog refresh interval in milliseconds.
|
|
98
98
|
* @param register - the apply-scoped `harnessDir → cache key` reverse-map
|
|
99
|
-
* registration
|
|
100
|
-
* workspace's entry invalidatable by a ledger change; see
|
|
101
|
-
* `createCatalogInvalidation`).
|
|
102
|
-
* @param digests - per agent+workspace turn digests (last rendered text)
|
|
99
|
+
* registration. * @param digests - per agent+workspace turn digests (last rendered text)
|
|
103
100
|
* for the digest-gated re-emission.
|
|
104
101
|
* @param payload - the proposed step the loop is about to enter.
|
|
105
102
|
* @param next - the remaining pre-step chain; its value is the delegated decision.
|
package/dist/gates/dispatch.d.ts
CHANGED
|
@@ -11,14 +11,13 @@ export declare const DISPATCH_LOGGER = "mstar/dispatch-gate";
|
|
|
11
11
|
* default id + its fork sibling — roadmap §9 W-B1: fork dispatches carry the
|
|
12
12
|
* same Assignment-shaped `{ description, prompt }` args and must be gated
|
|
13
13
|
* like `subagent`). Exported SHARED with the agent-flow settle pairing
|
|
14
|
-
* (`registerSettleListener` matches the same tool set
|
|
15
|
-
* `20260811-panel-f4-timeliness` Task 1) so the default cannot drift between
|
|
14
|
+
* (`registerSettleListener` matches the same tool set) so the default cannot drift between
|
|
16
15
|
* the gate and the settle seam.
|
|
17
16
|
*/
|
|
18
17
|
export declare const DEFAULT_DISPATCH_TOOLS: readonly ["subagent", "subagent_fork"];
|
|
19
18
|
/**
|
|
20
19
|
* The fixed workflow/ralph tool names the workflow gate matches (plan
|
|
21
|
-
*
|
|
20
|
+
* — architect-verified): the workflow tool
|
|
22
21
|
* registers under Config-default name `'workflow'` and is RENAMEABLE per
|
|
23
22
|
* instance (`toolName`, `tool-workflow/src/index.ts:41`); `ralph` is a
|
|
24
23
|
* fixed name (`tool-ralph/src/index.ts:413`). A renamed instance is out
|
|
@@ -51,7 +50,7 @@ export interface DispatchGateAdvisory {
|
|
|
51
50
|
* stay silent — no false-positive warnings. Callers MUST pass the engine
|
|
52
51
|
* `assignmentHeaderRegion` slice: a `## Assignment` heading or
|
|
53
52
|
* field line quoted in the task body must not shape a non-assignment prompt.
|
|
54
|
-
* Exported for the agent-flow ledger's shape guard
|
|
53
|
+
* Exported for the agent-flow ledger's shape guard — the shared
|
|
55
54
|
* `DshHostAdapter.dispatchGate` core applies the SAME guard on both dispatch
|
|
56
55
|
* surfaces, so the exec-less host-hook path records nothing for
|
|
57
56
|
* non-Assignment text either).
|
|
@@ -65,7 +64,7 @@ export declare function isAssignmentShaped(assignmentText: string): boolean;
|
|
|
65
64
|
* frontmatter, else warn-only.
|
|
66
65
|
*/
|
|
67
66
|
export declare function resolveDispatchHard(harnessDir: string | null, config: Config, assignmentText: string): boolean;
|
|
68
|
-
/** A header value that means "no value" (placeholder conventions). Type guard so callers narrow to `string`. Shared with the agent-flow ledger
|
|
67
|
+
/** A header value that means "no value" (placeholder conventions). Type guard so callers narrow to `string`. Shared with the agent-flow ledger (one grammar, no copy-paste drift). */
|
|
69
68
|
export declare function isNaValue(value: string | undefined): value is undefined;
|
|
70
69
|
/**
|
|
71
70
|
* Resolve the target plan id from the Assignment HEADER region: `Plan Path`
|
|
@@ -95,7 +94,7 @@ export declare function sessionIdOf(exec: ToolExecution): string | undefined;
|
|
|
95
94
|
* whose plan row is `InProgress`.
|
|
96
95
|
*
|
|
97
96
|
* Contract (status-and-residuals.md § Pre-dispatch re-verify; v3
|
|
98
|
-
* relocation —
|
|
97
|
+
* relocation —): before any
|
|
99
98
|
* writable implement dispatch, reread the ACTIVE workflow snapshot
|
|
100
99
|
* (`workflows/<id>/snapshot.json` — the v1 root `plans[]` home is gone; the
|
|
101
100
|
* root v2 `status.json` supplies the active `workflows[]`) and confirm
|
|
@@ -150,8 +149,7 @@ export declare function dispatchGateCore(config: Config, harnessDir: string | nu
|
|
|
150
149
|
};
|
|
151
150
|
/**
|
|
152
151
|
* The workflow-gate input composed from one `workflow`/`ralph` tool call
|
|
153
|
-
*
|
|
154
|
-
* P-c and Task 3 P-b policies): the tool name + the structural reads of
|
|
152
|
+
* : the tool name + the structural reads of
|
|
155
153
|
* `meta` (workflow) / `objective` (ralph) + the in-flight call.
|
|
156
154
|
*/
|
|
157
155
|
export interface WorkflowGateInput {
|
|
@@ -164,7 +162,7 @@ export interface WorkflowGateInput {
|
|
|
164
162
|
/** The in-flight tool call — Task 3 P-b lease attribution reads the calling agent/session off it. */
|
|
165
163
|
exec: ToolExecution;
|
|
166
164
|
/**
|
|
167
|
-
* P-b lease attribution
|
|
165
|
+
* P-b lease attribution: the calling workspace's first
|
|
168
166
|
* `InProgress` plan lacking `execution_lease` coverage (computed by
|
|
169
167
|
* {@link writableFanOutUncovered} from the status.json read through the
|
|
170
168
|
* contained resolver path — `preExecuteListener` already resolved the
|
|
@@ -177,7 +175,7 @@ export interface WorkflowGateInput {
|
|
|
177
175
|
/**
|
|
178
176
|
* Compose the {@link WorkflowGateInput} from one workflow/ralph tool call's
|
|
179
177
|
* arguments — structural reads, NEVER throws (plan
|
|
180
|
-
*
|
|
178
|
+
* Task 1; args shapes architect-verified:
|
|
181
179
|
* workflow `{ script, meta: { name, description, whenToUse?, phases? },
|
|
182
180
|
* args? }` (`tool-workflow/src/index.ts:152-161`); ralph
|
|
183
181
|
* `{ objective, maxRounds?, maxHandoffChars? }`
|
|
@@ -187,7 +185,7 @@ export interface WorkflowGateInput {
|
|
|
187
185
|
*
|
|
188
186
|
* `meta.name` is NORMALIZED through {@link normalizeWorkflowName} (control
|
|
189
187
|
* chars stripped) BEFORE the empty check — the P-c cache-key congruence
|
|
190
|
-
* fold-in
|
|
188
|
+
* fold-in: the run-start observation (workflow-ledger.ts)
|
|
191
189
|
* keys the ask cache with the SAME normalized name, so a control-char name
|
|
192
190
|
* (`au\u0000dit`) asks once and observes under one key instead of re-asking
|
|
193
191
|
* forever. The length is NEVER capped here (the gate's identity axis is
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Warn-only adoption advisory for the OPTIONAL `dsh-llm-fallbacks` plugin
|
|
3
|
-
* (plan
|
|
4
|
-
* Task 3): when the capability is mounted, ONE advisory pass per apply
|
|
3
|
+
* (plan Task 4 + when the capability is mounted, ONE advisory pass per apply
|
|
5
4
|
* reports the deployment's fallbacks taxonomy state (bounded: ≤1 warn per
|
|
6
5
|
* category, logger `mstar/fallbacks-advisory`):
|
|
7
6
|
*
|
|
@@ -28,12 +27,18 @@
|
|
|
28
27
|
*
|
|
29
28
|
* Unreadable row config (absent field / non-object, or an unreadable
|
|
30
29
|
* `roles.list`) → skip + one debug log. Unmounted → the pass is not invoked
|
|
31
|
-
* (
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
30
|
+
* (`{ ran: false, converged: false }`, no logs). An aborted pass (any caught
|
|
31
|
+
* error, including a rejected re-declare) reports `{ ran: true, converged:
|
|
32
|
+
* false }` — the honest latch: the caller arms its one-shot latch only on
|
|
33
|
+
* `ran && converged`, so a failed pass never suppresses the decision-point
|
|
34
|
+
* retry. The degraded-abort warn is deduplicated to at most ONE per apply
|
|
35
|
+
* (module flag; the entry resets it via {@link resetAdvisoryAbortWarn}).
|
|
36
|
+
* The advisory NEVER writes the fallbacks config — the read is read-only
|
|
37
|
+
* over the deployment's config layer (never the fallbacks plugin's module
|
|
38
|
+
* internals); the only write path is the idempotent seeds re-declare
|
|
39
|
+
* through the released seeds surface (no-delta → no settings write
|
|
40
|
+
* upstream). The advisory never throws (the caller's dispatch/apply flow is
|
|
41
|
+
* never affected).
|
|
37
42
|
*
|
|
38
43
|
* Module boundary: no barrel — the entry imports this module by explicit
|
|
39
44
|
* relative path (the role-persona module pattern).
|
|
@@ -54,24 +59,56 @@ export declare function setAdvisoryLogger(sink: AdvisoryLogSink): AdvisoryLogSin
|
|
|
54
59
|
/**
|
|
55
60
|
* Warn id-list cap: an id-list warn line lists at most this many ids before
|
|
56
61
|
* the `… and K more` suffix — a huge registry (thousands of rows) must not
|
|
57
|
-
* produce a multi-KB log line (
|
|
62
|
+
* produce a multi-KB log line (cap). Exported for the
|
|
58
63
|
* suite's cap assertions; module surface only — the entry's frozen 47-name
|
|
59
64
|
* export surface deliberately does not re-export it.
|
|
60
65
|
*/
|
|
61
66
|
export declare const ADVISORY_ID_LIST_CAP = 20;
|
|
62
67
|
/**
|
|
63
|
-
* One advisory pass
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* One advisory pass outcome (the honest-latch contract):
|
|
69
|
+
* - `ran` — the pass executed (the capability is mounted); `false` means the
|
|
70
|
+
* pass was not invoked (unmounted). Carries the one-pass-per-apply
|
|
71
|
+
* bookkeeping.
|
|
72
|
+
* - `converged` — the pass reached its converged end. Per return path:
|
|
73
|
+
* unmounted → `false`; aborted pass (any caught error, including a
|
|
74
|
+
* rejected re-declare) → `false`; a no-re-declare path (loader-fallback
|
|
75
|
+
* structural read, unreadable config, or a service-present pass that
|
|
76
|
+
* never reaches the re-declare) → `true`; service-present path → reflects
|
|
77
|
+
* the re-declare resolving.
|
|
78
|
+
*
|
|
79
|
+
* The caller (entry `apply`) arms its one-shot latch only on
|
|
80
|
+
* `ran && converged` — a rejected re-declare must never suppress the
|
|
81
|
+
* `subagent/start` decision-point retry.
|
|
82
|
+
*/
|
|
83
|
+
export interface AdvisoryPassReport {
|
|
84
|
+
ran: boolean;
|
|
85
|
+
converged: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Reset the degraded-abort warn dedup flag (one warn per apply budget).
|
|
89
|
+
* Called by the entry at `apply` (next to the advisory sink binding) and in
|
|
90
|
+
* the `llm-fallbacks` inject child's teardown (a fiber swap re-opens the
|
|
91
|
+
* budget for the re-applied fiber). Exported for the suite's dedup case.
|
|
92
|
+
*/
|
|
93
|
+
export declare function resetAdvisoryAbortWarn(): void;
|
|
94
|
+
/**
|
|
95
|
+
* One advisory pass: unmounted → not invoked (`{ ran: false, converged:
|
|
96
|
+
* false }`, no logs); mounted → report the taxonomy adoption state (bounded:
|
|
97
|
+
* ≤1 warn per category). With the service present the pass is ASYNC: it
|
|
98
|
+
* awaits the idempotent re-declare before the effective-state readback
|
|
99
|
+
* (report determinism — the boot dual-inject-child race window is closed).
|
|
100
|
+
* Never throws — every failure mode degrades to skip + one debug/warn, and
|
|
101
|
+
* an aborted pass reports `converged: false` (the honest latch). Never
|
|
102
|
+
* writes the fallbacks config.
|
|
69
103
|
*
|
|
70
104
|
* @param ctx - the plugin's registrant context (the app composition root).
|
|
71
105
|
* @param agentsDir - the `harness-agents/` mirror root the mstar role-id set
|
|
72
106
|
* is derived from; absent → the taxonomy checks are skipped (one debug
|
|
73
107
|
* log; the legacy-keys check is mirror-independent and still runs).
|
|
74
|
-
* @returns
|
|
75
|
-
*
|
|
108
|
+
* @returns the {@link AdvisoryPassReport} — `ran` marks a mounted pass (the
|
|
109
|
+
* one-pass-per-apply bookkeeping), `converged` marks a pass that reached
|
|
110
|
+
* its converged end; the caller (entry `apply`) arms the one-shot latch
|
|
111
|
+
* only on `ran && converged`, so an aborted pass (e.g. a rejected
|
|
112
|
+
* re-declare) never suppresses the decision-point retry.
|
|
76
113
|
*/
|
|
77
|
-
export declare function runFallbacksAdvisory(ctx: Context, agentsDir: string | undefined): Promise<
|
|
114
|
+
export declare function runFallbacksAdvisory(ctx: Context, agentsDir: string | undefined): Promise<AdvisoryPassReport>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Capability probes for the OPTIONAL `dsh-llm-fallbacks` plugin (plan
|
|
3
|
-
*
|
|
3
|
+
* Task 1 — probe foundation).
|
|
4
4
|
*
|
|
5
5
|
* The fallbacks plugin is an optional SEPARATE install (two-command
|
|
6
6
|
* contract) and a dev-time-only dependency of this package: src carries
|
|
@@ -55,7 +55,7 @@ export declare function fallbacksService(ctx: Context): FallbacksServiceView | u
|
|
|
55
55
|
* The fallbacks loader row when present and enabled (group rows skipped).
|
|
56
56
|
* Unlike {@link fallbacksMounted}, NO live-fiber requirement: the entry is
|
|
57
57
|
* declarative and `options.config` is set at entry creation, so the adoption
|
|
58
|
-
* advisory
|
|
58
|
+
* advisory can read the
|
|
59
59
|
* deployment's row config even during HMR/fiber-swap windows — the advisory
|
|
60
60
|
* caller gates on `fallbacksMounted` first.
|
|
61
61
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Zero-config seed declaration for the OPTIONAL `dsh-llm-fallbacks` plugin
|
|
3
|
-
*
|
|
3
|
+
* : when the `llm-fallbacks` service is
|
|
4
4
|
* applied, this module declares the 13 `mode: subagent` mstar roles into the
|
|
5
5
|
* fallbacks seed registry — persona = mirror `description` (verbatim, the
|
|
6
6
|
* SSOT stays `mstar-roles`) + one mandatory-load guide line.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local structural mirrors of the consumed `dsh-llm-fallbacks` surface
|
|
3
|
-
*
|
|
3
|
+
* . dsh natively
|
|
4
4
|
* covers subagent customization, so the fallbacks
|
|
5
5
|
* plugin is an OPTIONAL capability activated by the unchanged two-command
|
|
6
6
|
* install contract — and a dev-time-only dependency of this package (type
|
|
@@ -4,7 +4,7 @@ import type { Config, HarnessResolver } from './_shared.ts';
|
|
|
4
4
|
export declare const GOAL_BRIDGE_LOGGER = "mstar/goal-bridge";
|
|
5
5
|
/**
|
|
6
6
|
* Flat `maxGoalRounds` config fallback (architect decision — plan
|
|
7
|
-
*
|
|
7
|
+
* ): 256, aligned with the GoalService default
|
|
8
8
|
* (`goal/src/index.ts:187`) and ralph `maxRounds` (`tool-ralph/src/index.ts:37`).
|
|
9
9
|
*/
|
|
10
10
|
export declare const DEFAULT_MAX_GOAL_ROUNDS = 256;
|
|
@@ -46,8 +46,7 @@ export interface GoalView extends GoalRefView {
|
|
|
46
46
|
* index.ts:244-257`); `complete` is a CAS by `{ id, revision }`
|
|
47
47
|
* (`GOAL_STALE_REVISION` on stale). The drift path uses complete+create
|
|
48
48
|
* (never `edit`) so each new iteration gets a FRESH goal with a clean
|
|
49
|
-
* round budget
|
|
50
|
-
*/
|
|
49
|
+
* round budget. */
|
|
51
50
|
export interface GoalsServiceView {
|
|
52
51
|
get(agent: unknown): GoalView | undefined;
|
|
53
52
|
create(agent: unknown, request: {
|
|
@@ -74,8 +73,7 @@ export declare function iterationGoalObjective(iterationId: string): string;
|
|
|
74
73
|
* `status` is `active` or `locked` — the directory name IS the iteration id
|
|
75
74
|
* (plan-conventions `{ITERATION_DIR}/<id>/`). Completed/status-less/archived
|
|
76
75
|
* compasses do not steer. Silent on any read failure (advisory degrade).
|
|
77
|
-
* Shared with the planMode bridge via explicit no-barrel import (
|
|
78
|
-
* the same "is an active iteration steering" read).
|
|
76
|
+
* Shared with the planMode bridge via explicit no-barrel import (the same "is an active iteration steering" read).
|
|
79
77
|
* @param harnessDir - the resolved `{HARNESS_DIR}`.
|
|
80
78
|
*/
|
|
81
79
|
export declare function steeringCompass(harnessDir: string): {
|
|
@@ -115,13 +113,12 @@ export declare function mirrorIterationGoal(agent: unknown, input: MirrorIterati
|
|
|
115
113
|
* first root-like ancestor. `undefined` when unresolvable (fork lineage,
|
|
116
114
|
* non-in-process provider, registry gap, or a cycle) — the decision point
|
|
117
115
|
* then silently skips. Cycle guard: a `seen` set over visited session ids
|
|
118
|
-
* (the upstream `liveLineage` guard
|
|
119
|
-
* F-003) breaks on ANY revisited id — a 1-hop self-loop, a 2+ hop cycle
|
|
116
|
+
* (the upstream `liveLineage` guard) breaks on ANY revisited id — a 1-hop self-loop, a 2+ hop cycle
|
|
120
117
|
* (A→B→A), or a longer malformed lineage — instead of spinning forever on
|
|
121
118
|
* the synchronous `subagent/start` decision-point listeners (reachable via
|
|
122
119
|
* HMR remounts, resumed/forked sessions with stale headers, or a future
|
|
123
120
|
* host change). Shared with the planMode bridge via explicit no-barrel
|
|
124
|
-
* import (
|
|
121
|
+
* import (the same `subagent/start` decision-point root walk).
|
|
125
122
|
*/
|
|
126
123
|
export declare function rootAgentOf(agent: unknown, agents: AgentsView): unknown | undefined;
|
|
127
124
|
/**
|
|
@@ -131,7 +128,7 @@ export declare function rootAgentOf(agent: unknown, agents: AgentsView): unknown
|
|
|
131
128
|
* decision point — index.ts advisory slot), resolving the delegating ROOT
|
|
132
129
|
* via the `parentSession` walk — the two mirror edges are idempotent (get +
|
|
133
130
|
* compare when the mirror is in place — no churn) — plus a THIRD, advisory
|
|
134
|
-
* listener on the `session/event` firehose
|
|
131
|
+
* listener on the `session/event` firehose : a `goal/change`
|
|
135
132
|
* envelope whose goal is blocked logs ONE warn (code + objective summary +
|
|
136
133
|
* project-register residual pointer) with ZERO harness writes
|
|
137
134
|
* (the one-way mirror; see {@link warnBlockedGoal}). The goals service is an
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Native-first role-persona delivery
|
|
3
|
-
* Task 3): a role-matched subagent start merges the persona into the request's
|
|
2
|
+
* Native-first role-persona delivery : a role-matched subagent start merges the persona into the request's
|
|
4
3
|
* NATIVE `persona` slot (`@deepseek-ai/dsh-subagent`
|
|
5
4
|
* `SubagentStartRequest.persona`) — the additive `mstar:role-persona`
|
|
6
5
|
* system-prompt section is gone. Native semantics: the request persona
|
|
@@ -37,14 +36,20 @@
|
|
|
37
36
|
* parsers the dispatch gate uses (`assignmentHeaderRegion` +
|
|
38
37
|
* `parseAssignmentFields`) — over the start request's prompt text (the
|
|
39
38
|
* `ContentBlock[]` the child receives as its first user message). Persona
|
|
40
|
-
* lookup
|
|
39
|
+
* lookup is the single
|
|
41
40
|
* {@link personaFor} surface — `Config.rolePersonas[executeAs]` →
|
|
42
41
|
* `harness-agents/` mirror default → skip (never gated on `roleMap` or on
|
|
43
42
|
* the fallbacks mounted state: persona delivery is fallbacks-independent).
|
|
44
43
|
* `roleMap` is a taxonomy bridge for logging + future rule-driven interop
|
|
45
44
|
* only. The mirror root is bound at apply (`setRolePersonaAgentsDir` ←
|
|
46
45
|
* `packagedAgentsDir()`), package-relative so the shipped bundle works from
|
|
47
|
-
* any launch cwd.
|
|
46
|
+
* any launch cwd. Lifetime: the root is a module-level binding with ONE
|
|
47
|
+
* writer — the per-apply `setRolePersonaAgentsDir` call — and it is read
|
|
48
|
+
* per start, so every start observes an apply-constant value; re-calling
|
|
49
|
+
* the setter (an HMR re-apply) IS the re-bind, and that re-bind is the
|
|
50
|
+
* intended reset (it also re-arms the mirror-absent latch below). The
|
|
51
|
+
* per-apply payload `Config.rolePersonas` is the contrast: closed over per
|
|
52
|
+
* apply in `registerRolePersonaChannel`.
|
|
48
53
|
*
|
|
49
54
|
* Capability gates (native fail-loud contracts, per surface): one-shot
|
|
50
55
|
* `SubagentRuntime.start` REJECTS a request carrying `persona` for a
|
|
@@ -69,6 +74,22 @@
|
|
|
69
74
|
* per apply (S-002 latch); a throwing merge aborts the merge only — the
|
|
70
75
|
* ORIGINAL request reaches the service and the start is never affected.
|
|
71
76
|
*
|
|
77
|
+
* Seam probe (apply-time, observation only): a future cordis rename/removal
|
|
78
|
+
* of `internal/get` would stop the listener from ever firing — persona
|
|
79
|
+
* delivery would silently degrade to the raw service with no runtime
|
|
80
|
+
* signal. {@link probeRolePersonaSeam} runs ONCE per apply right after
|
|
81
|
+
* {@link registerRolePersonaChannel}: a temporary canary listener + ONE
|
|
82
|
+
* controlled proxied read (`ctx.subagents` — NEVER `ctx.get`, whose accessor
|
|
83
|
+
* bypasses the waterfall and would false-warn every healthy boot) assert
|
|
84
|
+
* that the seam dispatched AND the returned value carries the wrapper brand.
|
|
85
|
+
* A broken seam warns ONCE per apply (fail-loud); an unresolved service is
|
|
86
|
+
* `service-absent` (`ok: true` + one debug — the apply ctx does not resolve
|
|
87
|
+
* `subagents`; cordis resolves the service in dispatch scopes, where reads
|
|
88
|
+
* are intercepted per read); any probe-internal error fails
|
|
89
|
+
* OPEN (`ok` + one debug) — the probe never throws and never blocks a
|
|
90
|
+
* dispatch. The decision core is the pure {@link evaluateSeamProbe}, so the
|
|
91
|
+
* whole outcome table is unit-pinnable without cordis internals.
|
|
92
|
+
*
|
|
72
93
|
* Persona text is rendered by dsh system-prompt's STRICT `{{...}}`
|
|
73
94
|
* interpolation (the native persona has the same template semantics as the
|
|
74
95
|
* deployment persona), so persona values MUST NOT contain `{{` paired with
|
|
@@ -78,7 +99,12 @@
|
|
|
78
99
|
* boot throw).
|
|
79
100
|
*
|
|
80
101
|
* Module boundary: no barrel — the entry imports this module by explicit
|
|
81
|
-
* relative path and re-exports the public names verbatim
|
|
102
|
+
* relative path and re-exports the public names verbatim, EXCEPT the four
|
|
103
|
+
* probe exports (`PERSONA_SEAM_EVENT`, `ROLE_PERSONA_WRAPPER_BRAND`,
|
|
104
|
+
* `evaluateSeamProbe`, `probeRolePersonaSeam`), which are deliberately NOT
|
|
105
|
+
* re-exported from the entry: the frozen entry surface keeps the probe
|
|
106
|
+
* observable only through this module (tests import it directly; the
|
|
107
|
+
* shipped bundle exports no probe symbol). No dsh-subagent
|
|
82
108
|
* dependency: the runtime surface is consumed structurally (same pattern as
|
|
83
109
|
* the probe's `LoaderEntryView` and T2's `fallbacks-structural.ts`).
|
|
84
110
|
*/
|
|
@@ -86,6 +112,23 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
86
112
|
import type { Config } from './_shared.ts';
|
|
87
113
|
/** Logger label for the role-persona channel (dsh logger naming: `<scope>/<subject>`). */
|
|
88
114
|
export declare const ROLE_PERSONA_LOGGER = "mstar/role-persona";
|
|
115
|
+
/**
|
|
116
|
+
* The interception seam: the cordis service-read waterfall event the channel
|
|
117
|
+
* listener registers on. The registration and the apply-time seam probe both
|
|
118
|
+
* reference THIS constant — a future cordis rename of `internal/get` becomes
|
|
119
|
+
* a one-line, probe-family-caught edit here instead of a silent delivery
|
|
120
|
+
* stop (the probe family pins the literal; see `probeRolePersonaSeam`).
|
|
121
|
+
*/
|
|
122
|
+
export declare const PERSONA_SEAM_EVENT = "internal/get";
|
|
123
|
+
/**
|
|
124
|
+
* Wrapper brand — the non-enumerable symbol own property every persona
|
|
125
|
+
* wrapper carries (`wrapSubagentsService` stamps it at creation). The apply-
|
|
126
|
+
* time seam probe reads it to assert the wrapper was actually installed on
|
|
127
|
+
* the controlled read. Non-enumerable + symbol keeps the wrapper's
|
|
128
|
+
* key/spread/JSON surface identical to the wrapped service's (behavior-
|
|
129
|
+
* neutral by construction).
|
|
130
|
+
*/
|
|
131
|
+
export declare const ROLE_PERSONA_WRAPPER_BRAND: symbol;
|
|
89
132
|
/** One consumed prompt content block (`@deepseek-ai/dsh-llm` `ContentBlock` text members). */
|
|
90
133
|
interface PromptBlockView {
|
|
91
134
|
readonly type: string;
|
|
@@ -167,8 +210,14 @@ export type RolePersonaLogSink = (level: RolePersonaLogLevel, message: string) =
|
|
|
167
210
|
*/
|
|
168
211
|
export declare function setRolePersonaLogger(sink: RolePersonaLogSink): RolePersonaLogSink;
|
|
169
212
|
/**
|
|
170
|
-
* Bind the persona-defaults mirror root
|
|
171
|
-
*
|
|
213
|
+
* Bind the persona-defaults mirror root — the module sink's only writer,
|
|
214
|
+
* invoked once per apply from the entry with `packagedAgentsDir()`, so an
|
|
215
|
+
* HMR re-apply re-binds the root instead of inheriting the previous
|
|
216
|
+
* apply's binding. That re-bind is the intended reset: beyond swapping the
|
|
217
|
+
* root it re-arms the S-002 mirror-absent latch (`mirrorAbsentDebugged`),
|
|
218
|
+
* keeping the "no mirror" debug at most once per apply, and the returned
|
|
219
|
+
* PRIOR binding lets a caller restore the previous root (test pattern:
|
|
220
|
+
* {@link setRolePersonaLogger}).
|
|
172
221
|
* @param dir - the mirror root, or `undefined` to disable mirror defaults.
|
|
173
222
|
*/
|
|
174
223
|
export declare function setRolePersonaAgentsDir(dir: string | undefined): string | undefined;
|
|
@@ -188,4 +237,71 @@ export declare function setRolePersonaAgentsDir(dir: string | undefined): string
|
|
|
188
237
|
* only payload source; `roleMap` is never consulted for the merge).
|
|
189
238
|
*/
|
|
190
239
|
export declare function registerRolePersonaChannel(ctx: Context, config: Config): void;
|
|
240
|
+
/** Outcome of one apply-time seam probe ({@link probeRolePersonaSeam}). */
|
|
241
|
+
export interface PersonaSeamProbeResult {
|
|
242
|
+
/** `true` = the channel is healthy OR the probe failed open (never block apply). */
|
|
243
|
+
ok: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* Why the probe classified the channel the way it did. `ok: false` ALWAYS
|
|
246
|
+
* carries a reason; `service-absent` may appear with `ok: true` (the
|
|
247
|
+
* sanctioned no-warn unresolved-service classification).
|
|
248
|
+
*/
|
|
249
|
+
reason?: 'seam-absent' | 'wrap-skipped' | 'service-absent';
|
|
250
|
+
}
|
|
251
|
+
/** One probe observation — the inputs of the pure decision core. */
|
|
252
|
+
export interface SeamProbeInputs {
|
|
253
|
+
/** Whether the temporary canary listener fired during the controlled read. */
|
|
254
|
+
dispatched: boolean;
|
|
255
|
+
/** The value the controlled read threw (`undefined` = the read resolved). */
|
|
256
|
+
readError: unknown;
|
|
257
|
+
/** The controlled read's resolved value (`undefined` when the read threw). */
|
|
258
|
+
value: unknown;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Pure decision core of the seam probe — the ENTIRE outcome table, unit-
|
|
262
|
+
* pinnable without cordis internals:
|
|
263
|
+
*
|
|
264
|
+
* - canary silent → `{ ok: false, reason: 'seam-absent' }` — cordis no
|
|
265
|
+
* longer dispatches the seam; our listener can never run. Dominates the
|
|
266
|
+
* other inputs (a silent canary means the delivery channel is gone).
|
|
267
|
+
* - canary fired + read threw → `{ ok: true, reason: 'service-absent' }` —
|
|
268
|
+
* the seam works but the reading ctx does not resolve `subagents` (on the
|
|
269
|
+
* real composition the apply ctx is inject-guarded; cordis resolves the
|
|
270
|
+
* service in dispatch scopes, where reads are intercepted per read). Never
|
|
271
|
+
* a warn.
|
|
272
|
+
* - canary fired + branded value → `{ ok: true }` — healthy.
|
|
273
|
+
* - canary fired + any other resolved value (unbranded object, primitive,
|
|
274
|
+
* undefined) → `{ ok: false, reason: 'wrap-skipped' }` — the listener ran
|
|
275
|
+
* but the shape was unrecognized (the `wrapSubagentsService` pass-through).
|
|
276
|
+
*/
|
|
277
|
+
export declare function evaluateSeamProbe({ dispatched, readError, value }: SeamProbeInputs): PersonaSeamProbeResult;
|
|
278
|
+
/**
|
|
279
|
+
* Apply-time seam probe — runs EXACTLY ONCE per apply, immediately after
|
|
280
|
+
* {@link registerRolePersonaChannel} (entry wiring), and classifies the
|
|
281
|
+
* channel's install state per {@link evaluateSeamProbe} (observation only —
|
|
282
|
+
* it never changes delivery semantics):
|
|
283
|
+
*
|
|
284
|
+
* 1. register a TEMPORARY {@link PERSONA_SEAM_EVENT} canary listener
|
|
285
|
+
* (`(ctx, name, error, next) => { dispatched = true; return next() }`),
|
|
286
|
+
* keeping the disposer `ctx.on` returns;
|
|
287
|
+
* 2. perform ONE controlled proxied read `ctx.subagents` inside try/catch —
|
|
288
|
+
* the exact read path the per-call `ctx.subagents.start(...)` dispatch
|
|
289
|
+
* takes. NEVER `ctx.get('subagents')`: the accessor reads the service
|
|
290
|
+
* store directly and bypasses the waterfall, which would false-warn
|
|
291
|
+
* `seam-absent` on every healthy boot;
|
|
292
|
+
* 3. dispose the canary SYNCHRONOUSLY (`finally` — also on the throwing
|
|
293
|
+
* read path);
|
|
294
|
+
* 4. classify via {@link evaluateSeamProbe} and log: `ok === false` → ONE
|
|
295
|
+
* warn ({@link SEAM_WARN} + reason); `service-absent` → one debug; a
|
|
296
|
+
* healthy probe stays silent.
|
|
297
|
+
*
|
|
298
|
+
* Contained failure: the body is fully try/catch-wrapped — any probe-
|
|
299
|
+
* internal error (e.g. a rejected listener registration) fails OPEN with
|
|
300
|
+
* `{ ok: true }` plus ONE debug naming the error. Never throws out of
|
|
301
|
+
* `apply`; never affects a subagent start.
|
|
302
|
+
*
|
|
303
|
+
* @param ctx - the plugin's registrant context (a runtime-bearing context —
|
|
304
|
+
* proxied property reads on it dispatch the seam waterfall).
|
|
305
|
+
*/
|
|
306
|
+
export declare function probeRolePersonaSeam(ctx: Context): PersonaSeamProbeResult;
|
|
191
307
|
export {};
|
|
@@ -56,9 +56,21 @@ export declare class SkillLintVetoError extends Error {
|
|
|
56
56
|
* CLI `mstar skill lint` combination plus the ephemeral-citation gate;
|
|
57
57
|
* violation codes `lint.frontmatter.*` / `skill-authoring.five-question.*`
|
|
58
58
|
* / `skill.ephemeral.*`). Pure: no enforcement, no I/O.
|
|
59
|
+
*
|
|
60
|
+
* Five-question profile (spec A4): the shared Engine classifier
|
|
61
|
+
* (`classifySkillLint`) selects the mode from `options.skillId` — the
|
|
62
|
+
* trusted resolved skill-target basename passed by the fs-intent path and
|
|
63
|
+
* `lintSkillWrite`. A doc-only call (no `skillId`) stays strict authoring —
|
|
64
|
+
* the greenfield default is never loosened by an unparented document. The
|
|
65
|
+
* frontmatter and ephemeral-citation checks run in every profile; `core`
|
|
66
|
+
* (exact `mstar-harness-core`) skips only the five-question check.
|
|
59
67
|
* @param doc - the full SKILL.md text.
|
|
68
|
+
* @param options - `skillId`: the resolved skill-target directory basename
|
|
69
|
+
* (trusted boundary identity — never the doc's YAML `name` alone).
|
|
60
70
|
*/
|
|
61
|
-
export declare function lintSkillDoc(doc: string
|
|
71
|
+
export declare function lintSkillDoc(doc: string, options?: {
|
|
72
|
+
skillId?: string;
|
|
73
|
+
}): GateResult;
|
|
62
74
|
/**
|
|
63
75
|
* Enforce the skill-authoring lints over a KNOWN document (the brief's
|
|
64
76
|
* "incoming doc when available" branch): `Enforcement: hard` + violations →
|
|
@@ -68,8 +80,13 @@ export declare function lintSkillDoc(doc: string): GateResult;
|
|
|
68
80
|
* needed on this branch. The content-blind listener path (where the
|
|
69
81
|
* incoming doc is never visible) routes through {@link gateSkillIntent}
|
|
70
82
|
* instead, which applies the status-gate repair-escape decision.
|
|
83
|
+
*
|
|
84
|
+
* The lint profile is classified from the trusted resolved skill-target
|
|
85
|
+
* basename (spec A4): `basename(dirname(resolve(options.target)))` — the
|
|
86
|
+
* write's own target, never the document's YAML `name`.
|
|
71
87
|
* @param doc - the document about to be written (the write's content).
|
|
72
|
-
* @param options - target display path (veto message
|
|
88
|
+
* @param options - target display path (veto message + profile identity) +
|
|
89
|
+
* resolved hard flag.
|
|
73
90
|
*/
|
|
74
91
|
export declare function lintSkillWrite(doc: string, options: {
|
|
75
92
|
target: string;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Harness-rules system-prompt injection (
|
|
3
|
-
* Task 2): the root session's ONE `mstar:harness-rules` pointer section plus
|
|
4
|
-
* the `mstar:engine-status` runtime-context summary, both registered on the
|
|
5
|
-
* GLOBAL prompt layer — visible to the root session AND every dispatched
|
|
2
|
+
* Harness-rules system-prompt injection (visible to the root session AND every dispatched
|
|
6
3
|
* child — on their own names and layers (the child persona rides the NATIVE
|
|
7
4
|
* subagent persona channel since plan
|
|
8
|
-
*
|
|
5
|
+
* Task 3 — no child-scoped
|
|
9
6
|
* `mstar:role-persona` section exists anymore; duplicate-name throws remain
|
|
10
7
|
* per name per layer, verified `scope/src/store.ts`).
|
|
11
8
|
*
|
|
@@ -18,13 +15,13 @@
|
|
|
18
15
|
* interpolation and throws on unknown/malformed/undefined references
|
|
19
16
|
* (`interpolate` in `@deepseek-ai/dsh-system-prompt`), so every injected
|
|
20
17
|
* string must carry no complete group. The mechanism is LIVE, not static
|
|
21
|
-
*
|
|
18
|
+
* : every operator-controlled value embedded below
|
|
22
19
|
* (harness dir, plan ids, iteration id, lease fields, direction prose)
|
|
23
20
|
* is passed through `stripInterpolationHazard` — complete `{{…}}` groups
|
|
24
21
|
* are screened so a hostile value can never break prompt assembly, while
|
|
25
22
|
* a lone `{{` stays literal prose.
|
|
26
23
|
* - The harness dir is resolved PER ASSEMBLY from the assembly context's
|
|
27
|
-
* agent
|
|
24
|
+
* agent : the
|
|
28
25
|
* session cwd of the agent whose prompt is being assembled, via
|
|
29
26
|
* `resolver.forAgent`, with the boot value (`forWorkspace(undefined)`,
|
|
30
27
|
* the explicit config or null) as the fallback when the assembly carries
|
|
@@ -39,13 +36,12 @@
|
|
|
39
36
|
* re-registration, in zero-config and explicit-config deployments alike.
|
|
40
37
|
* - The context provider reuses the catalog's unified machine-summary
|
|
41
38
|
* source (`buildCatalogSources` — the SAME builder the engine-status
|
|
42
|
-
* pre-step catalog row uses) and projects the SLIM digest
|
|
43
|
-
* `20260820-dsh-engine-status-slim` Task 2): the version watermark
|
|
39
|
+
* pre-step catalog row uses) and projects the SLIM digest: the version watermark
|
|
44
40
|
* ALWAYS, plus ONE `workflow … | plans: …` line only when the active set
|
|
45
41
|
* selects a lifecycle (`state.selection.kind === 'active'`). Harness dir
|
|
46
42
|
* and enforcement live in `mstar:harness-rules`; residuals / leases /
|
|
47
43
|
* direction / iteration-gate detail stay exclusive to the pre-step row.
|
|
48
|
-
* v3
|
|
44
|
+
* v3 : the
|
|
49
45
|
* digest reads ONLY the catalog row (`state` — itself aggregated from the
|
|
50
46
|
* SELECTED workflow snapshot + project registers) — no direct
|
|
51
47
|
* status.json / snapshot file reads to change. The build is TTL-memoized
|
|
@@ -64,7 +60,7 @@
|
|
|
64
60
|
* - Registration is deferred through `ctx.inject(['systemPrompt'], …)`
|
|
65
61
|
* (HMR-safe re-apply): the `section()`/`context()` calls run on the
|
|
66
62
|
* inject child, and the exact disposers they return are collected on
|
|
67
|
-
* that child via `systemPromptCtx.effect`
|
|
63
|
+
* that child via `systemPromptCtx.effect` — the
|
|
68
64
|
* registrations therefore unwind with THIS plugin's apply by explicit
|
|
69
65
|
* ownership, so a re-apply disposes the old registrations before
|
|
70
66
|
* registering fresh ones (no duplicate-name throw, no stale closure from
|
package/dist/gates/tools.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { HarnessResolver } from './_shared.ts';
|
|
|
18
18
|
export declare function registerSddIterationTools(ctx: Context, resolver: HarnessResolver): void;
|
|
19
19
|
/**
|
|
20
20
|
* Register the on-demand seam validation tools (
|
|
21
|
-
*
|
|
21
|
+
* : `mstar design-md validate` / `mstar compound
|
|
22
22
|
* validate` CLI mirrors plus the audit / roles validators — thin wrappers
|
|
23
23
|
* running the engine in-app. The registrations are deferred with
|
|
24
24
|
* `ctx.inject(['tools'], …)` (same optional-unit pattern as the sdd tools),
|