@mstar-harness/dsh 3.5.1 → 3.6.0-alpha.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/README.i18n.yaml +2 -2
- package/README.md +15 -17
- package/README.zh.md +15 -17
- package/dist/client/index.d.ts +1 -1
- package/dist/client/panel/PanelView.d.ts +2 -2
- package/dist/client/panel/use-mstar-engine-status.d.ts +8 -8
- package/dist/client.js +5 -5
- package/dist/gates/_shared.d.ts +46 -14
- package/dist/gates/agent-personas.d.ts +3 -3
- package/dist/gates/fallbacks-advisory.d.ts +2 -2
- package/dist/gates/fallbacks-probe.d.ts +12 -6
- package/dist/gates/fallbacks-seeds.d.ts +12 -10
- package/dist/gates/fallbacks-structural.d.ts +101 -0
- package/dist/gates/goal-bridge.d.ts +1 -1
- package/dist/gates/role-persona.d.ts +191 -0
- package/dist/gates/system-prompt.d.ts +7 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +136 -111
- package/harness-skills/mstar-artifacts/references/status-and-residuals.md +25 -13
- package/harness-skills/mstar-coding-behavior/SKILL.md +2 -0
- package/harness-skills/mstar-harness-core/SKILL.md +13 -1
- package/harness-skills/mstar-iteration/SKILL.md +1 -1
- package/harness-skills/mstar-iteration/references/phase-3-iteration-close.md +12 -2
- package/package.json +20 -20
- package/dist/gates/fallbacks-decoration.d.ts +0 -108
package/dist/index.js
CHANGED
|
@@ -4036,6 +4036,13 @@ function formatViolation(violation14) {
|
|
|
4036
4036
|
function asRecord(value) {
|
|
4037
4037
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
4038
4038
|
}
|
|
4039
|
+
var CATALOG_STATE_JOIN_LIMIT = 8;
|
|
4040
|
+
function joinCapped(items, cap, separator, render) {
|
|
4041
|
+
const visible = items.slice(0, cap).map(render);
|
|
4042
|
+
if (items.length > cap)
|
|
4043
|
+
visible.push(`+${items.length - cap} more`);
|
|
4044
|
+
return visible.join(separator);
|
|
4045
|
+
}
|
|
4039
4046
|
function resolveSeamHard(harnessDir, config) {
|
|
4040
4047
|
if (config.enforcement === "hard")
|
|
4041
4048
|
return true;
|
|
@@ -5491,7 +5498,7 @@ function renderEngineStatusCatalog(source) {
|
|
|
5491
5498
|
if (state.selection.kind === "active" && state.selection.warning !== undefined) {
|
|
5492
5499
|
lines.push(`workflow warning: ${state.selection.warning.code} ${state.selection.warning.message}`);
|
|
5493
5500
|
}
|
|
5494
|
-
lines.push(`plans: ${state.plans.length === 0 ? "none registered" : state.plans
|
|
5501
|
+
lines.push(`plans: ${state.plans.length === 0 ? "none registered" : joinCapped(state.plans, CATALOG_STATE_JOIN_LIMIT, " ", (p) => `${p.id}(${p.status})`)}`);
|
|
5495
5502
|
lines.push(`residuals: ${state.residuals.length === 0 ? "none open" : state.residuals.map((r) => `${r.severity} ${r.count}`).join(", ")}`);
|
|
5496
5503
|
if (state.iterationBaseBranch !== null && state.targetBranch !== null) {
|
|
5497
5504
|
const integration = state.specIntegrationBranch !== null ? ` (spec integration: ${state.specIntegrationBranch})` : "";
|
|
@@ -5504,7 +5511,7 @@ function renderEngineStatusCatalog(source) {
|
|
|
5504
5511
|
].filter((part) => part !== null).join("; ");
|
|
5505
5512
|
if (policy !== "")
|
|
5506
5513
|
lines.push(`policy: ${policy}`);
|
|
5507
|
-
lines.push(`leases: ${state.leases.length === 0 ? "none active" : state.leases
|
|
5514
|
+
lines.push(`leases: ${state.leases.length === 0 ? "none active" : joinCapped(state.leases, CATALOG_STATE_JOIN_LIMIT, "; ", (l) => `${l.planId} → ${l.holder}${l.worktreePath !== null ? ` (${l.worktreePath})` : ""}`)}`);
|
|
5508
5515
|
if (state.knowledge !== null) {
|
|
5509
5516
|
lines.push(`knowledge: ${state.knowledge.docCount} doc${state.knowledge.docCount === 1 ? "" : "s"} (${state.knowledge.categories.join(", ")})`);
|
|
5510
5517
|
}
|
|
@@ -7206,112 +7213,111 @@ function unquote(value) {
|
|
|
7206
7213
|
return value.length >= 2 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
|
|
7207
7214
|
}
|
|
7208
7215
|
|
|
7209
|
-
// src/gates/
|
|
7210
|
-
var
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
if (loader === undefined)
|
|
7217
|
-
return;
|
|
7218
|
-
for (const entry of loader.entries()) {
|
|
7219
|
-
if (entry.options.name !== FALLBACKS_ENTRY_NAME)
|
|
7220
|
-
continue;
|
|
7221
|
-
if (entry.options.group)
|
|
7222
|
-
continue;
|
|
7223
|
-
if (entry.disabled)
|
|
7224
|
-
continue;
|
|
7225
|
-
return entry;
|
|
7226
|
-
}
|
|
7227
|
-
return;
|
|
7228
|
-
}
|
|
7229
|
-
function fallbacksMounted(ctx) {
|
|
7230
|
-
if (fallbacksService(ctx) !== undefined)
|
|
7231
|
-
return true;
|
|
7232
|
-
const entry = fallbacksEntry(ctx);
|
|
7233
|
-
if (entry === undefined)
|
|
7234
|
-
return false;
|
|
7235
|
-
return entry.fiber !== undefined;
|
|
7236
|
-
}
|
|
7237
|
-
|
|
7238
|
-
// src/gates/fallbacks-decoration.ts
|
|
7239
|
-
var DECORATION_LOGGER = "mstar/subagent-decoration";
|
|
7240
|
-
var PERSONA_SECTION_NAME = "mstar:role-persona";
|
|
7241
|
-
var PERSONA_SECTION_ORDER = 1;
|
|
7242
|
-
var decorationLogSink = () => {};
|
|
7243
|
-
function setDecorationLogger(sink) {
|
|
7244
|
-
const prior = decorationLogSink;
|
|
7245
|
-
decorationLogSink = sink;
|
|
7216
|
+
// src/gates/role-persona.ts
|
|
7217
|
+
var ROLE_PERSONA_LOGGER = "mstar/role-persona";
|
|
7218
|
+
var SUBAGENTS_SERVICE = "subagents";
|
|
7219
|
+
var rolePersonaLogSink = () => {};
|
|
7220
|
+
function setRolePersonaLogger(sink) {
|
|
7221
|
+
const prior = rolePersonaLogSink;
|
|
7222
|
+
rolePersonaLogSink = sink;
|
|
7246
7223
|
return prior;
|
|
7247
7224
|
}
|
|
7248
|
-
var
|
|
7225
|
+
var rolePersonaAgentsDir;
|
|
7249
7226
|
var mirrorAbsentDebugged = false;
|
|
7250
|
-
function
|
|
7251
|
-
const prior =
|
|
7252
|
-
|
|
7227
|
+
function setRolePersonaAgentsDir(dir) {
|
|
7228
|
+
const prior = rolePersonaAgentsDir;
|
|
7229
|
+
rolePersonaAgentsDir = dir;
|
|
7253
7230
|
mirrorAbsentDebugged = false;
|
|
7254
7231
|
return prior;
|
|
7255
7232
|
}
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
const
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7233
|
+
var wrapperCache = new WeakMap;
|
|
7234
|
+
function registerRolePersonaChannel(ctx, config) {
|
|
7235
|
+
const rolePersonas = config.rolePersonas;
|
|
7236
|
+
ctx.on("internal/get", (_readCtx, name, _error, next) => {
|
|
7237
|
+
const value = next();
|
|
7238
|
+
if (name !== SUBAGENTS_SERVICE)
|
|
7239
|
+
return value;
|
|
7240
|
+
try {
|
|
7241
|
+
return wrapSubagentsService(value, rolePersonas);
|
|
7242
|
+
} catch (error) {
|
|
7243
|
+
log2("warn", `role persona channel degraded to pass-through (subagent starts unaffected): ${errorMessage2(error)}`);
|
|
7244
|
+
return value;
|
|
7245
|
+
}
|
|
7246
|
+
});
|
|
7266
7247
|
}
|
|
7267
|
-
function
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7248
|
+
function wrapSubagentsService(value, rolePersonas) {
|
|
7249
|
+
if (typeof value !== "object" || value === null)
|
|
7250
|
+
return value;
|
|
7251
|
+
const service = value;
|
|
7252
|
+
if (typeof service.start !== "function" || typeof service.getProvider !== "function")
|
|
7253
|
+
return value;
|
|
7254
|
+
const cached = wrapperCache.get(value);
|
|
7255
|
+
if (cached !== undefined && cached.rolePersonas === rolePersonas)
|
|
7256
|
+
return cached.wrapper;
|
|
7257
|
+
const wrapper = Object.create(value);
|
|
7258
|
+
wrapper.start = (name, request) => {
|
|
7259
|
+
let merged = request;
|
|
7260
|
+
try {
|
|
7261
|
+
merged = withRolePersona(service, name, request, rolePersonas, "one-shot");
|
|
7262
|
+
} catch (error) {
|
|
7263
|
+
log2("warn", `role persona merge degraded to pass-through (subagent start unaffected): ${errorMessage2(error)}`);
|
|
7277
7264
|
}
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
if (agentsDir === undefined && !mirrorAbsentDebugged) {
|
|
7290
|
-
mirrorAbsentDebugged = true;
|
|
7291
|
-
log2("debug", "harness-agents mirror absent — mstar:role-persona skipped (config-only lookups; mirror defaults unavailable)");
|
|
7265
|
+
return service.start(name, merged);
|
|
7266
|
+
};
|
|
7267
|
+
if (typeof service.startContinuable === "function") {
|
|
7268
|
+
wrapper.startContinuable = (spec) => {
|
|
7269
|
+
let merged = spec;
|
|
7270
|
+
try {
|
|
7271
|
+
const mergedRequest = withRolePersona(service, spec.provider, spec.request, rolePersonas, "continuable");
|
|
7272
|
+
if (mergedRequest !== spec.request)
|
|
7273
|
+
merged = { ...spec, request: mergedRequest };
|
|
7274
|
+
} catch (error) {
|
|
7275
|
+
log2("warn", `role persona merge degraded to pass-through (continuable subagent start unaffected): ${errorMessage2(error)}`);
|
|
7292
7276
|
}
|
|
7293
|
-
return;
|
|
7294
|
-
}
|
|
7295
|
-
child.ctx.systemPrompt.section({
|
|
7296
|
-
name: PERSONA_SECTION_NAME,
|
|
7297
|
-
order: PERSONA_SECTION_ORDER,
|
|
7298
|
-
text: persona.text
|
|
7299
|
-
});
|
|
7300
|
-
if (fallbacksMounted(ctx)) {
|
|
7301
|
-
log2("info", `dsh-llm-fallbacks mounted (v${fallbacksService(ctx)?.version ?? "unknown"}) — mstar:role-persona injected for role '${executeAs}'`);
|
|
7302
|
-
} else {
|
|
7303
|
-
log2("debug", `dsh-llm-fallbacks unmounted — mstar:role-persona injected from ${persona.source === "config" ? "mstar Config" : "harness-agents default"} for role '${executeAs}' (decoration channel unchanged)`);
|
|
7304
|
-
}
|
|
7305
|
-
} catch (error) {
|
|
7306
|
-
log2("warn", `mstar:role-persona decoration aborted (degraded — subagent dispatch unaffected): ${errorMessage2(error)}`);
|
|
7277
|
+
return service.startContinuable(merged);
|
|
7278
|
+
};
|
|
7307
7279
|
}
|
|
7280
|
+
wrapperCache.set(value, { rolePersonas, wrapper });
|
|
7281
|
+
return wrapper;
|
|
7282
|
+
}
|
|
7283
|
+
function withRolePersona(service, providerName, request, rolePersonas, surface) {
|
|
7284
|
+
if (request.persona !== undefined)
|
|
7285
|
+
return request;
|
|
7286
|
+
const personas = rolePersonas;
|
|
7287
|
+
const agentsDir = rolePersonaAgentsDir;
|
|
7288
|
+
if ((personas == null || Object.keys(personas).length === 0) && agentsDir === undefined)
|
|
7289
|
+
return request;
|
|
7290
|
+
const taskPrompt = (request.prompt ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join(`
|
|
7291
|
+
`);
|
|
7292
|
+
if (taskPrompt.trim().length === 0)
|
|
7293
|
+
return request;
|
|
7294
|
+
const executeAs = parseAssignmentFields(assignmentHeaderRegion(taskPrompt)).executeAs;
|
|
7295
|
+
if (executeAs === undefined)
|
|
7296
|
+
return request;
|
|
7297
|
+
const persona = personaFor(executeAs, { rolePersonas: personas, agentsDir }, (message) => log2("warn", message));
|
|
7298
|
+
if (persona === undefined) {
|
|
7299
|
+
if (agentsDir === undefined && !mirrorAbsentDebugged) {
|
|
7300
|
+
mirrorAbsentDebugged = true;
|
|
7301
|
+
log2("debug", "harness-agents mirror absent — role persona skipped (config-only lookups; mirror defaults unavailable)");
|
|
7302
|
+
}
|
|
7303
|
+
return request;
|
|
7304
|
+
}
|
|
7305
|
+
const provider = service.getProvider(providerName);
|
|
7306
|
+
if (provider === undefined)
|
|
7307
|
+
return request;
|
|
7308
|
+
if (surface === "one-shot" ? provider.capabilities?.persona !== true : typeof provider.prepareContinuable !== "function") {
|
|
7309
|
+
log2("debug", surface === "one-shot" ? `subagent provider '${providerName}' lacks the persona capability — role persona for '${executeAs}' skipped (start proceeds unchanged)` : `subagent provider '${providerName}' does not support continuable children — role persona for '${executeAs}' skipped (the native continuable start fails loud its own way)`);
|
|
7310
|
+
return request;
|
|
7311
|
+
}
|
|
7312
|
+
log2("debug", `role persona delivered via the native subagent persona channel for role '${executeAs}' (${surface} start, source: ${persona.source === "config" ? "mstar Config" : "harness-agents default"})`);
|
|
7313
|
+
return { ...request, persona: persona.text };
|
|
7308
7314
|
}
|
|
7309
7315
|
function errorMessage2(error) {
|
|
7310
7316
|
return error instanceof Error ? error.message : String(error);
|
|
7311
7317
|
}
|
|
7312
7318
|
function log2(level, message) {
|
|
7313
7319
|
try {
|
|
7314
|
-
|
|
7320
|
+
rolePersonaLogSink(level, message);
|
|
7315
7321
|
} catch {}
|
|
7316
7322
|
}
|
|
7317
7323
|
|
|
@@ -7992,6 +7998,35 @@ ${mstarLoadLine(roleId)}` });
|
|
|
7992
7998
|
return { declared, skipped, preserved, outcome };
|
|
7993
7999
|
}
|
|
7994
8000
|
|
|
8001
|
+
// src/gates/fallbacks-probe.ts
|
|
8002
|
+
var FALLBACKS_ENTRY_NAME = "dsh-llm-fallbacks";
|
|
8003
|
+
function fallbacksService(ctx) {
|
|
8004
|
+
return ctx.get("llm-fallbacks");
|
|
8005
|
+
}
|
|
8006
|
+
function fallbacksEntry(ctx) {
|
|
8007
|
+
const loader = ctx.get("loader");
|
|
8008
|
+
if (loader === undefined)
|
|
8009
|
+
return;
|
|
8010
|
+
for (const entry of loader.entries()) {
|
|
8011
|
+
if (entry.options.name !== FALLBACKS_ENTRY_NAME)
|
|
8012
|
+
continue;
|
|
8013
|
+
if (entry.options.group)
|
|
8014
|
+
continue;
|
|
8015
|
+
if (entry.disabled)
|
|
8016
|
+
continue;
|
|
8017
|
+
return entry;
|
|
8018
|
+
}
|
|
8019
|
+
return;
|
|
8020
|
+
}
|
|
8021
|
+
function fallbacksMounted(ctx) {
|
|
8022
|
+
if (fallbacksService(ctx) !== undefined)
|
|
8023
|
+
return true;
|
|
8024
|
+
const entry = fallbacksEntry(ctx);
|
|
8025
|
+
if (entry === undefined)
|
|
8026
|
+
return false;
|
|
8027
|
+
return entry.fiber !== undefined;
|
|
8028
|
+
}
|
|
8029
|
+
|
|
7995
8030
|
// src/gates/fallbacks-advisory.ts
|
|
7996
8031
|
var ADVISORY_LOGGER = "mstar/fallbacks-advisory";
|
|
7997
8032
|
var advisoryLogSink = () => {};
|
|
@@ -8276,12 +8311,6 @@ function engineStatusProvider(ctx, resolver, bootHarnessDir) {
|
|
|
8276
8311
|
};
|
|
8277
8312
|
}
|
|
8278
8313
|
var DIGEST_PLAN_CAP = 8;
|
|
8279
|
-
function joinCapped(items, cap, separator, render) {
|
|
8280
|
-
const visible = items.slice(0, cap).map(render);
|
|
8281
|
-
if (items.length > cap)
|
|
8282
|
-
visible.push(`+${items.length - cap} more`);
|
|
8283
|
-
return visible.join(separator);
|
|
8284
|
-
}
|
|
8285
8314
|
function engineStatusSummary(source) {
|
|
8286
8315
|
const lines = [`mstar engine status: v${source.version}`];
|
|
8287
8316
|
const state = source.state;
|
|
@@ -8404,16 +8433,14 @@ function apply(ctx, config) {
|
|
|
8404
8433
|
else
|
|
8405
8434
|
logger.info(message);
|
|
8406
8435
|
});
|
|
8407
|
-
|
|
8408
|
-
const logger = ctx.logger(
|
|
8436
|
+
setRolePersonaLogger((level, message) => {
|
|
8437
|
+
const logger = ctx.logger(ROLE_PERSONA_LOGGER);
|
|
8409
8438
|
if (level === "debug")
|
|
8410
8439
|
logger.debug(message);
|
|
8411
|
-
else if (level === "info")
|
|
8412
|
-
logger.info(message);
|
|
8413
8440
|
else
|
|
8414
8441
|
logger.warn(message);
|
|
8415
8442
|
});
|
|
8416
|
-
|
|
8443
|
+
setRolePersonaAgentsDir(packagedAgentsDir());
|
|
8417
8444
|
setHarnessPromptLogger((level, message) => {
|
|
8418
8445
|
const logger = ctx.logger(HARNESS_PROMPT_LOGGER);
|
|
8419
8446
|
if (level === "debug")
|
|
@@ -8526,9 +8553,9 @@ function apply(ctx, config) {
|
|
|
8526
8553
|
ctx.on("fs/write-intent", (target, actor, next) => seamWriteIntentListener(ctx, resolver, config, seam, target, actor, next), { prepend: true });
|
|
8527
8554
|
}
|
|
8528
8555
|
ctx.on("tools/pre-execute", (exec, next) => preExecuteListener(ctx, resolver, config, adapter, exec, next), { prepend: true });
|
|
8529
|
-
ctx
|
|
8556
|
+
registerRolePersonaChannel(ctx, config);
|
|
8557
|
+
ctx.events.on("subagent/start", () => {
|
|
8530
8558
|
runAdvisoryPass();
|
|
8531
|
-
decorateSubagentStart(ctx, config, info);
|
|
8532
8559
|
});
|
|
8533
8560
|
const ttlMs = config.catalogTtlMs ?? DEFAULT_CATALOG_TTL_MS;
|
|
8534
8561
|
const explicitKey = bootHarnessDir !== null ? EXPLICIT_CACHE_KEY : undefined;
|
|
@@ -8547,10 +8574,11 @@ function apply(ctx, config) {
|
|
|
8547
8574
|
}
|
|
8548
8575
|
export {
|
|
8549
8576
|
skillLocalConfig,
|
|
8550
|
-
|
|
8551
|
-
|
|
8577
|
+
setRolePersonaLogger,
|
|
8578
|
+
setRolePersonaAgentsDir,
|
|
8552
8579
|
setAdvisoryLogger,
|
|
8553
8580
|
runFallbacksAdvisory,
|
|
8581
|
+
registerRolePersonaChannel,
|
|
8554
8582
|
recordWorkflowVerdict,
|
|
8555
8583
|
recordSettle,
|
|
8556
8584
|
recordDispatch,
|
|
@@ -8564,17 +8592,14 @@ export {
|
|
|
8564
8592
|
lintCompoundWrite,
|
|
8565
8593
|
lintAuditWrite,
|
|
8566
8594
|
inject,
|
|
8567
|
-
decorateSubagentStart,
|
|
8568
8595
|
apply,
|
|
8569
8596
|
SkillLintVetoError,
|
|
8570
8597
|
SeamVetoError,
|
|
8571
8598
|
SETTLE_SEAM,
|
|
8572
|
-
|
|
8573
|
-
PERSONA_SECTION_NAME,
|
|
8599
|
+
ROLE_PERSONA_LOGGER,
|
|
8574
8600
|
HarnessResolver,
|
|
8575
8601
|
DshMstar,
|
|
8576
8602
|
DshHostAdapter,
|
|
8577
|
-
DECORATION_LOGGER,
|
|
8578
8603
|
Config,
|
|
8579
8604
|
AGENT_FLOW_MAX_EVENTS,
|
|
8580
8605
|
AGENT_FLOW_FILE,
|
|
@@ -43,29 +43,33 @@ Canonical vs legacy residual definitions → **`mstar-artifacts` SKILL.md**("`
|
|
|
43
43
|
```json
|
|
44
44
|
{
|
|
45
45
|
"schema_version": 1,
|
|
46
|
-
"id": "
|
|
47
|
-
"type": "
|
|
48
|
-
"status": "running
|
|
49
|
-
"started_at": "
|
|
50
|
-
"
|
|
51
|
-
"updated_at": "YYYY-MM-DD",
|
|
46
|
+
"id": "iter-demo",
|
|
47
|
+
"type": "iteration",
|
|
48
|
+
"status": "running",
|
|
49
|
+
"started_at": "2026-08-30",
|
|
50
|
+
"updated_at": "2026-08-30",
|
|
52
51
|
"phase": "phase-2-execute",
|
|
53
52
|
"plans": [
|
|
54
53
|
{
|
|
55
54
|
"id": "plan-id",
|
|
56
55
|
"title": "Plan title",
|
|
57
56
|
"file": "{PLAN_DIR}/plan-id-feature-name.md",
|
|
58
|
-
"status": "
|
|
57
|
+
"status": "InProgress",
|
|
59
58
|
"owner": "@project-manager",
|
|
60
59
|
"agents": ["@fullstack-dev"],
|
|
61
60
|
"progress": 0,
|
|
62
61
|
"tags": [],
|
|
63
|
-
"created_at": "
|
|
64
|
-
"updated_at": "
|
|
62
|
+
"created_at": "2026-08-29",
|
|
63
|
+
"updated_at": "2026-08-30",
|
|
65
64
|
"done_at": null,
|
|
66
65
|
"notes": [],
|
|
67
66
|
"metadata": {},
|
|
68
|
-
"execution_lease": {
|
|
67
|
+
"execution_lease": {
|
|
68
|
+
"holder": "omp:demo-session",
|
|
69
|
+
"claimed_at": "2026-08-30T02:30:00Z",
|
|
70
|
+
"worktree_path": "/tmp/worktrees/demo-plan",
|
|
71
|
+
"working_branch": "feature/demo-plan"
|
|
72
|
+
}
|
|
69
73
|
}
|
|
70
74
|
],
|
|
71
75
|
"execution_policy": {
|
|
@@ -73,14 +77,22 @@ Canonical vs legacy residual definitions → **`mstar-artifacts` SKILL.md**("`
|
|
|
73
77
|
"worktree_mode": "",
|
|
74
78
|
"push_policy": ""
|
|
75
79
|
},
|
|
76
|
-
"integration_merge_lease": {
|
|
77
|
-
|
|
80
|
+
"integration_merge_lease": {
|
|
81
|
+
"holder": "omp:demo-session",
|
|
82
|
+
"claimed_at": "2026-08-30T03:00:00Z",
|
|
83
|
+
"plan_id": "plan-id",
|
|
84
|
+
"source_branch": "feature/demo-plan",
|
|
85
|
+
"target_branch": "iteration/iter-demo"
|
|
86
|
+
},
|
|
87
|
+
"branch": { "base": "main", "integration": "iteration/iter-demo", "target": "main" },
|
|
78
88
|
"control_worktree_path": "/abs/repo/root",
|
|
79
89
|
"legacy_metadata": {},
|
|
80
|
-
"compass_ref": "iterations
|
|
90
|
+
"compass_ref": "iterations/iter-demo/delivery-compass.md"
|
|
81
91
|
}
|
|
82
92
|
```
|
|
83
93
|
|
|
94
|
+
- The example above depicts the **held** state (both leases populated, illustrative placeholder values) and passes `validateWorkflowSnapshot`; the released state is **key absence** (delete-key-on-release below), never `null` or `{}`, and enum scalars (`type` / `status` / plan-row `status`) are always single values — the full enum sets are `type`: `plan | iteration`, snapshot `status`: `running | paused | completed | failed | stopped`, plan-row `status`: `Todo | InProgress | InReview | Blocked | Done`.
|
|
95
|
+
|
|
84
96
|
- `plans[]` rows are the **legacy PlanRow shape verbatim** (unknown row fields preserved, never re-bucketed). Per-row `execution_lease` stays on the row; `integration_merge_lease` is **top-level** (the v1 root-`metadata` home is gone).
|
|
85
97
|
- Terminal statuses (`completed` / `failed` / `stopped`) require `ended_at` and no dangling leases.
|
|
86
98
|
- `execution_policy` keys are copied from v1 root `metadata` at migrate; values are accepted-but-opaque this iteration (no semantic gate).
|
|
@@ -31,6 +31,8 @@ The failure mode: "correct" code that is alien to the codebase — works but loo
|
|
|
31
31
|
|
|
32
32
|
## 2) Simplicity First
|
|
33
33
|
|
|
34
|
+
**Upstream invariants**: the global engineering rules live in `mstar-harness-core`(核心研发守则)——no backward-compat layers, simplest implementation, layered growth, modularity, dependency discipline, long-term architecture; this section is their implementation-level playbook.
|
|
35
|
+
|
|
34
36
|
Implement the smallest durable slice that satisfies the request and acceptance criteria.
|
|
35
37
|
|
|
36
38
|
**The Ladder.** A reflex hierarchy for every decision — stop at the first rung that holds:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mstar-harness-core
|
|
3
|
-
description: Morning Star (启明星) harness **强制全局入口** —— 信息源优先级、最小交付循环、状态机与 Done 权限、Task category 路由(含 quick 禁豁免)、@explore
|
|
3
|
+
description: Morning Star (启明星) harness **强制全局入口** —— 信息源优先级、最小交付循环、状态机与 Done 权限、Task category 路由(含 quick 禁豁免)、@explore 边界、长任务纪律、核心研发守则、护栏不变量、反模式索引、Morning Star Skill 索引与宿主入口。**任何**非平凡任务开始前必须先 Read 本 skill;再按角色与任务 **按需** Read 其它 `mstar-*` 专题(勿默认通读全部)。`@project-manager` 开轮必读 + `mstar-dispatch-gates` / `mstar-phase-gates` / `mstar-conventions` 等;实现/审查/QA 必读本 skill + `mstar-coding-behavior` 及角色清单(见 `mstar-roles`)。Prepare/派发/Git/residual/QC 细则在专题 skill,不在此重复。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Morning Star Harness Core(启明星核心)
|
|
@@ -121,6 +121,18 @@ Read **`mstar-host`** after this skill; detect host per its table, then Read the
|
|
|
121
121
|
| Kimi | `Agent`/`AgentSwarm`(仅 `coder`/`explore`/`plan`);角色绑定在 prompt(C5b);Plan 双写 → `references/kimi.md` · `kimi-plan-mode-bridge.md` |
|
|
122
122
|
| 其它 | 同 `mstar-host` skill;按工具信号选 reference |
|
|
123
123
|
|
|
124
|
+
## 核心研发守则
|
|
125
|
+
|
|
126
|
+
全局工程不变量,适用于所有角色;实现级操作细节(The Ladder、surgical、debugging 等)→ **`mstar-coding-behavior`**。
|
|
127
|
+
|
|
128
|
+
- Do not preserve backward compatibility. Remove obsolete paths instead of adding compatibility layers, fallbacks, or migrations.
|
|
129
|
+
- Choose the simplest implementation that fully meets the current requirements. Avoid speculative abstractions, configuration, and indirection.
|
|
130
|
+
- Grow the system in layers. Start from the smallest version that works end to end, and add each new capability on top of a product that already works. Never trade a working product for unfinished complexity.
|
|
131
|
+
- Keep components modular and concerns clearly separated.
|
|
132
|
+
- Prefer established, well-maintained libraries when they reduce overall complexity or improve reliability. Do not reimplement common functionality without a clear reason.
|
|
133
|
+
- Lean on the dependencies already in the project before writing your own implementation or adding packages. Do not assume a library lacks a capability without checking its documentation and types.
|
|
134
|
+
- Make architectural decisions for the long term. Do not accept a stopgap that only works for now and is meant to be replaced later.
|
|
135
|
+
|
|
124
136
|
## 护栏(不变量)
|
|
125
137
|
|
|
126
138
|
- 未经用户同意不改宿主配置文件与用户凭据。
|
|
@@ -45,7 +45,7 @@ Phase 5: PR merge-ready loop —— 至 mergeable + CI 全绿 + reviews resolved
|
|
|
45
45
|
| **→ 迭代交付完成** | §5.5 exit checklist 全 `[x]` | PR mergeable;required CI 全绿;reviews resolved | Phase 4 开 PR 即宣称完成 |
|
|
46
46
|
| **start → integration branch** | §1.6 Review & Edit chain | 三角色按序 invoke;**specs** 为主产出;**禁止** start 链向 `{KNOWLEDGE_DIR}/` 新增;writing-specialist corpus hygiene + compass `status: locked` | PM 代做专业编辑;并行三角色;product/architect 写 knowledge;临时笔记进 specs |
|
|
47
47
|
|
|
48
|
-
> **Engine check (when available):** run `mstar iteration gate --workflow <id> --compass <delivery-compass.md>` (or `import { evaluatePhaseGate } from "@mstar-harness/engine"` in a host hook) to evaluate the transition gate above against the workflow snapshot. On `fail` (gate-blocking violations) -> do not proceed; fix and re-run. Note: during the Phase-3 window (`transition: phase-3-close`) the gate exits 1 until the §3.4 close items (`status: completed` + `end_date`) are written — that exit-1 is the expected "close work pending" signal (the exit checklist gates Phase 4, not the Phase-3 entry), so proceed with Phase 3 per the table below. Skill text below remains authoritative when the runtime is absent.
|
|
48
|
+
> **Engine check (when available):** run `mstar iteration gate --workflow <id> --compass <delivery-compass.md> --branch "$(git branch --show-current)" --integration <spec_integration_branch> --target <target_branch>` (or `import { evaluatePhaseGate } from "@mstar-harness/engine"` with the `currentBranch` / `specIntegrationBranch` / `prBaseBranch` probe inputs in a host hook) to evaluate the transition gate above against the workflow snapshot — the branch probes cover §3.5 exit item 5 (`EXIT_BRANCH_MISMATCH` when the commit checkout is not on `spec_integration_branch`; verify **before** the §3.5 close commit, not after). On `fail` (gate-blocking violations) -> do not proceed; fix and re-run. Note: during the Phase-3 window (`transition: phase-3-close`) the gate exits 1 until the §3.4 close items (`status: completed` + `end_date`) are written — that exit-1 is the expected "close work pending" signal (the exit checklist gates Phase 4, not the Phase-3 entry), so proceed with Phase 3 per the table below. Skill text below remains authoritative when the runtime is absent.
|
|
49
49
|
|
|
50
50
|
**误判信号**:对话里出现 compound 摘要、roadmap 更新、或「所有 plan 已完成」但 **未** 打印 §3.1 / §3.5 checklist → 视为 **Phase 3 未执行**,回到 §3.0。
|
|
51
51
|
|
|
@@ -80,14 +80,24 @@ PM 打印 **iteration-close exit checklist**;全部为 `[x]` 后方可 `git co
|
|
|
80
80
|
- [ ] 当前分支是 `spec_integration_branch`
|
|
81
81
|
- [ ] PR base = snapshot `branch.target`(`target_branch`,与 compass frontmatter 一致);**不是**未记录的 `main`
|
|
82
82
|
|
|
83
|
-
**Commit
|
|
83
|
+
**Commit 前提(HARD — branch-anchored,防递交到控制分支)**:§3.5 的 commit 是 **branch 锚定**的——`git commit` 落在**当前检出分支**,`<spec_integration_branch>` 只出现在 push 参数里。当控制 worktree(或任一检出)不在 integration 分支时,未经下述核对直接执行本配方,compound 会把 tracked 的 `{KNOWLEDGE_DIR}/`、`{SPECS_DIR}/`、`CONCEPTS.md` 递交到控制分支(如 `main`),integration 分支的 PR 永远带不上这些 shared 产物。因此 **任何 `git add` 之前**必须先验分支;mismatch → **STOP**(不得 commit、不得 push、不得「先提交后挪」),改在正确检出上重做(见下)。
|
|
84
|
+
|
|
85
|
+
1. 解析 `<spec_integration_branch>`:snapshot `branch.integration`(workflows/<id>/snapshot.json)→ 缺失时 compass frontmatter `spec_integration_branch`;仍缺 → STOP 补齐,不得默认 `main`。
|
|
86
|
+
2. **先验后提交**(在执行 commit 的检出处):`git branch --show-current` === `<spec_integration_branch>`。§3.2–§3.4 产生的 tracked close 产物本就应处于未提交状态等待本 commit,**不要求**此处工作树干净。engine 可用 → 在 add/commit **前**运行 `mstar iteration gate --workflow <id> --compass <delivery-compass.md> --branch <current> --integration <spec_integration_branch> --target <target_branch>` 并确认 exit 无 `EXIT_BRANCH_MISMATCH` / `EXIT_PR_BASE_MISMATCH`(Phase-3 窗口预期的其它 exit-1 除外,见 Phase transition gates 注)。
|
|
87
|
+
3. **mismatch 时**:不产生任何提交。tracked 子树(`{KNOWLEDGE_DIR}/`、`{SPECS_DIR}/`、`CONCEPTS.md`、迭代 package 中 tracked 部分)在**检出 `<spec_integration_branch>` 的 worktree** 重新写入或在 commit 前恢复(它们默认 tracked、随 Git 分支走;进程产物 plans/iterations/status/sdd 经 control 绝对路径不受影响)。然后重跑本 checklist。
|
|
88
|
+
|
|
89
|
+
**在 `<spec_integration_branch>` 检出上执行**:
|
|
84
90
|
|
|
85
91
|
```bash
|
|
86
|
-
git
|
|
92
|
+
git branch --show-current # must print <spec_integration_branch> — mismatch → STOP, see above
|
|
93
|
+
git add {ITERATION_DIR}/<id>/ {ITERATION_DIR}/README.md {KNOWLEDGE_DIR}/ {SPECS_DIR}/ CONCEPTS.md
|
|
94
|
+
git add STRATEGY.md # only if updated in §3.3 (tracked root file); skip line otherwise
|
|
87
95
|
git commit -m "chore(iteration): close <iteration-id> — compound round, roadmap update"
|
|
88
96
|
git push origin <spec_integration_branch>
|
|
89
97
|
```
|
|
90
98
|
|
|
99
|
+
Staging 说明:`{SPECS_DIR}` 为解析后的实际 specs 目录(候选链见 `mstar-conventions`,如 `{HARNESS_DIR}/specs/`、`docs/specs/`、`specs/`);本轮更新过才加入。§3.3 更新过的 tracked 项目层 roadmap tracker 若为 tracked 文件,一并 stage(gitignored 的 process 产物不进 commit)。
|
|
100
|
+
|
|
91
101
|
PR 目标使用 snapshot `branch.target`;缺失时停止并补齐,不得默认 `main`。
|
|
92
102
|
|
|
93
103
|
## 3.6 可选:触发 compound-refresh
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mstar-harness/dsh",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0-alpha.2",
|
|
4
4
|
"description": "Morning Star harness dsh (DeepSeek Harness) cordis function plugin — in-process engine gates (status/dispatch/lease) with hard refusal channels.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"client": {
|
|
46
46
|
"inject": [
|
|
47
|
-
"@deepseek-ai/dsh-client-
|
|
47
|
+
"@deepseek-ai/dsh-client-store",
|
|
48
48
|
"@deepseek-ai/dsh-client-ui-conversation",
|
|
49
49
|
"@deepseek-ai/dsh-client-locale"
|
|
50
50
|
],
|
|
@@ -56,31 +56,30 @@
|
|
|
56
56
|
"test": "bun test",
|
|
57
57
|
"typecheck:tests": "bunx tsc --noEmit -p tests/tsconfig.json",
|
|
58
58
|
"bundle-assets": "bun run scripts/bundle-harness-assets.ts",
|
|
59
|
-
"build": "bun run bundle-assets && rm -rf dist && bun build src/index.ts src/invariant.ts --target node --outdir dist --external @deepseek-ai/cordis --external @deepseek-ai/dsh-skill-filesystem --external @deepseek-ai/dsh-tools --external @deepseek-ai/dsh-llm
|
|
59
|
+
"build": "bun run bundle-assets && rm -rf dist && bun build src/index.ts src/invariant.ts --target node --outdir dist --external @deepseek-ai/cordis --external @deepseek-ai/dsh-skill-filesystem --external @deepseek-ai/dsh-tools --external @deepseek-ai/dsh-llm && bun run build-client && bunx tsc",
|
|
60
60
|
"build-client": "bun run scripts/build-client-bundle.ts",
|
|
61
61
|
"prepublishOnly": "bun run build"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
64
|
"bun": ">=1.2.17"
|
|
65
65
|
},
|
|
66
|
-
"dependencies": {
|
|
67
|
-
"dsh-llm-fallbacks": "^0.3.0"
|
|
68
|
-
},
|
|
69
66
|
"peerDependencies": {
|
|
70
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
71
|
-
"@deepseek-ai/dsh-agent": "^0.1.
|
|
72
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
73
|
-
"@deepseek-ai/dsh-client-
|
|
74
|
-
"@deepseek-ai/dsh-client-ui-
|
|
75
|
-
"@deepseek-ai/dsh-client-ui-
|
|
76
|
-
"@deepseek-ai/dsh-
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
78
|
-
"@deepseek-ai/dsh-
|
|
79
|
-
"@deepseek-ai/dsh-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
81
|
-
"@deepseek-ai/dsh-
|
|
82
|
-
"@deepseek-ai/dsh-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
67
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
68
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-store": "^0.1.2-alpha.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-chat": "^0.1.2-alpha.2",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-alpha.2",
|
|
73
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
|
|
75
|
+
"@deepseek-ai/dsh-commands": "^0.1.2-alpha.2",
|
|
76
|
+
"@deepseek-ai/dsh-fs": "^0.1.2-alpha.2",
|
|
77
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
78
|
+
"@deepseek-ai/dsh-jobs": "^0.1.2-alpha.2",
|
|
79
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
|
|
80
|
+
"@deepseek-ai/dsh-skill": "^0.1.2-alpha.2",
|
|
81
|
+
"@deepseek-ai/dsh-skill-filesystem": "^0.1.2-alpha.2",
|
|
82
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-alpha.2"
|
|
84
83
|
},
|
|
85
84
|
"publishConfig": {
|
|
86
85
|
"access": "public"
|
|
@@ -91,6 +90,7 @@
|
|
|
91
90
|
"@types/react": "~18.3.1",
|
|
92
91
|
"js-yaml": "^4.1.0",
|
|
93
92
|
"bun-types": "^1.2.17",
|
|
93
|
+
"dsh-llm-fallbacks": "^0.4.0-alpha.1",
|
|
94
94
|
"schemastery": "^3.18.0",
|
|
95
95
|
"typescript": "^5.9.3",
|
|
96
96
|
"vitest": "^4.1.8",
|