@starci/hfs 1.0.0 → 1.0.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/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.1 - 2026-09-30
|
|
4
|
+
|
|
5
|
+
- Fixed: `package.json` now has `exports` for `./runtime/*` and `./package.json`, so other published packages can resolve the runtime copy it carries (`@starci/hfs/runtime/knowledge/hfs/slots.yaml`, `@starci/hfs/runtime/engine/yaml.mjs`) with `import.meta.resolve` or `require.resolve`, wherever the package is installed. `@starci/eslint-canon-be` 1.7.1 reads the slot manifest this way.
|
|
6
|
+
- Changed: `CHANGELOG.md` ships in the package (`files`).
|
|
7
|
+
- The bin is unchanged; the runtime copy is resynced (`canon-pins.yaml` states the new pins).
|
|
8
|
+
|
|
9
|
+
## 1.0.0 - 2026-09-30
|
|
10
|
+
|
|
11
|
+
- First registry publication: the `hfs` command line with its runtime bundle, sync files and templates.
|
package/README.md
CHANGED
|
@@ -36,3 +36,9 @@ except `hfs init`, which writes `hfs.json` only when none exists.
|
|
|
36
36
|
check can emit). After changing `scripts/lib/hfs-check.mjs`, `scripts/lib/hfs-slots.mjs`, `knowledge/hfs/slots.yaml`,
|
|
37
37
|
`knowledge/hfs/canon-pins.yaml` or the catalog entries of those codes, run `node packages/hfs/scripts/sync-runtime.mjs`;
|
|
38
38
|
`tests/hfs-cli.spec.mjs` fails on a stale copy. Bump `version` here and in the pin when the behaviour changes.
|
|
39
|
+
|
|
40
|
+
## Serving knowledge to other packages
|
|
41
|
+
|
|
42
|
+
`package.json` `exports` opens `./runtime/*`, so a package that needs a runtime file resolves it from the installed copy
|
|
43
|
+
(`import.meta.resolve("@starci/hfs/runtime/knowledge/hfs/slots.yaml")`), never from the product repository or a link path.
|
|
44
|
+
`@starci/eslint-canon-be` does this and lists `@starci/hfs` in `dependencies` at the exact version.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starci/hfs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "The HFS command line of a StarCi product repository: hfs check, init, explain, sync and work-hygiene. Self-contained: it carries the runtime files it reads.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -8,12 +8,17 @@
|
|
|
8
8
|
"bin": {
|
|
9
9
|
"hfs": "./bin/hfs.mjs"
|
|
10
10
|
},
|
|
11
|
+
"exports": {
|
|
12
|
+
"./package.json": "./package.json",
|
|
13
|
+
"./runtime/*": "./runtime/*"
|
|
14
|
+
},
|
|
11
15
|
"files": [
|
|
12
16
|
"bin/hfs.mjs",
|
|
13
17
|
"runtime/**",
|
|
14
18
|
"sync/**",
|
|
15
19
|
"templates/**",
|
|
16
|
-
"README.md"
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md"
|
|
17
22
|
],
|
|
18
23
|
"engines": {
|
|
19
24
|
"node": ">=22.13.0"
|
|
@@ -17,12 +17,12 @@ pins:
|
|
|
17
17
|
source: packages/grammar/package.json
|
|
18
18
|
why: nivo-fe pins 0.4.11 and 0.5.0 in one workspace, starci-next-fe 0.5.1, miamia-fe 0.5.0; the runtime source is 0.7.1.
|
|
19
19
|
'@starci/eslint-canon-be':
|
|
20
|
-
version: 1.7.
|
|
20
|
+
version: 1.7.1
|
|
21
21
|
group: starci
|
|
22
22
|
install: registry
|
|
23
23
|
side: be
|
|
24
24
|
source: packages/eslint/be/package.json
|
|
25
|
-
why: 'back-end repositories carry 1.2.1 and 1.2.2 while the runtime source is 1.7.0: the round-3 catch-up landed the nest code-pattern profile''s version and content digest, left unbumped when R78-R82 landed, plus the inbox-dedupe-required shape-detection fix; 1.7.0 adds named-entity-manager-only (R83).'
|
|
25
|
+
why: 'back-end repositories carry 1.2.1 and 1.2.2 while the runtime source is 1.7.0: the round-3 catch-up landed the nest code-pattern profile''s version and content digest, left unbumped when R78-R82 landed, plus the inbox-dedupe-required shape-detection fix; 1.7.0 adds named-entity-manager-only (R83); 1.7.1 reads the slot manifest from the installed @starci/hfs runtime copy instead of the product repository.'
|
|
26
26
|
'@starci/eslint-canon-fe':
|
|
27
27
|
version: 5.1.2
|
|
28
28
|
group: starci
|
|
@@ -69,12 +69,12 @@ pins:
|
|
|
69
69
|
side: fe
|
|
70
70
|
source: packages/playwright-preset/package.json
|
|
71
71
|
'@starci/hfs':
|
|
72
|
-
version: 1.0.
|
|
72
|
+
version: 1.0.1
|
|
73
73
|
group: starci
|
|
74
74
|
install: registry
|
|
75
75
|
side: both
|
|
76
76
|
source: packages/hfs/package.json
|
|
77
|
-
why: the hfs command line (check, init, explain) of every product repository, installed from the npm registry.
|
|
77
|
+
why: the hfs command line (check, init, explain) of every product repository, installed from the npm registry; 1.0.1 exports runtime/* so the eslint canons resolve the knowledge it carries.
|
|
78
78
|
# --- tooling
|
|
79
79
|
typescript:
|
|
80
80
|
version: 5.9.3
|
|
@@ -92,14 +92,15 @@ ruleParams:
|
|
|
92
92
|
globalModules: [src/modules/platform/config/, src/modules/platform/logging/, src/modules/platform/database/]
|
|
93
93
|
# HFS_SIZE_GROWTH: a file above soft may not grow against its parent commit; a new file stays within soft.
|
|
94
94
|
fileLines: {soft: 500, hardGrowth: true}
|
|
95
|
-
#
|
|
96
|
-
|
|
95
|
+
# R21 HFS_DUPLICATE_CODE: the ONE threshold of duplicate code (the architecture machine reads it here; no other file states it):
|
|
96
|
+
# a token-normalised block of at least `lines` source lines and `tokens` tokens that appears twice.
|
|
97
|
+
duplicateBlock: {lines: 8, tokens: 60}
|
|
97
98
|
fe:
|
|
98
99
|
# Slot budgets (component.tsx 300, hooks 200, modules 400) are stricter than this cap where they apply.
|
|
99
100
|
fileLines: {soft: 500, hardGrowth: true}
|
|
100
101
|
# FE_TRANSPORT_OWNER: the one module per app that may call fetch.
|
|
101
102
|
clientModule: "apps/<app>/src/modules/api/client.ts"
|
|
102
|
-
|
|
103
|
+
duplicateBlock: {lines: 8, tokens: 60}
|
|
103
104
|
|
|
104
105
|
slots:
|
|
105
106
|
|
|
@@ -144,13 +144,13 @@ function manifestShapeProblems(m) {
|
|
|
144
144
|
for (const key of Object.keys(def ?? {})) if (!['mayImport', 'acyclic', 'lowerLayerOnly'].includes(key)) bad.push(`tiers.${profile}.${tier}.${key} is not a tier field`);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
-
const
|
|
147
|
+
const blockOk = (v) => isMap(v) && Number.isInteger(v.lines) && v.lines >= 2 && Number.isInteger(v.tokens) && v.tokens >= 1 && Object.keys(v).length === 2;
|
|
148
148
|
const fileLinesOk = (v) => isMap(v) && Number.isInteger(v.soft) && v.soft >= 1 && typeof v.hardGrowth === 'boolean' && Object.keys(v).length === 2;
|
|
149
149
|
const rp = m.ruleParams;
|
|
150
150
|
if (!isMap(rp) || Object.keys(rp).some((k) => !PROFILES.includes(k)) || !PROFILES.every((p) => isMap(rp[p]))) bad.push('ruleParams must be a map with be and fe');
|
|
151
151
|
else {
|
|
152
|
-
if (!(strList(rp.be.globalModules) && new Set(rp.be.globalModules).size === rp.be.globalModules.length) || !fileLinesOk(rp.be.fileLines) || !
|
|
153
|
-
if (!fileLinesOk(rp.fe.fileLines) || typeof rp.fe.clientModule !== 'string' || !rp.fe.clientModule || !
|
|
152
|
+
if (!(strList(rp.be.globalModules) && new Set(rp.be.globalModules).size === rp.be.globalModules.length) || !fileLinesOk(rp.be.fileLines) || !blockOk(rp.be.duplicateBlock) || Object.keys(rp.be).length !== 3) bad.push('ruleParams.be needs globalModules (unique paths), fileLines {soft, hardGrowth} and duplicateBlock {lines >= 2, tokens >= 1}');
|
|
153
|
+
if (!fileLinesOk(rp.fe.fileLines) || typeof rp.fe.clientModule !== 'string' || !rp.fe.clientModule || !blockOk(rp.fe.duplicateBlock) || Object.keys(rp.fe).length !== 3) bad.push('ruleParams.fe needs fileLines {soft, hardGrowth}, clientModule and duplicateBlock {lines >= 2, tokens >= 1}');
|
|
154
154
|
}
|
|
155
155
|
if (!Array.isArray(m.slots) || !m.slots.length) { bad.push('slots must be a non-empty list'); return bad; }
|
|
156
156
|
const slotKeys = new Set(['id', 'profiles', 'path', 'presence', 'tracked', 'tier', 'tests', 'owner', 'appKind', 'minInstances', 'requiredWhen', 'requiredInstances', 'requires', 'allows', 'forbids', 'layers', 'budget', 'managedBy', 'rules', 'goesTo', 'why', 'since', 'retiredIn', 'successor']);
|
|
@@ -535,7 +535,7 @@ export function createSlotResolver(manifest, repo) {
|
|
|
535
535
|
});
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
/** The rule parameters of one profile (be: globalModules, fileLines,
|
|
538
|
+
/** The rule parameters of one profile (be: globalModules, fileLines, duplicateBlock; fe: fileLines, clientModule, duplicateBlock), as a frozen deep copy. */
|
|
539
539
|
export function ruleParams(manifest, profile) {
|
|
540
540
|
if (!PROFILES.includes(profile)) fail('HFS_MANIFEST_INVALID', `ruleParams has no profile ${profile}`, { profile });
|
|
541
541
|
const deepFreeze = (v) => { if (v && typeof v === 'object') Object.values(v).forEach(deepFreeze); return Object.freeze(v); };
|
|
@@ -662,6 +662,12 @@ export function loadRuleCatalog({ root = skillRoot, file = path.join(root, HFS_R
|
|
|
662
662
|
byCode: (code) => byCode.get(code) ?? null,
|
|
663
663
|
/** The rules that run at a gate. */
|
|
664
664
|
forGate: (gate) => list.filter((r) => r.gates.includes(gate)),
|
|
665
|
+
/** The catalogued why code of a lint finding's rule id (`starci-be/<id>`, `starci-fe/<id>`), or undefined. */
|
|
666
|
+
lintCode: (ruleId) => {
|
|
667
|
+
const [plugin, id] = String(ruleId ?? '').split('/');
|
|
668
|
+
const kind = plugin === 'starci-be' ? 'eslint-be' : plugin === 'starci-fe' ? 'eslint-fe' : null;
|
|
669
|
+
return kind ? list.find((r) => r.enforcers.some((e) => e.kind === kind && e.id === id))?.code : undefined;
|
|
670
|
+
},
|
|
665
671
|
/** The rules one enforcer judges, e.g. forEnforcer('eslint-be', 'error-home'). */
|
|
666
672
|
forEnforcer: (kind, id) => list.filter((r) => r.enforcers.some((e) => e.kind === kind && e.id === id)),
|
|
667
673
|
/** Every enforcer still owed, as {rule, kind, id}. */
|
|
@@ -671,5 +677,5 @@ export function loadRuleCatalog({ root = skillRoot, file = path.join(root, HFS_R
|
|
|
671
677
|
});
|
|
672
678
|
}
|
|
673
679
|
|
|
674
|
-
/** The
|
|
680
|
+
/** The rules of this runtime's catalog, frozen, in id order. */
|
|
675
681
|
export const rules = (options) => loadRuleCatalog(options).rules;
|