@lmzhen/dsh-evolution-core 0.26.26 → 0.27.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.
Files changed (107) hide show
  1. package/README.md +16 -1
  2. package/lib/composition/index.js +3 -0
  3. package/lib/composition-D8Y3-ROd.js +604 -0
  4. package/lib/ensure-MEYMj9jn.js +222 -0
  5. package/lib/errors-Br2-uUSK.js +57 -0
  6. package/lib/http-routes-BP-S3KV-.js +149 -0
  7. package/lib/http-routes.js +2 -0
  8. package/lib/index.js +66 -850
  9. package/lib/restrictor.js +37 -0
  10. package/lib/subagent/index.js +186 -0
  11. package/lib/types/citations.js +192 -0
  12. package/lib/types/{preset-composition.d.ts → composition/composer.d.ts} +1 -1
  13. package/lib/types/composition/composer.js +681 -0
  14. package/lib/types/composition/ensure.d.ts +10 -0
  15. package/lib/types/composition/ensure.js +95 -0
  16. package/lib/types/composition/index.d.ts +5 -0
  17. package/lib/types/composition/index.js +7 -0
  18. package/lib/types/composition/preset-ids.d.ts +17 -0
  19. package/lib/types/composition/preset-ids.js +21 -0
  20. package/lib/types/composition/restricted-preset.d.ts +36 -0
  21. package/lib/types/composition/restricted-preset.js +42 -0
  22. package/lib/types/constants.js +223 -0
  23. package/lib/types/cost.js +67 -0
  24. package/lib/types/curator.js +346 -0
  25. package/lib/types/diagnostics.d.ts +26 -0
  26. package/lib/types/diagnostics.js +23 -0
  27. package/lib/types/document-body.js +91 -0
  28. package/lib/types/drift-signals.js +319 -0
  29. package/lib/types/env.js +25 -0
  30. package/lib/types/errors.d.ts +4 -1
  31. package/lib/types/errors.js +59 -0
  32. package/lib/types/events.js +16 -0
  33. package/lib/types/evidence.js +65 -0
  34. package/lib/types/evolution-events.js +479 -0
  35. package/lib/types/fold-untrusted.js +44 -0
  36. package/lib/types/frontmatter.js +623 -0
  37. package/lib/types/fuzzy-match.js +135 -0
  38. package/lib/types/gates.js +51 -0
  39. package/lib/types/guards.js +27 -0
  40. package/lib/types/health-baseline.js +63 -0
  41. package/lib/types/http-routes.d.ts +67 -35
  42. package/lib/types/http-routes.js +135 -0
  43. package/lib/types/index.d.ts +7 -2
  44. package/lib/types/index.js +101 -0
  45. package/lib/types/instance-scope.js +69 -0
  46. package/lib/types/io.js +675 -0
  47. package/lib/types/learn-prompt.js +42 -0
  48. package/lib/types/limits.js +63 -0
  49. package/lib/types/live.js +107 -0
  50. package/lib/types/long-runs.js +96 -0
  51. package/lib/types/memory-store.d.ts +0 -16
  52. package/lib/types/memory-store.js +606 -0
  53. package/lib/types/mutations.js +95 -0
  54. package/lib/types/namespace-migration.js +156 -0
  55. package/lib/types/numeric.js +47 -0
  56. package/lib/types/opt-in.js +101 -0
  57. package/lib/types/package-identity.js +47 -0
  58. package/lib/types/params.js +328 -0
  59. package/lib/types/payload.js +36 -0
  60. package/lib/types/platform-line.generated.d.ts +10 -0
  61. package/lib/types/platform-line.generated.js +12 -0
  62. package/lib/types/platform-services.d.ts +2 -2
  63. package/lib/types/platform-services.js +52 -0
  64. package/lib/types/probe.js +122 -0
  65. package/lib/types/prompts.js +409 -0
  66. package/lib/types/quality.js +308 -0
  67. package/lib/types/reachability.js +122 -0
  68. package/lib/types/redact.js +257 -0
  69. package/lib/types/reference-rewrite.js +144 -0
  70. package/lib/types/reports.js +110 -0
  71. package/lib/types/restrictor.d.ts +11 -0
  72. package/lib/types/restrictor.js +48 -0
  73. package/lib/types/review-channel.js +59 -0
  74. package/lib/types/run-registry.js +345 -0
  75. package/lib/types/scope.js +7 -0
  76. package/lib/types/serial.js +17 -0
  77. package/lib/types/session-fold.d.ts +15 -0
  78. package/lib/types/session-fold.js +28 -0
  79. package/lib/types/session-projection.js +295 -0
  80. package/lib/types/signals.js +209 -0
  81. package/lib/types/skill-discovery.js +66 -0
  82. package/lib/types/skill-health.js +134 -0
  83. package/lib/types/skill-history.js +745 -0
  84. package/lib/types/skill-lint.js +112 -0
  85. package/lib/types/skill-reads.js +67 -0
  86. package/lib/types/skill-row-cells.js +123 -0
  87. package/lib/types/skill-store.js +3528 -0
  88. package/lib/types/state-store.js +60 -0
  89. package/lib/types/store-ledger.js +117 -0
  90. package/lib/types/subagent/channel.d.ts +4 -0
  91. package/lib/types/subagent/channel.js +131 -0
  92. package/lib/types/subagent/index.d.ts +4 -0
  93. package/lib/types/subagent/index.js +5 -0
  94. package/lib/types/subagent/readiness.d.ts +6 -0
  95. package/lib/types/subagent/readiness.js +35 -0
  96. package/lib/types/subagent/types.d.ts +58 -0
  97. package/lib/types/subagent/types.js +2 -0
  98. package/lib/types/threats.js +338 -0
  99. package/lib/types/tool-dispatch.d.ts +5 -0
  100. package/lib/types/tool-dispatch.js +535 -0
  101. package/lib/types/tree-write.js +40 -0
  102. package/lib/types/unit-members.js +121 -0
  103. package/lib/types/usage.js +474 -0
  104. package/lib/types/write-authority.js +23 -0
  105. package/lib/types/write-gates.js +344 -0
  106. package/lib/types/write-inventory.js +158 -0
  107. package/package.json +39 -11
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Skill structure-health domain (rc.73 A1, 008 design): a SECOND assessment
3
+ * dimension beside the six-factor usage quality — document hygiene, consumed
4
+ * by the curator health view and the `/evolution skills health` command.
5
+ *
6
+ * PURE and DERIVED: nothing is persisted; every assessment is computed from
7
+ * file facts at read time. The judgment split follows the original's
8
+ * boundary/治理 layering — deterministic signals here, refinement proposals
9
+ * stay in the review/curator judgment layer. Never become a 7th factor of
10
+ * `computeQualityScores` (different dimension, different consumers).
11
+ */
12
+ import { AUTHORING_SPLIT_LINE_CHARS, UPSTREAM_LIMIT_CHARS_PER_TOKEN } from "./constants.js";
13
+ import { bodyCost, tokenLineFor } from "./cost.js";
14
+ import { lintSkill } from "./skill-lint.js";
15
+ export const DEFAULT_HEALTH_THRESHOLDS = {
16
+ // V6: the number is the UPSTREAM line itself (20k characters — "if you're
17
+ // pushing past 20k, split into references/*.md"). The previous 40k was twice
18
+ // that line, which is why a body could sit at 2x the authoring discipline and
19
+ // still read as merely "warn". The JUDGMENT happens in tokens (see
20
+ // assessStructureHealth): the line is converted per body composition, so the
21
+ // textual trigger stays exactly "20k characters" while every reported number is
22
+ // a token count.
23
+ softBodyChars: AUTHORING_SPLIT_LINE_CHARS,
24
+ stampDensityPerKb: 2,
25
+ churnMinPatches: 20,
26
+ };
27
+ /**
28
+ * Stamp regex shared by health assessment and the maintenance probe (single
29
+ * source, 011). Two refinements over the naive form (F-320): the hex branch
30
+ * requires at least one digit so coincidental all-letter English words
31
+ * (`defaced`, `feedback`) are not counted as commit shas; the ISO branch
32
+ * accepts a UTC `Z`, a numeric UTC offset (`+08:00`), or no timezone at all —
33
+ * non-UTC timestamps used to escape detection (log-like content missed).
34
+ *
35
+ * Known boundary, recorded not fixed (C-22, v10 audit): the hex branch also
36
+ * matches 7-40 char PURE-DIGIT strings (order numbers etc.), so stamp density
37
+ * can be over-reported for such content. The misjudgment direction is "extra
38
+ * stamp hits" only — never a miss — and no real incident exists; revisit only
39
+ * if curator decisions are actually distorted (v10 deferral ledger).
40
+ */
41
+ export const HEALTH_STAMP_RE = new RegExp(String.raw `\brc\.\d+\b|\b(?=[0-9a-f]{7,40}\b)[0-9a-f]*[0-9][0-9a-f]*\b|\b\d{4}-\d{2}-\d{2}(?:T[0-9:.]+(?:Z|[+-]\d{2}:?\d{2})?)?\b`, 'g');
42
+ /**
43
+ * Bodies below this size skip stamp-density assessment: a few dates or shas
44
+ * in a short body are ordinary documentation, not log-like content. With the
45
+ * 1KB density floor a 3-date sentence in a small skill measured 3.0/KB and
46
+ * warned on a perfectly healthy body (audit 2026-08-31 X1).
47
+ */
48
+ export const MIN_STAMP_BODY_CHARS = 2_000;
49
+ /**
50
+ * The findings for ONE body, computed by the engine that owns the judgement (G4).
51
+ *
52
+ * Deliberately a thin call into `assessStructureHealth`: a later consumer (the write receipt) needs
53
+ * findings for a body it is about to store, and re-deriving the facts anywhere else would be a
54
+ * SECOND judgement — the token-scale line, the /1024 stamp density and the soft/2 support threshold
55
+ * all live in one place and must stay there.
56
+ * @param skillName - the skill the body belongs to (used in messages).
57
+ * @param content - the WHOLE SKILL.md text, frontmatter included (the engine's own convention).
58
+ * @param supportGroups - non-empty support dirs; pass the real count, never a guess.
59
+ * @param thresholds - the configured thresholds; defaults to the shipped ones.
60
+ * @returns the findings, in rule order.
61
+ */
62
+ export function lintBody(skillName, content, supportGroups, thresholds = DEFAULT_HEALTH_THRESHOLDS) {
63
+ return assessStructureHealth({ skillName, bodyChars: content.length, bodyText: content, supportGroups }, thresholds).findings;
64
+ }
65
+ export function assessStructureHealth(snapshot, thresholds = DEFAULT_HEALTH_THRESHOLDS) {
66
+ const dims = {
67
+ bodyChars: snapshot.bodyChars,
68
+ bodyTokens: Math.round(snapshot.bodyChars / UPSTREAM_LIMIT_CHARS_PER_TOKEN),
69
+ stampDensityPerKb: null,
70
+ stampHits: null,
71
+ supportGroups: snapshot.supportGroups,
72
+ supportFiles: snapshot.supportFiles ?? null,
73
+ churnPatches: null,
74
+ churnReads: null,
75
+ };
76
+ // V6: the JUDGMENT runs on the token scale. The configured number stays the
77
+ // borrowed UPSTREAM character line, converted per body composition, so the
78
+ // textual trigger is unchanged while every reported number is a token count.
79
+ // Without body text the token scale is unavailable — the character line then
80
+ // decides, because an absent measurement must never read as a pass.
81
+ const text = snapshot.bodyText;
82
+ const hasText = typeof text === 'string' && text.length > 0;
83
+ const cost = hasText ? bodyCost(text) : null;
84
+ const lineTokens = cost === null ? null : tokenLineFor(thresholds.softBodyChars, cost);
85
+ dims.bodyTokens = cost === null
86
+ // No text: no composition to weigh, so the LIMIT basis is the only honest
87
+ // conversion — the estimate range would need a CJK/ASCII split we do not have.
88
+ ? Math.round(snapshot.bodyChars / UPSTREAM_LIMIT_CHARS_PER_TOKEN)
89
+ : cost.tokens;
90
+ const overLine = cost === null || lineTokens === null
91
+ ? snapshot.bodyChars >= thresholds.softBodyChars
92
+ : cost.tokens >= lineTokens;
93
+ const overTwice = cost === null || lineTokens === null
94
+ ? snapshot.bodyChars >= thresholds.softBodyChars * 2
95
+ : cost.tokens >= lineTokens * 2;
96
+ // G2 ③: the over-line judgement is now expressed as `findings` (see the RULES table in skill-lint);
97
+ // the free-text copy that used to live here is gone, and `overLine`/`overTwice` feed the facts above.
98
+ if (snapshot.bodyText && snapshot.bodyChars >= MIN_STAMP_BODY_CHARS) {
99
+ const kb = Math.max(1, snapshot.bodyChars / 1024);
100
+ const stamps = (snapshot.bodyText.match(HEALTH_STAMP_RE) ?? []).length;
101
+ dims.stampDensityPerKb = stamps / kb;
102
+ dims.stampHits = stamps;
103
+ }
104
+ if (snapshot.patchCount !== undefined && snapshot.readCount !== undefined) {
105
+ dims.churnPatches = snapshot.patchCount;
106
+ dims.churnReads = snapshot.readCount;
107
+ }
108
+ // G1/§3b: the FORM of the judgement. `skill-lint` owns no thresholds — it re-expresses what this
109
+ // engine already decided (token-scale line, /1024 stamp density, soft/2 support threshold).
110
+ const findings = lintSkill({
111
+ skillName: snapshot.skillName,
112
+ dims,
113
+ softLineChars: thresholds.softBodyChars,
114
+ overSoftLine: overLine,
115
+ overTwiceSoftLine: overTwice,
116
+ stampLimitPerKb: thresholds.stampDensityPerKb,
117
+ churnMinPatches: thresholds.churnMinPatches,
118
+ // This engine's snapshot always carries a MEASURED body (its type has no null arm yet); the
119
+ // unreadable case becomes expressible when the caller's type does, and the rule already waits.
120
+ readable: true,
121
+ });
122
+ // G2 ③: the verdict now reads the FINDINGS (equivalent to the reason list by construction — the
123
+ // churn threshold above was aligned for exactly this switch, and the old tests staying green is
124
+ // the equivalence proof).
125
+ const verdict = findings.some(f => f.rule === 'body-oversize-2x')
126
+ ? 'needs-restructure'
127
+ : findings.length > 0 ? 'warn' : 'healthy';
128
+ return {
129
+ verdict,
130
+ dims,
131
+ findings,
132
+ };
133
+ }
134
+ //# sourceMappingURL=skill-health.js.map