@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.
- package/README.md +16 -1
- package/lib/composition/index.js +3 -0
- package/lib/composition-D8Y3-ROd.js +604 -0
- package/lib/ensure-MEYMj9jn.js +222 -0
- package/lib/errors-Br2-uUSK.js +57 -0
- package/lib/http-routes-BP-S3KV-.js +149 -0
- package/lib/http-routes.js +2 -0
- package/lib/index.js +66 -850
- package/lib/restrictor.js +37 -0
- package/lib/subagent/index.js +186 -0
- package/lib/types/citations.js +192 -0
- package/lib/types/{preset-composition.d.ts → composition/composer.d.ts} +1 -1
- package/lib/types/composition/composer.js +681 -0
- package/lib/types/composition/ensure.d.ts +10 -0
- package/lib/types/composition/ensure.js +95 -0
- package/lib/types/composition/index.d.ts +5 -0
- package/lib/types/composition/index.js +7 -0
- package/lib/types/composition/preset-ids.d.ts +17 -0
- package/lib/types/composition/preset-ids.js +21 -0
- package/lib/types/composition/restricted-preset.d.ts +36 -0
- package/lib/types/composition/restricted-preset.js +42 -0
- package/lib/types/constants.js +223 -0
- package/lib/types/cost.js +67 -0
- package/lib/types/curator.js +346 -0
- package/lib/types/diagnostics.d.ts +26 -0
- package/lib/types/diagnostics.js +23 -0
- package/lib/types/document-body.js +91 -0
- package/lib/types/drift-signals.js +319 -0
- package/lib/types/env.js +25 -0
- package/lib/types/errors.d.ts +4 -1
- package/lib/types/errors.js +59 -0
- package/lib/types/events.js +16 -0
- package/lib/types/evidence.js +65 -0
- package/lib/types/evolution-events.js +479 -0
- package/lib/types/fold-untrusted.js +44 -0
- package/lib/types/frontmatter.js +623 -0
- package/lib/types/fuzzy-match.js +135 -0
- package/lib/types/gates.js +51 -0
- package/lib/types/guards.js +27 -0
- package/lib/types/health-baseline.js +63 -0
- package/lib/types/http-routes.d.ts +67 -35
- package/lib/types/http-routes.js +135 -0
- package/lib/types/index.d.ts +7 -2
- package/lib/types/index.js +101 -0
- package/lib/types/instance-scope.js +69 -0
- package/lib/types/io.js +675 -0
- package/lib/types/learn-prompt.js +42 -0
- package/lib/types/limits.js +63 -0
- package/lib/types/live.js +107 -0
- package/lib/types/long-runs.js +96 -0
- package/lib/types/memory-store.d.ts +0 -16
- package/lib/types/memory-store.js +606 -0
- package/lib/types/mutations.js +95 -0
- package/lib/types/namespace-migration.js +156 -0
- package/lib/types/numeric.js +47 -0
- package/lib/types/opt-in.js +101 -0
- package/lib/types/package-identity.js +47 -0
- package/lib/types/params.js +328 -0
- package/lib/types/payload.js +36 -0
- package/lib/types/platform-line.generated.d.ts +10 -0
- package/lib/types/platform-line.generated.js +12 -0
- package/lib/types/platform-services.d.ts +2 -2
- package/lib/types/platform-services.js +52 -0
- package/lib/types/probe.js +122 -0
- package/lib/types/prompts.js +409 -0
- package/lib/types/quality.js +308 -0
- package/lib/types/reachability.js +122 -0
- package/lib/types/redact.js +257 -0
- package/lib/types/reference-rewrite.js +144 -0
- package/lib/types/reports.js +110 -0
- package/lib/types/restrictor.d.ts +11 -0
- package/lib/types/restrictor.js +48 -0
- package/lib/types/review-channel.js +59 -0
- package/lib/types/run-registry.js +345 -0
- package/lib/types/scope.js +7 -0
- package/lib/types/serial.js +17 -0
- package/lib/types/session-fold.d.ts +15 -0
- package/lib/types/session-fold.js +28 -0
- package/lib/types/session-projection.js +295 -0
- package/lib/types/signals.js +209 -0
- package/lib/types/skill-discovery.js +66 -0
- package/lib/types/skill-health.js +134 -0
- package/lib/types/skill-history.js +745 -0
- package/lib/types/skill-lint.js +112 -0
- package/lib/types/skill-reads.js +67 -0
- package/lib/types/skill-row-cells.js +123 -0
- package/lib/types/skill-store.js +3528 -0
- package/lib/types/state-store.js +60 -0
- package/lib/types/store-ledger.js +117 -0
- package/lib/types/subagent/channel.d.ts +4 -0
- package/lib/types/subagent/channel.js +131 -0
- package/lib/types/subagent/index.d.ts +4 -0
- package/lib/types/subagent/index.js +5 -0
- package/lib/types/subagent/readiness.d.ts +6 -0
- package/lib/types/subagent/readiness.js +35 -0
- package/lib/types/subagent/types.d.ts +58 -0
- package/lib/types/subagent/types.js +2 -0
- package/lib/types/threats.js +338 -0
- package/lib/types/tool-dispatch.d.ts +5 -0
- package/lib/types/tool-dispatch.js +535 -0
- package/lib/types/tree-write.js +40 -0
- package/lib/types/unit-members.js +121 -0
- package/lib/types/usage.js +474 -0
- package/lib/types/write-authority.js +23 -0
- package/lib/types/write-gates.js +344 -0
- package/lib/types/write-inventory.js +158 -0
- 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
|