@lmzhen/dsh-evolution-merge 0.30.27 → 0.30.28

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/lib/index.js CHANGED
@@ -8217,7 +8217,7 @@ function buildValidationPlan(input) {
8217
8217
  const staged = new Set(files.map((file) => file.path));
8218
8218
  const manifest = new Set(manifestFiles);
8219
8219
  const forwardRefs = [...refs].filter((ref) => !staged.has(ref)).sort();
8220
- const reverseRefs = files.map((file) => file.path).filter((path) => !refs.has(path) && manifest.has(path)).sort();
8220
+ const reverseRefs = files.map((file) => file.path).filter((path) => path !== "SKILL.md" && !refs.has(path) && manifest.has(path)).sort();
8221
8221
  const orphanFiles = [...new Set(input.existingSupport ?? [])].filter((path) => !staged.has(path)).sort();
8222
8222
  const byPath = /* @__PURE__ */ new Map();
8223
8223
  const supportSources = input.supportSources ?? [];
@@ -8234,12 +8234,14 @@ function buildValidationPlan(input) {
8234
8234
  path,
8235
8235
  sources: value.sources
8236
8236
  }));
8237
- const sourceThreatFiles = (input.cards ?? []).flatMap((card) => (card.files ?? []).filter((file) => scanContentThreats(file.content) !== null).map((file) => card.name + "/" + file.path));
8237
+ const participants = input.participants === void 0 ? void 0 : new Set(input.participants);
8238
+ const participantCards = participants === void 0 ? input.cards ?? [] : (input.cards ?? []).filter((card) => participants.has(card.name));
8239
+ const sourceThreatFiles = participantCards.flatMap((card) => (card.files ?? []).filter((file) => scanContentThreats(file.content) !== null).map((file) => card.name + "/" + file.path));
8238
8240
  const threat = {
8239
- body: scanContentThreats(input.tree.body) !== null || (input.cards ?? []).some((card) => scanContentThreats(card.body) !== null),
8241
+ body: scanContentThreats(input.tree.body) !== null || participantCards.some((card) => scanContentThreats(card.body) !== null),
8240
8242
  files: [...files.filter((file) => scanContentThreats(file.content) !== null).map((file) => file.path), ...sourceThreatFiles]
8241
8243
  };
8242
- const sourceRevisions = input.sourceRevisions ?? Object.fromEntries((input.cards ?? []).map((card) => [card.name, digest(card.body)]));
8244
+ const sourceRevisions = input.sourceRevisions ?? Object.fromEntries(participantCards.map((card) => [card.name, digest(card.body)]));
8243
8245
  const revision = digest(JSON.stringify({
8244
8246
  target: input.target,
8245
8247
  body: digest(input.tree.body),
@@ -8473,6 +8475,7 @@ async function runAuthoring(options) {
8473
8475
  source: "staged"
8474
8476
  })),
8475
8477
  manifestFiles,
8478
+ ...options.sources === void 0 ? {} : { participants: [...options.sources, options.target] },
8476
8479
  existingSupport: (options.cards.find((card) => card.name === options.target)?.files ?? []).map((file) => file.path)
8477
8480
  });
8478
8481
  const findings = [...validateStagedTree(tree.value, limitsSnapshot.skillLimits), ...validationPlan.findings];
@@ -8890,6 +8893,11 @@ async function runNewChildAuthoring(options, row, decision, signal) {
8890
8893
  source: "staged"
8891
8894
  })),
8892
8895
  manifestFiles,
8896
+ participants: [
8897
+ row.a,
8898
+ row.b,
8899
+ decision.target
8900
+ ],
8893
8901
  existingSupport: (options.cards.find((card) => card.name === decision.target)?.files ?? []).map((file) => file.path),
8894
8902
  supportSources: options.cards.filter((card) => card.name === row.a || card.name === row.b).flatMap((card) => (card.files ?? []).map((file) => ({
8895
8903
  path: file.path,
@@ -65,7 +65,7 @@ export async function runAuthoring(options) {
65
65
  const limitsSnapshot = limitsSnapshotOf(options.limits ?? DEFAULT_SKILL_LIMITS);
66
66
  const participants = new Set(options.sources ?? []);
67
67
  const supportSources = options.cards.filter(card => participants.has(card.name)).flatMap(card => (card.files ?? []).map(file => ({ path: file.path, content: file.content, source: card.name })));
68
- const validationPlan = buildValidationPlan({ tree: tree.value, target: options.target, limits: limitsSnapshot, cards: options.cards, supportSources, ...(options.promptVersion === undefined ? {} : { promptVersion: options.promptVersion }), ...(options.promptHash === undefined ? {} : { promptHash: options.promptHash }), supportFiles: tree.value.files.map(file => ({ path: file.path, content: file.content, source: 'staged' })), manifestFiles, existingSupport: (options.cards.find(card => card.name === options.target)?.files ?? []).map(file => file.path) });
68
+ const validationPlan = buildValidationPlan({ tree: tree.value, target: options.target, limits: limitsSnapshot, cards: options.cards, supportSources, ...(options.promptVersion === undefined ? {} : { promptVersion: options.promptVersion }), ...(options.promptHash === undefined ? {} : { promptHash: options.promptHash }), supportFiles: tree.value.files.map(file => ({ path: file.path, content: file.content, source: 'staged' })), manifestFiles, ...(options.sources === undefined ? {} : { participants: [...options.sources, options.target] }), existingSupport: (options.cards.find(card => card.name === options.target)?.files ?? []).map(file => file.path) });
69
69
  const findings = [...validateStagedTree(tree.value, limitsSnapshot.skillLimits), ...validationPlan.findings];
70
70
  const lengths = { bodyBytes: Buffer.byteLength(tree.value.body, 'utf8'), fileBytes: tree.value.files.reduce((sum, file) => sum + Buffer.byteLength(file.content, 'utf8'), 0), totalBytes: Buffer.byteLength(tree.value.body, 'utf8') + tree.value.files.reduce((sum, file) => sum + Buffer.byteLength(file.content, 'utf8'), 0) };
71
71
  if (hasBlockingFinding(findings))
@@ -61,5 +61,7 @@ export declare function buildValidationPlan(input: {
61
61
  }[];
62
62
  readonly promptVersion?: string;
63
63
  readonly promptHash?: string;
64
+ /** Skills that participate in this merge (pair sources and target); omit for legacy all-card behavior. */
65
+ readonly participants?: readonly string[];
64
66
  }): ValidationPlan;
65
67
  //# sourceMappingURL=validation-plan.d.ts.map
@@ -10,7 +10,9 @@ export function buildValidationPlan(input) {
10
10
  const staged = new Set(files.map(file => file.path));
11
11
  const manifest = new Set(manifestFiles);
12
12
  const forwardRefs = [...refs].filter(ref => !staged.has(ref)).sort();
13
- const reverseRefs = files.map(file => file.path).filter(path => !refs.has(path) && manifest.has(path)).sort();
13
+ // SKILL.md is the body itself, never a support reference; a child may list it in the
14
+ // authoring manifest, but it must not require the body to reference itself.
15
+ const reverseRefs = files.map(file => file.path).filter(path => path !== 'SKILL.md' && !refs.has(path) && manifest.has(path)).sort();
14
16
  const existing = new Set(input.existingSupport ?? []);
15
17
  const orphanFiles = [...existing].filter(path => !staged.has(path)).sort();
16
18
  const byPath = new Map();
@@ -25,9 +27,11 @@ export function buildValidationPlan(input) {
25
27
  byPath.set(file.path, entry);
26
28
  }
27
29
  const supportConflicts = [...byPath.entries()].filter(([, value]) => value.contents.size > 1).map(([path, value]) => ({ path, sources: value.sources }));
28
- const sourceThreatFiles = (input.cards ?? []).flatMap(card => (card.files ?? []).filter(file => scanContentThreats(file.content) !== null).map(file => card.name + '/' + file.path));
29
- const threat = { body: scanContentThreats(input.tree.body) !== null || (input.cards ?? []).some(card => scanContentThreats(card.body) !== null), files: [...files.filter(file => scanContentThreats(file.content) !== null).map(file => file.path), ...sourceThreatFiles] };
30
- const sourceRevisions = input.sourceRevisions ?? Object.fromEntries((input.cards ?? []).map(card => [card.name, digest(card.body)]));
30
+ const participants = input.participants === undefined ? undefined : new Set(input.participants);
31
+ const participantCards = participants === undefined ? (input.cards ?? []) : (input.cards ?? []).filter(card => participants.has(card.name));
32
+ const sourceThreatFiles = participantCards.flatMap(card => (card.files ?? []).filter(file => scanContentThreats(file.content) !== null).map(file => card.name + '/' + file.path));
33
+ const threat = { body: scanContentThreats(input.tree.body) !== null || participantCards.some(card => scanContentThreats(card.body) !== null), files: [...files.filter(file => scanContentThreats(file.content) !== null).map(file => file.path), ...sourceThreatFiles] };
34
+ const sourceRevisions = input.sourceRevisions ?? Object.fromEntries(participantCards.map(card => [card.name, digest(card.body)]));
31
35
  const revision = digest(JSON.stringify({ target: input.target, body: digest(input.tree.body), files: files.map(file => [file.path, file.digest]), q09: { forwardRefs, reverseRefs, orphanFiles }, supportConflicts, threat, sourceRevisions, targetRevision: input.targetRevision ?? null }));
32
36
  const findings = [];
33
37
  const stageDigest = digest(JSON.stringify(files.map(file => [file.path, file.digest])));
@@ -90,7 +90,7 @@ export async function runNewChildAuthoring(options, row, decision, signal) {
90
90
  if (missing !== null)
91
91
  return { kind: 'failed', failure: { stage: 'author', code: 'merge-manifest-missing', message: 'manifest file missing from staged tree: ' + missing, retryable: true, retryFrom: 'agent2' } };
92
92
  const limitsSnapshot = limitsSnapshotOf(options.limits ?? DEFAULT_SKILL_LIMITS);
93
- const validationPlan = buildValidationPlan({ tree: tree.value, target: decision.target, limits: limitsSnapshot, cards: options.cards, promptVersion: MERGE_PROMPT_VERSION, promptHash: promptHashOf(buildRound2Prompt(row, decision)), supportFiles: tree.value.files.map(file => ({ path: file.path, content: file.content, source: 'staged' })), manifestFiles, existingSupport: (options.cards.find(card => card.name === decision.target)?.files ?? []).map(file => file.path), supportSources: options.cards.filter(card => card.name === row.a || card.name === row.b).flatMap(card => (card.files ?? []).map(file => ({ path: file.path, content: file.content, source: card.name }))) });
93
+ const validationPlan = buildValidationPlan({ tree: tree.value, target: decision.target, limits: limitsSnapshot, cards: options.cards, promptVersion: MERGE_PROMPT_VERSION, promptHash: promptHashOf(buildRound2Prompt(row, decision)), supportFiles: tree.value.files.map(file => ({ path: file.path, content: file.content, source: 'staged' })), manifestFiles, participants: [row.a, row.b, decision.target], existingSupport: (options.cards.find(card => card.name === decision.target)?.files ?? []).map(file => file.path), supportSources: options.cards.filter(card => card.name === row.a || card.name === row.b).flatMap(card => (card.files ?? []).map(file => ({ path: file.path, content: file.content, source: card.name }))) });
94
94
  const findings = [...validateStagedTree(tree.value, limitsSnapshot.skillLimits), ...validationPlan.findings];
95
95
  if (hasBlockingFinding(findings)) {
96
96
  const lengths = { bodyBytes: Buffer.byteLength(tree.value.body, 'utf8'), fileBytes: tree.value.files.reduce((sum, file) => sum + Buffer.byteLength(file.content, 'utf8'), 0), totalBytes: Buffer.byteLength(tree.value.body, 'utf8') + tree.value.files.reduce((sum, file) => sum + Buffer.byteLength(file.content, 'utf8'), 0) };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-merge",
3
3
  "description": "Skill auto-merge domain: screening, two-round authoring, queues and commit orchestration (community build)",
4
- "version": "0.30.27",
4
+ "version": "0.30.28",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,9 +32,9 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@deepseek-ai/schemastery": "^3.18.5",
35
- "@lmzhen/dsh-evolution-core": "^0.30.27",
36
- "@lmzhen/dsh-evolution-commands": "^0.30.27",
37
- "@lmzhen/dsh-evolution-merge-engine": "0.30.27"
35
+ "@lmzhen/dsh-evolution-core": "^0.30.28",
36
+ "@lmzhen/dsh-evolution-commands": "^0.30.28",
37
+ "@lmzhen/dsh-evolution-merge-engine": "0.30.28"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@deepseek-ai/cordis": "^4.0.5"