@agimon-ai/vibe-lint-plugin-doom-extension 0.0.1-alpha.15
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/LICENSE +52 -0
- package/README.md +29 -0
- package/dist/_virtual/_rolldown/runtime.cjs +1 -0
- package/dist/configs/recommended.cjs +2 -0
- package/dist/configs/recommended.cjs.map +1 -0
- package/dist/configs/recommended.d.cts +11 -0
- package/dist/configs/recommended.d.cts.map +1 -0
- package/dist/configs/recommended.d.mts +11 -0
- package/dist/configs/recommended.d.mts.map +1 -0
- package/dist/configs/recommended.mjs +2 -0
- package/dist/configs/recommended.mjs.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +1 -0
- package/dist/plugin.cjs +2 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +6 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.mts +6 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +2 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/rules/architecture.cjs +2 -0
- package/dist/rules/architecture.cjs.map +1 -0
- package/dist/rules/architecture.d.cts +14 -0
- package/dist/rules/architecture.d.cts.map +1 -0
- package/dist/rules/architecture.d.mts +14 -0
- package/dist/rules/architecture.d.mts.map +1 -0
- package/dist/rules/architecture.mjs +2 -0
- package/dist/rules/architecture.mjs.map +1 -0
- package/dist/rules/conventions.cjs +3 -0
- package/dist/rules/conventions.cjs.map +1 -0
- package/dist/rules/conventions.d.cts +12 -0
- package/dist/rules/conventions.d.cts.map +1 -0
- package/dist/rules/conventions.d.mts +12 -0
- package/dist/rules/conventions.d.mts.map +1 -0
- package/dist/rules/conventions.mjs +3 -0
- package/dist/rules/conventions.mjs.map +1 -0
- package/dist/rules/index.d.cts +5 -0
- package/dist/rules/index.d.mts +5 -0
- package/dist/rules/manifestEntries.cjs +2 -0
- package/dist/rules/manifestEntries.cjs.map +1 -0
- package/dist/rules/manifestEntries.mjs +2 -0
- package/dist/rules/manifestEntries.mjs.map +1 -0
- package/dist/rules/piExtensionContract.cjs +3 -0
- package/dist/rules/piExtensionContract.cjs.map +1 -0
- package/dist/rules/piExtensionContract.d.cts +6 -0
- package/dist/rules/piExtensionContract.d.cts.map +1 -0
- package/dist/rules/piExtensionContract.d.mts +6 -0
- package/dist/rules/piExtensionContract.d.mts.map +1 -0
- package/dist/rules/piExtensionContract.mjs +3 -0
- package/dist/rules/piExtensionContract.mjs.map +1 -0
- package/dist/rules/registry.cjs +2 -0
- package/dist/rules/registry.cjs.map +1 -0
- package/dist/rules/registry.d.cts +6 -0
- package/dist/rules/registry.d.cts.map +1 -0
- package/dist/rules/registry.d.mts +6 -0
- package/dist/rules/registry.d.mts.map +1 -0
- package/dist/rules/registry.mjs +2 -0
- package/dist/rules/registry.mjs.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: AgiFlow
|
|
6
|
+
Licensed Work: @agimon-ai/public-packages
|
|
7
|
+
The Licensed Work is (c) 2026 AgiFlow.
|
|
8
|
+
Additional Use Grant: None
|
|
9
|
+
Change Date: 2030-03-06
|
|
10
|
+
Change License: Apache License, Version 2.0
|
|
11
|
+
|
|
12
|
+
Terms
|
|
13
|
+
|
|
14
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
15
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
16
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
17
|
+
production use.
|
|
18
|
+
|
|
19
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
20
|
+
available distribution of a specific version of the Licensed Work under this
|
|
21
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
22
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
23
|
+
above terminate.
|
|
24
|
+
|
|
25
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
26
|
+
currently in effect as described in this License, you must purchase a
|
|
27
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
28
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
29
|
+
|
|
30
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
31
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
32
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
33
|
+
for each version of the Licensed Work released by Licensor.
|
|
34
|
+
|
|
35
|
+
You must conspicuously display this License on each original or modified copy
|
|
36
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
37
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
38
|
+
License apply to your use of that work.
|
|
39
|
+
|
|
40
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
41
|
+
terminate your rights under this License for the current and all other
|
|
42
|
+
versions of the Licensed Work.
|
|
43
|
+
|
|
44
|
+
This License does not grant you any right in any trademark or logo of
|
|
45
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
46
|
+
Licensor as expressly required by this License).
|
|
47
|
+
|
|
48
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
49
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
52
|
+
TITLE.
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @agimon-ai/vibe-lint-plugin-doom-extension
|
|
2
|
+
|
|
3
|
+
Deterministic Vibe-Lint rules for publishable DoomPi extension packages.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -D @agimon-ai/vibe-lint @agimon-ai/vibe-lint-plugin-doom-extension
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configure
|
|
12
|
+
|
|
13
|
+
Vibe-Lint resolves the short plugin name to this package:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
plugins:
|
|
17
|
+
- core
|
|
18
|
+
- doom-extension
|
|
19
|
+
|
|
20
|
+
extends:
|
|
21
|
+
- core/recommended
|
|
22
|
+
- doom-extension/recommended
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Use `doom-extension/migration` to enable every rule at warning severity while migrating an existing package.
|
|
26
|
+
|
|
27
|
+
## Public API
|
|
28
|
+
|
|
29
|
+
The default export is the Vibe-Lint plugin contract. The package also exports `doomExtensionPlugin`, `rules`, `recommended`, `migration`, and each deterministic rule definition as named exports.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={rules:{"doom-folder-layout":`error`,"compatibility-wrapper-only":`error`,"public-export-boundary":`off`,"no-internal-public-import":`off`,"doom-layer-boundary":`off`,"service-boundary":`error`,"schema-placement":`error`,"doom-package-shape":`error`,"pi-peer-version":`error`,"pi-extension-default-factory":`error`,"thin-pi-adapter":`error`,"no-raw-pi-events":`error`,"no-protocol-channel-literals":`error`,"dispose-external-subscriptions":`error`,"provider-owned-policy":`error`}},t={rules:Object.fromEntries(Object.keys(e.rules).map(e=>[e,`warn`]))};exports.migration=t,exports.recommended=e;
|
|
2
|
+
//# sourceMappingURL=recommended.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended.cjs","names":[],"sources":["../../src/configs/recommended.ts"],"sourcesContent":["import type { Severity } from '@agimon-ai/vibe-lint';\n\nexport const recommended: { rules: Record<string, Severity> } = {\n rules: {\n 'doom-folder-layout': 'error',\n 'compatibility-wrapper-only': 'error',\n // Migration rules are promoted after all Doom packages move to src/exports.\n 'public-export-boundary': 'off',\n 'no-internal-public-import': 'off',\n 'doom-layer-boundary': 'off',\n 'service-boundary': 'error',\n 'schema-placement': 'error',\n 'doom-package-shape': 'error',\n 'pi-peer-version': 'error',\n 'pi-extension-default-factory': 'error',\n 'thin-pi-adapter': 'error',\n 'no-raw-pi-events': 'error',\n 'no-protocol-channel-literals': 'error',\n 'dispose-external-subscriptions': 'error',\n 'provider-owned-policy': 'error',\n },\n};\n\nexport const migration: { rules: Record<string, Severity> } = {\n rules: Object.fromEntries(Object.keys(recommended.rules).map((ruleId) => [ruleId, 'warn' as const])),\n};\n"],"mappings":"AAEA,MAAa,EAAmD,CAC9D,MAAO,CACL,qBAAsB,QACtB,6BAA8B,QAE9B,yBAA0B,MAC1B,4BAA6B,MAC7B,sBAAuB,MACvB,mBAAoB,QACpB,mBAAoB,QACpB,qBAAsB,QACtB,kBAAmB,QACnB,+BAAgC,QAChC,kBAAmB,QACnB,mBAAoB,QACpB,+BAAgC,QAChC,iCAAkC,QAClC,wBAAyB,OAC3B,CACF,EAEa,EAAiD,CAC5D,MAAO,OAAO,YAAY,OAAO,KAAK,EAAY,KAAK,CAAC,CAAC,IAAK,GAAW,CAAC,EAAQ,MAAe,CAAC,CAAC,CACrG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Severity } from "@agimon-ai/vibe-lint";
|
|
2
|
+
//#region src/configs/recommended.d.ts
|
|
3
|
+
declare const recommended: {
|
|
4
|
+
rules: Record<string, Severity>;
|
|
5
|
+
};
|
|
6
|
+
declare const migration: {
|
|
7
|
+
rules: Record<string, Severity>;
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { migration, recommended };
|
|
11
|
+
//# sourceMappingURL=recommended.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended.d.cts","names":[],"sources":["../../src/configs/recommended.ts"],"mappings":";;cAEa;EAAe,OAAO,eAAe;;cAqBrC;EAAa,OAAO,eAAe"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Severity } from "@agimon-ai/vibe-lint";
|
|
2
|
+
//#region src/configs/recommended.d.ts
|
|
3
|
+
declare const recommended: {
|
|
4
|
+
rules: Record<string, Severity>;
|
|
5
|
+
};
|
|
6
|
+
declare const migration: {
|
|
7
|
+
rules: Record<string, Severity>;
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { migration, recommended };
|
|
11
|
+
//# sourceMappingURL=recommended.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended.d.mts","names":[],"sources":["../../src/configs/recommended.ts"],"mappings":";;cAEa;EAAe,OAAO,eAAe;;cAqBrC;EAAa,OAAO,eAAe"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={rules:{"doom-folder-layout":`error`,"compatibility-wrapper-only":`error`,"public-export-boundary":`off`,"no-internal-public-import":`off`,"doom-layer-boundary":`off`,"service-boundary":`error`,"schema-placement":`error`,"doom-package-shape":`error`,"pi-peer-version":`error`,"pi-extension-default-factory":`error`,"thin-pi-adapter":`error`,"no-raw-pi-events":`error`,"no-protocol-channel-literals":`error`,"dispose-external-subscriptions":`error`,"provider-owned-policy":`error`}},t={rules:Object.fromEntries(Object.keys(e.rules).map(e=>[e,`warn`]))};export{t as migration,e as recommended};
|
|
2
|
+
//# sourceMappingURL=recommended.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended.mjs","names":[],"sources":["../../src/configs/recommended.ts"],"sourcesContent":["import type { Severity } from '@agimon-ai/vibe-lint';\n\nexport const recommended: { rules: Record<string, Severity> } = {\n rules: {\n 'doom-folder-layout': 'error',\n 'compatibility-wrapper-only': 'error',\n // Migration rules are promoted after all Doom packages move to src/exports.\n 'public-export-boundary': 'off',\n 'no-internal-public-import': 'off',\n 'doom-layer-boundary': 'off',\n 'service-boundary': 'error',\n 'schema-placement': 'error',\n 'doom-package-shape': 'error',\n 'pi-peer-version': 'error',\n 'pi-extension-default-factory': 'error',\n 'thin-pi-adapter': 'error',\n 'no-raw-pi-events': 'error',\n 'no-protocol-channel-literals': 'error',\n 'dispose-external-subscriptions': 'error',\n 'provider-owned-policy': 'error',\n },\n};\n\nexport const migration: { rules: Record<string, Severity> } = {\n rules: Object.fromEntries(Object.keys(recommended.rules).map((ruleId) => [ruleId, 'warn' as const])),\n};\n"],"mappings":"AAEA,MAAa,EAAmD,CAC9D,MAAO,CACL,qBAAsB,QACtB,6BAA8B,QAE9B,yBAA0B,MAC1B,4BAA6B,MAC7B,sBAAuB,MACvB,mBAAoB,QACpB,mBAAoB,QACpB,qBAAsB,QACtB,kBAAmB,QACnB,+BAAgC,QAChC,kBAAmB,QACnB,mBAAoB,QACpB,+BAAgC,QAChC,iCAAkC,QAClC,wBAAyB,OAC3B,CACF,EAEa,EAAiD,CAC5D,MAAO,OAAO,YAAY,OAAO,KAAK,EAAY,KAAK,CAAC,CAAC,IAAK,GAAW,CAAC,EAAQ,MAAe,CAAC,CAAC,CACrG"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./configs/recommended.cjs"),t=require("./rules/architecture.cjs"),n=require("./rules/conventions.cjs"),r=require("./rules/piExtensionContract.cjs"),i=require("./rules/registry.cjs"),a=require("./plugin.cjs");exports.compatibilityWrapperOnly=t.compatibilityWrapperOnly,exports.default=a.doomExtensionPlugin,exports.disposeExternalSubscriptions=n.disposeExternalSubscriptions,exports.doomExtensionPlugin=a.doomExtensionPlugin,exports.doomFolderLayout=t.doomFolderLayout,exports.doomLayerBoundary=t.doomLayerBoundary,exports.doomPackageShape=n.doomPackageShape,exports.migration=e.migration,exports.noInternalPublicImport=t.noInternalPublicImport,exports.noProtocolChannelLiterals=n.noProtocolChannelLiterals,exports.noRawPiEvents=n.noRawPiEvents,exports.piExtensionDefaultFactory=r.piExtensionDefaultFactory,exports.piPeerVersion=n.piPeerVersion,exports.providerOwnedPolicy=n.providerOwnedPolicy,exports.publicExportBoundary=t.publicExportBoundary,exports.recommended=e.recommended,exports.rules=i.rules,exports.schemaPlacement=t.schemaPlacement,exports.serviceBoundary=t.serviceBoundary,exports.thinPiAdapter=n.thinPiAdapter;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { migration, recommended } from "./configs/recommended.cjs";
|
|
2
|
+
import { doomExtensionPlugin } from "./plugin.cjs";
|
|
3
|
+
import { compatibilityWrapperOnly, doomFolderLayout, doomLayerBoundary, noInternalPublicImport, publicExportBoundary, schemaPlacement, serviceBoundary } from "./rules/architecture.cjs";
|
|
4
|
+
import { disposeExternalSubscriptions, doomPackageShape, noProtocolChannelLiterals, noRawPiEvents, piPeerVersion, providerOwnedPolicy, thinPiAdapter } from "./rules/conventions.cjs";
|
|
5
|
+
import { piExtensionDefaultFactory } from "./rules/piExtensionContract.cjs";
|
|
6
|
+
import { rules } from "./rules/registry.cjs";
|
|
7
|
+
import "./rules/index.cjs";
|
|
8
|
+
export { compatibilityWrapperOnly, doomExtensionPlugin as default, disposeExternalSubscriptions, doomExtensionPlugin, doomFolderLayout, doomLayerBoundary, doomPackageShape, migration, noInternalPublicImport, noProtocolChannelLiterals, noRawPiEvents, piExtensionDefaultFactory, piPeerVersion, providerOwnedPolicy, publicExportBoundary, recommended, rules, schemaPlacement, serviceBoundary, thinPiAdapter };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { migration, recommended } from "./configs/recommended.mjs";
|
|
2
|
+
import { doomExtensionPlugin } from "./plugin.mjs";
|
|
3
|
+
import { compatibilityWrapperOnly, doomFolderLayout, doomLayerBoundary, noInternalPublicImport, publicExportBoundary, schemaPlacement, serviceBoundary } from "./rules/architecture.mjs";
|
|
4
|
+
import { disposeExternalSubscriptions, doomPackageShape, noProtocolChannelLiterals, noRawPiEvents, piPeerVersion, providerOwnedPolicy, thinPiAdapter } from "./rules/conventions.mjs";
|
|
5
|
+
import { piExtensionDefaultFactory } from "./rules/piExtensionContract.mjs";
|
|
6
|
+
import { rules } from "./rules/registry.mjs";
|
|
7
|
+
import "./rules/index.mjs";
|
|
8
|
+
export { compatibilityWrapperOnly, doomExtensionPlugin as default, disposeExternalSubscriptions, doomExtensionPlugin, doomFolderLayout, doomLayerBoundary, doomPackageShape, migration, noInternalPublicImport, noProtocolChannelLiterals, noRawPiEvents, piExtensionDefaultFactory, piPeerVersion, providerOwnedPolicy, publicExportBoundary, recommended, rules, schemaPlacement, serviceBoundary, thinPiAdapter };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{migration as e,recommended as t}from"./configs/recommended.mjs";import{compatibilityWrapperOnly as n,doomFolderLayout as r,doomLayerBoundary as i,noInternalPublicImport as a,publicExportBoundary as o,schemaPlacement as s,serviceBoundary as c}from"./rules/architecture.mjs";import{disposeExternalSubscriptions as l,doomPackageShape as u,noProtocolChannelLiterals as d,noRawPiEvents as f,piPeerVersion as p,providerOwnedPolicy as m,thinPiAdapter as h}from"./rules/conventions.mjs";import{piExtensionDefaultFactory as g}from"./rules/piExtensionContract.mjs";import{rules as _}from"./rules/registry.mjs";import{doomExtensionPlugin as v}from"./plugin.mjs";export{n as compatibilityWrapperOnly,v as default,l as disposeExternalSubscriptions,v as doomExtensionPlugin,r as doomFolderLayout,i as doomLayerBoundary,u as doomPackageShape,e as migration,a as noInternalPublicImport,d as noProtocolChannelLiterals,f as noRawPiEvents,g as piExtensionDefaultFactory,p as piPeerVersion,m as providerOwnedPolicy,o as publicExportBoundary,t as recommended,_ as rules,s as schemaPlacement,c as serviceBoundary,h as thinPiAdapter};
|
package/dist/plugin.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { VibeLintPlugin } from '@agimon-ai/vibe-lint';\nimport { migration, recommended } from './configs/recommended.js';\nimport { rules } from './rules/registry.js';\n\nexport const doomExtensionPlugin: VibeLintPlugin = {\n name: 'doom-extension',\n rules,\n configs: { migration, recommended },\n};\n"],"mappings":"6CAIa,EAAsC,CACjD,KAAM,iBACN,oCAAA,CAAA,CAAA,MACA,QAAS,CAAE,UAAA,EAAA,UAAW,YAAA,EAAA,WAAY,CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":";;cAIa,qBAAqB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.mts","names":[],"sources":["../src/plugin.ts"],"mappings":";;cAIa,qBAAqB"}
|
package/dist/plugin.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { VibeLintPlugin } from '@agimon-ai/vibe-lint';\nimport { migration, recommended } from './configs/recommended.js';\nimport { rules } from './rules/registry.js';\n\nexport const doomExtensionPlugin: VibeLintPlugin = {\n name: 'doom-extension',\n rules,\n configs: { migration, recommended },\n};\n"],"mappings":"oHAIA,MAAa,EAAsC,CACjD,KAAM,iBACN,QACA,QAAS,CAAE,YAAW,aAAY,CACpC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./manifestEntries.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:path");r=e.__toESM(r,1);let i=require("typescript");i=e.__toESM(i,1);const a=new Set([`adapters`,`commands`,`container`,`exports`,`schemas`,`services`,`tui`,`types`]),o=new Set([`bin`,`extensions`]),s=new Set([`agents`,`api`,`common`,`components`,`config`,`delegation`,`entries`,`helpers`,`interfaces`,`misc`,`protocol`,`runs`,`shared`,`slash`,`store`,`tool`,`utils`,`workflow`]),c=new Set([`.ts`,`.tsx`,`.mts`,`.cts`]),l=[`@earendil-works/pi-`,`inversify`],u=[`adapters`,`bin`,`commands`,`container`,`exports`,`extensions`,`tui`],d={adapters:new Set([`adapters`,`schemas`,`services`,`types`]),commands:new Set([`commands`,`schemas`,`services`,`types`]),container:new Set([`adapters`,`commands`,`container`,`schemas`,`services`,`tui`,`types`]),exports:a,schemas:new Set([`schemas`,`types`]),services:new Set([`schemas`,`services`,`types`]),tui:new Set([`schemas`,`services`,`tui`,`types`]),types:new Set([`types`])};function f(e){return!n.existsSync(e)||!c.has(r.extname(e))?null:i.default.createSourceFile(e,n.readFileSync(e,`utf8`),i.default.ScriptTarget.Latest,!0)}function p(e){return e.split(r.sep).filter(Boolean)}function m(e){let t=p(e),n=t.lastIndexOf(`src`);return n>=0?t[n+1]:void 0}function h(e){let t=[],n=e=>{(i.default.isImportDeclaration(e)||i.default.isExportDeclaration(e))&&e.moduleSpecifier&&i.default.isStringLiteralLike(e.moduleSpecifier)&&t.push(e.moduleSpecifier.text),i.default.isCallExpression(e)&&e.expression.kind===i.default.SyntaxKind.ImportKeyword&&e.arguments.length===1&&i.default.isStringLiteralLike(e.arguments[0])&&t.push(e.arguments[0].text),i.default.forEachChild(e,n)};return n(e),t}function g(e){return i.default.isCallExpression(e)&&(i.default.isPropertyAccessExpression(e.expression)&&i.default.isIdentifier(e.expression.expression)&&[`Type`,`z`].includes(e.expression.expression.text)&&e.expression.name.text!==`toJSONSchema`||i.default.isIdentifier(e.expression)&&[`Type`,`z`].includes(e.expression.text))?!0:e.getChildren().some(g)}function _(e){return e.statements.length>0&&e.statements.every(e=>i.default.isExportDeclaration(e)&&e.moduleSpecifier!==void 0)}function v(e,t){if(t.startsWith(`.`))return m(r.resolve(r.dirname(e),t))}const y={preflight:!0,rule:`Doom source modules use the canonical root vocabulary, with src/exports as the public boundary`,rationale:`One predictable folder vocabulary makes package boundaries navigable and mechanically enforceable.`,check(e){let t=m(e);if(!t||t===`index.ts`||a.has(t)||o.has(t))return null;let n=f(e);return n&&_(n)?null:`${s.has(t)?`Legacy root "${t}" must be a forwarding wrapper during migration.`:`Unknown root "${t}" is not canonical.`} Move implementation under exports, types, schemas, services, adapters, commands, container, or tui.`}},b={preflight:!0,rule:`Noncanonical compatibility modules contain forwarding exports only during migration`,rationale:`Compatibility paths may remain public temporarily without becoming a second implementation architecture.`,check(e){let t=m(e);if(!t||t===`index.ts`||a.has(t)||o.has(t))return null;let n=f(e);return n&&!_(n)?`Noncanonical public paths must contain only re-exports from canonical modules during migration.`:null}},x={preflight:!0,rule:`Pure forwarding modules may exist only under src/exports`,rationale:`A single manifest-facing boundary keeps compatibility facades from becoming a parallel internal architecture.`,check(e){let t=f(e);return!t||!_(t)||m(e)===`exports`?null:`Move this public facade under src/exports and import its canonical implementation directly everywhere else.`}},S={preflight:!0,rule:`Implementation modules never import src/exports or their own package public subpaths`,rationale:`Internal code should depend on canonical implementations rather than cycling through compatibility facades.`,check(e,n){let r=m(e);if(!r||r===`exports`)return null;let i=f(e);if(!i)return null;let a=t.readPackageManifest(n)?.name,o=h(i).filter(t=>v(e,t)===`exports`||a!==void 0&&(t===a||t.startsWith(`${a}/`))),s=[...new Set(o)];return s.length>0?`Implementation imports public package facades: ${s.join(`, `)}`:null}},C={preflight:!0,rule:`Canonical Doom layers point inward through types, schemas, services, adapters, and composition roots`,rationale:`A small universal dependency direction prevents host and presentation concerns from leaking into policy.`,check(e){let t=m(e),n=t?d[t]:void 0;if(!t||!n)return null;let r=f(e);if(!r||_(r))return null;let i=h(r).filter(t=>{let r=v(e,t);return r!==void 0&&!n.has(r)}),a=[...new Set(i)];return a.length>0?`Layer imports forbidden dependencies: ${a.join(`, `)}`:null}},w={preflight:!0,rule:`Services depend only on services, types, and schemas and never on hosts, containers, concrete adapters, or node:*`,rationale:`Host-neutral services remain independently testable and reusable when infrastructure points inward through contracts.`,check(e){if(m(e)!==`services`)return null;let t=f(e);if(!t||_(t))return null;let n=h(t).filter(t=>{if(t.startsWith(`node:`)||l.some(e=>t.startsWith(e)))return!0;let n=v(e,t);return n?u.includes(n):!1});return n.length>0?`Service imports forbidden dependencies: ${n.join(`, `)}`:null}},T={preflight:!0,rule:`Runtime TypeBox and Zod schema construction lives under src/schemas`,rationale:`Central runtime schemas keep validation contracts discoverable while services consume schema-derived types.`,check(e){let t=m(e);if(!t||t===`schemas`)return null;let n=f(e);return n&&g(n)?`Move runtime TypeBox or Zod schema construction under src/schemas and import the derived contract.`:null}};exports.compatibilityWrapperOnly=b,exports.doomFolderLayout=y,exports.doomLayerBoundary=C,exports.isPureReExportModule=_,exports.noInternalPublicImport=S,exports.publicExportBoundary=x,exports.schemaPlacement=T,exports.serviceBoundary=w;
|
|
2
|
+
//# sourceMappingURL=architecture.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.cjs","names":["fs","path","ts","readPackageManifest"],"sources":["../../src/rules/architecture.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport ts from 'typescript';\nimport { readPackageManifest } from './manifestEntries.js';\n\nconst CANONICAL_ROOTS = new Set([\n 'adapters',\n 'commands',\n 'container',\n 'exports',\n 'schemas',\n 'services',\n 'tui',\n 'types',\n]);\nconst TRANSITIONAL_ROOTS = new Set(['bin', 'extensions']);\nconst FORBIDDEN_ROOTS = new Set([\n 'agents',\n 'api',\n 'common',\n 'components',\n 'config',\n 'delegation',\n 'entries',\n 'helpers',\n 'interfaces',\n 'misc',\n 'protocol',\n 'runs',\n 'shared',\n 'slash',\n 'store',\n 'tool',\n 'utils',\n 'workflow',\n]);\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']);\nconst HOST_PACKAGES = ['@earendil-works/pi-', 'inversify'];\nconst EXTERNAL_IMPLEMENTATION_ROOTS = ['adapters', 'bin', 'commands', 'container', 'exports', 'extensions', 'tui'];\nconst ALLOWED_ROOT_DEPENDENCIES: Readonly<Record<string, ReadonlySet<string>>> = {\n adapters: new Set(['adapters', 'schemas', 'services', 'types']),\n commands: new Set(['commands', 'schemas', 'services', 'types']),\n container: new Set(['adapters', 'commands', 'container', 'schemas', 'services', 'tui', 'types']),\n exports: CANONICAL_ROOTS,\n schemas: new Set(['schemas', 'types']),\n services: new Set(['schemas', 'services', 'types']),\n tui: new Set(['schemas', 'services', 'tui', 'types']),\n types: new Set(['types']),\n};\n\nfunction readSource(filePath: string): ts.SourceFile | null {\n if (!fs.existsSync(filePath) || !SOURCE_EXTENSIONS.has(path.extname(filePath))) return null;\n return ts.createSourceFile(filePath, fs.readFileSync(filePath, 'utf8'), ts.ScriptTarget.Latest, true);\n}\n\nfunction normalizedParts(filePath: string): string[] {\n return filePath.split(path.sep).filter(Boolean);\n}\n\nfunction sourceRoot(filePath: string): string | undefined {\n const parts = normalizedParts(filePath);\n const sourceIndex = parts.lastIndexOf('src');\n return sourceIndex >= 0 ? parts[sourceIndex + 1] : undefined;\n}\n\nfunction collectSpecifiers(sourceFile: ts.SourceFile): string[] {\n const specifiers: string[] = [];\n const visit = (node: ts.Node): void => {\n if (\n (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&\n node.moduleSpecifier &&\n ts.isStringLiteralLike(node.moduleSpecifier)\n ) {\n specifiers.push(node.moduleSpecifier.text);\n }\n if (\n ts.isCallExpression(node) &&\n node.expression.kind === ts.SyntaxKind.ImportKeyword &&\n node.arguments.length === 1 &&\n ts.isStringLiteralLike(node.arguments[0]!)\n ) {\n specifiers.push(node.arguments[0].text);\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return specifiers;\n}\n\nfunction containsRuntimeSchema(node: ts.Node): boolean {\n if (\n ts.isCallExpression(node) &&\n ((ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.expression) &&\n ['Type', 'z'].includes(node.expression.expression.text) &&\n node.expression.name.text !== 'toJSONSchema') ||\n (ts.isIdentifier(node.expression) && ['Type', 'z'].includes(node.expression.text)))\n ) {\n return true;\n }\n return node.getChildren().some(containsRuntimeSchema);\n}\n\nexport function isPureReExportModule(sourceFile: ts.SourceFile): boolean {\n return (\n sourceFile.statements.length > 0 &&\n sourceFile.statements.every(\n (statement) => ts.isExportDeclaration(statement) && statement.moduleSpecifier !== undefined,\n )\n );\n}\n\nfunction relativeImportRoot(filePath: string, specifier: string): string | undefined {\n if (!specifier.startsWith('.')) return undefined;\n return sourceRoot(path.resolve(path.dirname(filePath), specifier));\n}\n\nexport const doomFolderLayout: RuleDefinition = {\n preflight: true,\n rule: 'Doom source modules use the canonical root vocabulary, with src/exports as the public boundary',\n rationale: 'One predictable folder vocabulary makes package boundaries navigable and mechanically enforceable.',\n check(filePath) {\n const root = sourceRoot(filePath);\n if (!root || root === 'index.ts' || CANONICAL_ROOTS.has(root) || TRANSITIONAL_ROOTS.has(root)) return null;\n const sourceFile = readSource(filePath);\n if (sourceFile && isPureReExportModule(sourceFile)) return null;\n const detail = FORBIDDEN_ROOTS.has(root)\n ? `Legacy root \"${root}\" must be a forwarding wrapper during migration.`\n : `Unknown root \"${root}\" is not canonical.`;\n return `${detail} Move implementation under exports, types, schemas, services, adapters, commands, container, or tui.`;\n },\n};\n\n/** @deprecated Remove after all Doom packages enable public-export-boundary. */\nexport const compatibilityWrapperOnly: RuleDefinition = {\n preflight: true,\n rule: 'Noncanonical compatibility modules contain forwarding exports only during migration',\n rationale: 'Compatibility paths may remain public temporarily without becoming a second implementation architecture.',\n check(filePath) {\n const root = sourceRoot(filePath);\n if (!root || root === 'index.ts' || CANONICAL_ROOTS.has(root) || TRANSITIONAL_ROOTS.has(root)) return null;\n const sourceFile = readSource(filePath);\n return sourceFile && !isPureReExportModule(sourceFile)\n ? 'Noncanonical public paths must contain only re-exports from canonical modules during migration.'\n : null;\n },\n};\n\nexport const publicExportBoundary: RuleDefinition = {\n preflight: true,\n rule: 'Pure forwarding modules may exist only under src/exports',\n rationale:\n 'A single manifest-facing boundary keeps compatibility facades from becoming a parallel internal architecture.',\n check(filePath) {\n const sourceFile = readSource(filePath);\n if (!sourceFile || !isPureReExportModule(sourceFile) || sourceRoot(filePath) === 'exports') return null;\n return 'Move this public facade under src/exports and import its canonical implementation directly everywhere else.';\n },\n};\n\nexport const noInternalPublicImport: RuleDefinition = {\n preflight: true,\n rule: 'Implementation modules never import src/exports or their own package public subpaths',\n rationale:\n 'Internal code should depend on canonical implementations rather than cycling through compatibility facades.',\n check(filePath, configRoot) {\n const root = sourceRoot(filePath);\n if (!root || root === 'exports') return null;\n const sourceFile = readSource(filePath);\n if (!sourceFile) return null;\n const packageName = readPackageManifest(configRoot)?.name;\n const blocked = collectSpecifiers(sourceFile).filter((specifier) => {\n if (relativeImportRoot(filePath, specifier) === 'exports') return true;\n return packageName !== undefined && (specifier === packageName || specifier.startsWith(`${packageName}/`));\n });\n const uniqueBlocked = [...new Set(blocked)];\n return uniqueBlocked.length > 0\n ? `Implementation imports public package facades: ${uniqueBlocked.join(', ')}`\n : null;\n },\n};\n\nexport const doomLayerBoundary: RuleDefinition = {\n preflight: true,\n rule: 'Canonical Doom layers point inward through types, schemas, services, adapters, and composition roots',\n rationale: 'A small universal dependency direction prevents host and presentation concerns from leaking into policy.',\n check(filePath) {\n const root = sourceRoot(filePath);\n const allowedRoots = root ? ALLOWED_ROOT_DEPENDENCIES[root] : undefined;\n if (!root || !allowedRoots) return null;\n const sourceFile = readSource(filePath);\n if (!sourceFile || isPureReExportModule(sourceFile)) return null;\n const blocked = collectSpecifiers(sourceFile).filter((specifier) => {\n const targetRoot = relativeImportRoot(filePath, specifier);\n return targetRoot !== undefined && !allowedRoots.has(targetRoot);\n });\n const uniqueBlocked = [...new Set(blocked)];\n return uniqueBlocked.length > 0 ? `Layer imports forbidden dependencies: ${uniqueBlocked.join(', ')}` : null;\n },\n};\n\nexport const serviceBoundary: RuleDefinition = {\n preflight: true,\n rule: 'Services depend only on services, types, and schemas and never on hosts, containers, concrete adapters, or node:*',\n rationale:\n 'Host-neutral services remain independently testable and reusable when infrastructure points inward through contracts.',\n check(filePath) {\n if (sourceRoot(filePath) !== 'services') return null;\n const sourceFile = readSource(filePath);\n if (!sourceFile || isPureReExportModule(sourceFile)) return null;\n const blocked = collectSpecifiers(sourceFile).filter((specifier) => {\n if (specifier.startsWith('node:') || HOST_PACKAGES.some((packageName) => specifier.startsWith(packageName))) {\n return true;\n }\n const targetRoot = relativeImportRoot(filePath, specifier);\n return targetRoot ? EXTERNAL_IMPLEMENTATION_ROOTS.includes(targetRoot) : false;\n });\n return blocked.length > 0 ? `Service imports forbidden dependencies: ${blocked.join(', ')}` : null;\n },\n};\n\nexport const schemaPlacement: RuleDefinition = {\n preflight: true,\n rule: 'Runtime TypeBox and Zod schema construction lives under src/schemas',\n rationale:\n 'Central runtime schemas keep validation contracts discoverable while services consume schema-derived types.',\n check(filePath) {\n const root = sourceRoot(filePath);\n if (!root || root === 'schemas') return null;\n const sourceFile = readSource(filePath);\n return sourceFile && containsRuntimeSchema(sourceFile)\n ? 'Move runtime TypeBox or Zod schema construction under src/schemas and import the derived contract.'\n : null;\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RuleDefinition } from "@agimon-ai/vibe-lint";
|
|
2
|
+
import "typescript";
|
|
3
|
+
//#region src/rules/architecture.d.ts
|
|
4
|
+
declare const doomFolderLayout: RuleDefinition;
|
|
5
|
+
/** @deprecated Remove after all Doom packages enable public-export-boundary. */
|
|
6
|
+
declare const compatibilityWrapperOnly: RuleDefinition;
|
|
7
|
+
declare const publicExportBoundary: RuleDefinition;
|
|
8
|
+
declare const noInternalPublicImport: RuleDefinition;
|
|
9
|
+
declare const doomLayerBoundary: RuleDefinition;
|
|
10
|
+
declare const serviceBoundary: RuleDefinition;
|
|
11
|
+
declare const schemaPlacement: RuleDefinition;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { compatibilityWrapperOnly, doomFolderLayout, doomLayerBoundary, noInternalPublicImport, publicExportBoundary, schemaPlacement, serviceBoundary };
|
|
14
|
+
//# sourceMappingURL=architecture.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.d.cts","names":[],"sources":["../../src/rules/architecture.ts"],"mappings":";;;cAsHa,kBAAkB;;cAiBlB,0BAA0B;cAc1B,sBAAsB;cAYtB,wBAAwB;cAsBxB,mBAAmB;cAmBnB,iBAAiB;cAoBjB,iBAAiB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { RuleDefinition } from "@agimon-ai/vibe-lint";
|
|
3
|
+
//#region src/rules/architecture.d.ts
|
|
4
|
+
declare const doomFolderLayout: RuleDefinition;
|
|
5
|
+
/** @deprecated Remove after all Doom packages enable public-export-boundary. */
|
|
6
|
+
declare const compatibilityWrapperOnly: RuleDefinition;
|
|
7
|
+
declare const publicExportBoundary: RuleDefinition;
|
|
8
|
+
declare const noInternalPublicImport: RuleDefinition;
|
|
9
|
+
declare const doomLayerBoundary: RuleDefinition;
|
|
10
|
+
declare const serviceBoundary: RuleDefinition;
|
|
11
|
+
declare const schemaPlacement: RuleDefinition;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { compatibilityWrapperOnly, doomFolderLayout, doomLayerBoundary, noInternalPublicImport, publicExportBoundary, schemaPlacement, serviceBoundary };
|
|
14
|
+
//# sourceMappingURL=architecture.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.d.mts","names":[],"sources":["../../src/rules/architecture.ts"],"mappings":";;;cAsHa,kBAAkB;;cAiBlB,0BAA0B;cAc1B,sBAAsB;cAYtB,wBAAwB;cAsBxB,mBAAmB;cAmBnB,iBAAiB;cAoBjB,iBAAiB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{readPackageManifest as e}from"./manifestEntries.mjs";import*as t from"node:fs";import*as n from"node:path";import r from"typescript";const i=new Set([`adapters`,`commands`,`container`,`exports`,`schemas`,`services`,`tui`,`types`]),a=new Set([`bin`,`extensions`]),o=new Set([`agents`,`api`,`common`,`components`,`config`,`delegation`,`entries`,`helpers`,`interfaces`,`misc`,`protocol`,`runs`,`shared`,`slash`,`store`,`tool`,`utils`,`workflow`]),s=new Set([`.ts`,`.tsx`,`.mts`,`.cts`]),c=[`@earendil-works/pi-`,`inversify`],l=[`adapters`,`bin`,`commands`,`container`,`exports`,`extensions`,`tui`],u={adapters:new Set([`adapters`,`schemas`,`services`,`types`]),commands:new Set([`commands`,`schemas`,`services`,`types`]),container:new Set([`adapters`,`commands`,`container`,`schemas`,`services`,`tui`,`types`]),exports:i,schemas:new Set([`schemas`,`types`]),services:new Set([`schemas`,`services`,`types`]),tui:new Set([`schemas`,`services`,`tui`,`types`]),types:new Set([`types`])};function d(e){return!t.existsSync(e)||!s.has(n.extname(e))?null:r.createSourceFile(e,t.readFileSync(e,`utf8`),r.ScriptTarget.Latest,!0)}function f(e){return e.split(n.sep).filter(Boolean)}function p(e){let t=f(e),n=t.lastIndexOf(`src`);return n>=0?t[n+1]:void 0}function m(e){let t=[],n=e=>{(r.isImportDeclaration(e)||r.isExportDeclaration(e))&&e.moduleSpecifier&&r.isStringLiteralLike(e.moduleSpecifier)&&t.push(e.moduleSpecifier.text),r.isCallExpression(e)&&e.expression.kind===r.SyntaxKind.ImportKeyword&&e.arguments.length===1&&r.isStringLiteralLike(e.arguments[0])&&t.push(e.arguments[0].text),r.forEachChild(e,n)};return n(e),t}function h(e){return r.isCallExpression(e)&&(r.isPropertyAccessExpression(e.expression)&&r.isIdentifier(e.expression.expression)&&[`Type`,`z`].includes(e.expression.expression.text)&&e.expression.name.text!==`toJSONSchema`||r.isIdentifier(e.expression)&&[`Type`,`z`].includes(e.expression.text))?!0:e.getChildren().some(h)}function g(e){return e.statements.length>0&&e.statements.every(e=>r.isExportDeclaration(e)&&e.moduleSpecifier!==void 0)}function _(e,t){if(t.startsWith(`.`))return p(n.resolve(n.dirname(e),t))}const v={preflight:!0,rule:`Doom source modules use the canonical root vocabulary, with src/exports as the public boundary`,rationale:`One predictable folder vocabulary makes package boundaries navigable and mechanically enforceable.`,check(e){let t=p(e);if(!t||t===`index.ts`||i.has(t)||a.has(t))return null;let n=d(e);return n&&g(n)?null:`${o.has(t)?`Legacy root "${t}" must be a forwarding wrapper during migration.`:`Unknown root "${t}" is not canonical.`} Move implementation under exports, types, schemas, services, adapters, commands, container, or tui.`}},y={preflight:!0,rule:`Noncanonical compatibility modules contain forwarding exports only during migration`,rationale:`Compatibility paths may remain public temporarily without becoming a second implementation architecture.`,check(e){let t=p(e);if(!t||t===`index.ts`||i.has(t)||a.has(t))return null;let n=d(e);return n&&!g(n)?`Noncanonical public paths must contain only re-exports from canonical modules during migration.`:null}},b={preflight:!0,rule:`Pure forwarding modules may exist only under src/exports`,rationale:`A single manifest-facing boundary keeps compatibility facades from becoming a parallel internal architecture.`,check(e){let t=d(e);return!t||!g(t)||p(e)===`exports`?null:`Move this public facade under src/exports and import its canonical implementation directly everywhere else.`}},x={preflight:!0,rule:`Implementation modules never import src/exports or their own package public subpaths`,rationale:`Internal code should depend on canonical implementations rather than cycling through compatibility facades.`,check(t,n){let r=p(t);if(!r||r===`exports`)return null;let i=d(t);if(!i)return null;let a=e(n)?.name,o=m(i).filter(e=>_(t,e)===`exports`||a!==void 0&&(e===a||e.startsWith(`${a}/`))),s=[...new Set(o)];return s.length>0?`Implementation imports public package facades: ${s.join(`, `)}`:null}},S={preflight:!0,rule:`Canonical Doom layers point inward through types, schemas, services, adapters, and composition roots`,rationale:`A small universal dependency direction prevents host and presentation concerns from leaking into policy.`,check(e){let t=p(e),n=t?u[t]:void 0;if(!t||!n)return null;let r=d(e);if(!r||g(r))return null;let i=m(r).filter(t=>{let r=_(e,t);return r!==void 0&&!n.has(r)}),a=[...new Set(i)];return a.length>0?`Layer imports forbidden dependencies: ${a.join(`, `)}`:null}},C={preflight:!0,rule:`Services depend only on services, types, and schemas and never on hosts, containers, concrete adapters, or node:*`,rationale:`Host-neutral services remain independently testable and reusable when infrastructure points inward through contracts.`,check(e){if(p(e)!==`services`)return null;let t=d(e);if(!t||g(t))return null;let n=m(t).filter(t=>{if(t.startsWith(`node:`)||c.some(e=>t.startsWith(e)))return!0;let n=_(e,t);return n?l.includes(n):!1});return n.length>0?`Service imports forbidden dependencies: ${n.join(`, `)}`:null}},w={preflight:!0,rule:`Runtime TypeBox and Zod schema construction lives under src/schemas`,rationale:`Central runtime schemas keep validation contracts discoverable while services consume schema-derived types.`,check(e){let t=p(e);if(!t||t===`schemas`)return null;let n=d(e);return n&&h(n)?`Move runtime TypeBox or Zod schema construction under src/schemas and import the derived contract.`:null}};export{y as compatibilityWrapperOnly,v as doomFolderLayout,S as doomLayerBoundary,g as isPureReExportModule,x as noInternalPublicImport,b as publicExportBoundary,w as schemaPlacement,C as serviceBoundary};
|
|
2
|
+
//# sourceMappingURL=architecture.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.mjs","names":[],"sources":["../../src/rules/architecture.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport ts from 'typescript';\nimport { readPackageManifest } from './manifestEntries.js';\n\nconst CANONICAL_ROOTS = new Set([\n 'adapters',\n 'commands',\n 'container',\n 'exports',\n 'schemas',\n 'services',\n 'tui',\n 'types',\n]);\nconst TRANSITIONAL_ROOTS = new Set(['bin', 'extensions']);\nconst FORBIDDEN_ROOTS = new Set([\n 'agents',\n 'api',\n 'common',\n 'components',\n 'config',\n 'delegation',\n 'entries',\n 'helpers',\n 'interfaces',\n 'misc',\n 'protocol',\n 'runs',\n 'shared',\n 'slash',\n 'store',\n 'tool',\n 'utils',\n 'workflow',\n]);\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']);\nconst HOST_PACKAGES = ['@earendil-works/pi-', 'inversify'];\nconst EXTERNAL_IMPLEMENTATION_ROOTS = ['adapters', 'bin', 'commands', 'container', 'exports', 'extensions', 'tui'];\nconst ALLOWED_ROOT_DEPENDENCIES: Readonly<Record<string, ReadonlySet<string>>> = {\n adapters: new Set(['adapters', 'schemas', 'services', 'types']),\n commands: new Set(['commands', 'schemas', 'services', 'types']),\n container: new Set(['adapters', 'commands', 'container', 'schemas', 'services', 'tui', 'types']),\n exports: CANONICAL_ROOTS,\n schemas: new Set(['schemas', 'types']),\n services: new Set(['schemas', 'services', 'types']),\n tui: new Set(['schemas', 'services', 'tui', 'types']),\n types: new Set(['types']),\n};\n\nfunction readSource(filePath: string): ts.SourceFile | null {\n if (!fs.existsSync(filePath) || !SOURCE_EXTENSIONS.has(path.extname(filePath))) return null;\n return ts.createSourceFile(filePath, fs.readFileSync(filePath, 'utf8'), ts.ScriptTarget.Latest, true);\n}\n\nfunction normalizedParts(filePath: string): string[] {\n return filePath.split(path.sep).filter(Boolean);\n}\n\nfunction sourceRoot(filePath: string): string | undefined {\n const parts = normalizedParts(filePath);\n const sourceIndex = parts.lastIndexOf('src');\n return sourceIndex >= 0 ? parts[sourceIndex + 1] : undefined;\n}\n\nfunction collectSpecifiers(sourceFile: ts.SourceFile): string[] {\n const specifiers: string[] = [];\n const visit = (node: ts.Node): void => {\n if (\n (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&\n node.moduleSpecifier &&\n ts.isStringLiteralLike(node.moduleSpecifier)\n ) {\n specifiers.push(node.moduleSpecifier.text);\n }\n if (\n ts.isCallExpression(node) &&\n node.expression.kind === ts.SyntaxKind.ImportKeyword &&\n node.arguments.length === 1 &&\n ts.isStringLiteralLike(node.arguments[0]!)\n ) {\n specifiers.push(node.arguments[0].text);\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return specifiers;\n}\n\nfunction containsRuntimeSchema(node: ts.Node): boolean {\n if (\n ts.isCallExpression(node) &&\n ((ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.expression) &&\n ['Type', 'z'].includes(node.expression.expression.text) &&\n node.expression.name.text !== 'toJSONSchema') ||\n (ts.isIdentifier(node.expression) && ['Type', 'z'].includes(node.expression.text)))\n ) {\n return true;\n }\n return node.getChildren().some(containsRuntimeSchema);\n}\n\nexport function isPureReExportModule(sourceFile: ts.SourceFile): boolean {\n return (\n sourceFile.statements.length > 0 &&\n sourceFile.statements.every(\n (statement) => ts.isExportDeclaration(statement) && statement.moduleSpecifier !== undefined,\n )\n );\n}\n\nfunction relativeImportRoot(filePath: string, specifier: string): string | undefined {\n if (!specifier.startsWith('.')) return undefined;\n return sourceRoot(path.resolve(path.dirname(filePath), specifier));\n}\n\nexport const doomFolderLayout: RuleDefinition = {\n preflight: true,\n rule: 'Doom source modules use the canonical root vocabulary, with src/exports as the public boundary',\n rationale: 'One predictable folder vocabulary makes package boundaries navigable and mechanically enforceable.',\n check(filePath) {\n const root = sourceRoot(filePath);\n if (!root || root === 'index.ts' || CANONICAL_ROOTS.has(root) || TRANSITIONAL_ROOTS.has(root)) return null;\n const sourceFile = readSource(filePath);\n if (sourceFile && isPureReExportModule(sourceFile)) return null;\n const detail = FORBIDDEN_ROOTS.has(root)\n ? `Legacy root \"${root}\" must be a forwarding wrapper during migration.`\n : `Unknown root \"${root}\" is not canonical.`;\n return `${detail} Move implementation under exports, types, schemas, services, adapters, commands, container, or tui.`;\n },\n};\n\n/** @deprecated Remove after all Doom packages enable public-export-boundary. */\nexport const compatibilityWrapperOnly: RuleDefinition = {\n preflight: true,\n rule: 'Noncanonical compatibility modules contain forwarding exports only during migration',\n rationale: 'Compatibility paths may remain public temporarily without becoming a second implementation architecture.',\n check(filePath) {\n const root = sourceRoot(filePath);\n if (!root || root === 'index.ts' || CANONICAL_ROOTS.has(root) || TRANSITIONAL_ROOTS.has(root)) return null;\n const sourceFile = readSource(filePath);\n return sourceFile && !isPureReExportModule(sourceFile)\n ? 'Noncanonical public paths must contain only re-exports from canonical modules during migration.'\n : null;\n },\n};\n\nexport const publicExportBoundary: RuleDefinition = {\n preflight: true,\n rule: 'Pure forwarding modules may exist only under src/exports',\n rationale:\n 'A single manifest-facing boundary keeps compatibility facades from becoming a parallel internal architecture.',\n check(filePath) {\n const sourceFile = readSource(filePath);\n if (!sourceFile || !isPureReExportModule(sourceFile) || sourceRoot(filePath) === 'exports') return null;\n return 'Move this public facade under src/exports and import its canonical implementation directly everywhere else.';\n },\n};\n\nexport const noInternalPublicImport: RuleDefinition = {\n preflight: true,\n rule: 'Implementation modules never import src/exports or their own package public subpaths',\n rationale:\n 'Internal code should depend on canonical implementations rather than cycling through compatibility facades.',\n check(filePath, configRoot) {\n const root = sourceRoot(filePath);\n if (!root || root === 'exports') return null;\n const sourceFile = readSource(filePath);\n if (!sourceFile) return null;\n const packageName = readPackageManifest(configRoot)?.name;\n const blocked = collectSpecifiers(sourceFile).filter((specifier) => {\n if (relativeImportRoot(filePath, specifier) === 'exports') return true;\n return packageName !== undefined && (specifier === packageName || specifier.startsWith(`${packageName}/`));\n });\n const uniqueBlocked = [...new Set(blocked)];\n return uniqueBlocked.length > 0\n ? `Implementation imports public package facades: ${uniqueBlocked.join(', ')}`\n : null;\n },\n};\n\nexport const doomLayerBoundary: RuleDefinition = {\n preflight: true,\n rule: 'Canonical Doom layers point inward through types, schemas, services, adapters, and composition roots',\n rationale: 'A small universal dependency direction prevents host and presentation concerns from leaking into policy.',\n check(filePath) {\n const root = sourceRoot(filePath);\n const allowedRoots = root ? ALLOWED_ROOT_DEPENDENCIES[root] : undefined;\n if (!root || !allowedRoots) return null;\n const sourceFile = readSource(filePath);\n if (!sourceFile || isPureReExportModule(sourceFile)) return null;\n const blocked = collectSpecifiers(sourceFile).filter((specifier) => {\n const targetRoot = relativeImportRoot(filePath, specifier);\n return targetRoot !== undefined && !allowedRoots.has(targetRoot);\n });\n const uniqueBlocked = [...new Set(blocked)];\n return uniqueBlocked.length > 0 ? `Layer imports forbidden dependencies: ${uniqueBlocked.join(', ')}` : null;\n },\n};\n\nexport const serviceBoundary: RuleDefinition = {\n preflight: true,\n rule: 'Services depend only on services, types, and schemas and never on hosts, containers, concrete adapters, or node:*',\n rationale:\n 'Host-neutral services remain independently testable and reusable when infrastructure points inward through contracts.',\n check(filePath) {\n if (sourceRoot(filePath) !== 'services') return null;\n const sourceFile = readSource(filePath);\n if (!sourceFile || isPureReExportModule(sourceFile)) return null;\n const blocked = collectSpecifiers(sourceFile).filter((specifier) => {\n if (specifier.startsWith('node:') || HOST_PACKAGES.some((packageName) => specifier.startsWith(packageName))) {\n return true;\n }\n const targetRoot = relativeImportRoot(filePath, specifier);\n return targetRoot ? EXTERNAL_IMPLEMENTATION_ROOTS.includes(targetRoot) : false;\n });\n return blocked.length > 0 ? `Service imports forbidden dependencies: ${blocked.join(', ')}` : null;\n },\n};\n\nexport const schemaPlacement: RuleDefinition = {\n preflight: true,\n rule: 'Runtime TypeBox and Zod schema construction lives under src/schemas',\n rationale:\n 'Central runtime schemas keep validation contracts discoverable while services consume schema-derived types.',\n check(filePath) {\n const root = sourceRoot(filePath);\n if (!root || root === 'schemas') return null;\n const sourceFile = readSource(filePath);\n return sourceFile && containsRuntimeSchema(sourceFile)\n ? 'Move runtime TypeBox or Zod schema construction under src/schemas and import the derived contract.'\n : null;\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./manifestEntries.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:path");r=e.__toESM(r,1);const i=`package.json`,a=`0.84.1`,o=[`@earendil-works/pi-agent-core`,`@earendil-works/pi-ai`,`@earendil-works/pi-coding-agent`,`@earendil-works/pi-tui`];function s(e){return n.existsSync(e)?n.readFileSync(e,`utf8`):null}function c(e){let t=s(e);return t?JSON.parse(t):null}const l={preflight:!0,rule:`Doom packages are public ESM packages with publish allowlists and closed, explicit exports`,rationale:`A publishable, closed package surface prevents accidental deep-import contracts and keeps host loading predictable.`,check(e){if(r.basename(e)!==i)return null;let t=c(e);if(!t)return null;let n=[];return t.private===!0&&n.push(`private: true is not allowed`),t.type!==`module`&&n.push(`type must be module`),(!t.files||t.files.length===0)&&n.push(`files publish allowlist is required`),t.publishConfig?.access!==`public`&&n.push(`publishConfig.access must be public`),(!t.exports||Object.keys(t.exports).length===0)&&n.push(`exports must be explicit`),t.exports&&Object.keys(t.exports).some(e=>e.includes(`*`))&&n.push(`wildcard exports are not allowed`),n.length>0?`Invalid Doom extension package: ${n.join(`; `)}`:null}},u={preflight:!0,rule:`Doom extension Pi peer and development dependencies must use exactly ${a}`,rationale:`Pi extension APIs are host-version-specific, so exact pins prevent runtime contract drift.`,check(e){if(r.basename(e)!==i)return null;let t=c(e);if(!t)return null;let n=o.flatMap(e=>{let n=t.peerDependencies?.[e],r=t.devDependencies?.[e];return!n&&!r||(n===void 0||n===a)&&(r===void 0||r===a)?[]:[e]});return n.length>0?`Pi dependencies must be pinned to ${a}: ${n.join(`, `)}`:null}},d={preflight:!0,rule:`Manifest-declared Pi entries remain thin host adapters and delegate implementation work`,rationale:`Thin adapters isolate Pi lifecycle wiring from testable extension behavior.`,check(e,n){let r=t.projectPath(e,n),i=r?t.sourceStem(r):null;if(!i||!t.piDiscoveryEntryStems(n).has(i))return null;let a=s(e);if(!a)return null;let o=a.split(`
|
|
2
|
+
`).length,c=/\b(class|interface)\s+\w+|registerTool\s*\(\s*\{/.test(a);return o>80||c?`Pi adapter is too broad. Move tools, services, schemas, and UI behavior into named implementation modules.`:null}},f={preflight:!0,rule:`Doom extensions must use typed protocol clients and providers instead of raw pi.events calls`,rationale:`Typed protocol runtime validation prevents silent event payload and channel drift.`,check(e){let t=s(e);return!t||e.includes(`${r.sep}doompi-extension-contracts${r.sep}`)?null:/\b(?:pi|ctx|context)\.events\.(?:emit|on)\s*\(/.test(t)?`Raw Pi event bus access is not allowed. Use @agimon-ai/doompi-extension-contracts.`:null}},p={preflight:!0,rule:`Doom protocol channel literals may only be declared in doompi-extension-contracts`,rationale:`Central channel ownership makes versioning and cross-extension discovery type-safe.`,check(e){if(![`.ts`,`.tsx`,`.mts`,`.cts`].includes(r.extname(e)))return null;let t=s(e);return!t||e.includes(`${r.sep}doompi-extension-contracts${r.sep}`)?null:/['"`]doom:[^'"`]+['"`]/.test(t)?`Move Doom protocol channel literals to @agimon-ai/doompi-extension-contracts.`:null}},m={preflight:!0,rule:`External event subscriptions must retain and invoke their disposer during shutdown`,rationale:`Pi can reload extensions in-process, so leaked listeners duplicate work and retain stale session state.`,check(e){let t=s(e);if(!t||!/\.events\.on\s*\(/.test(t))return null;let n=/(?:const|let)\s+\w*(?:dispose|unsubscribe|cleanup)\w*\s*=\s*[^;]*\.events\.on\s*\(/i.test(t),r=/['"]session_shutdown['"]/.test(t);return n&&r?null:`Retain the external subscription disposer and invoke it from session_shutdown.`}},h={preflight:!0,rule:`Consumers register semantic subagent policy and must not mutate foreign tool calls`,rationale:`The Team provider owns tool shapes and policy merging so consumers remain decoupled from implementation details.`,check(e){let t=s(e);return t&&/['"]tool_call['"]/.test(t)&&/(?:event|input)\.(?:input|params)\s*=|Object\.assign\s*\(\s*(?:event|input)/.test(t)?`Do not mutate foreign tool calls. Register typed subagent policy with the Team provider.`:null}};exports.disposeExternalSubscriptions=m,exports.doomPackageShape=l,exports.noProtocolChannelLiterals=p,exports.noRawPiEvents=f,exports.piPeerVersion=u,exports.providerOwnedPolicy=h,exports.thinPiAdapter=d;
|
|
3
|
+
//# sourceMappingURL=conventions.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conventions.cjs","names":["fs","path","projectPath","sourceStem","piDiscoveryEntryStems"],"sources":["../../src/rules/conventions.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport { piDiscoveryEntryStems, projectPath, sourceStem } from './manifestEntries.js';\n\nconst PACKAGE_MANIFEST_NAME = 'package.json';\nconst PI_VERSION = '0.84.1';\nconst PI_PACKAGES = [\n '@earendil-works/pi-agent-core',\n '@earendil-works/pi-ai',\n '@earendil-works/pi-coding-agent',\n '@earendil-works/pi-tui',\n] as const;\n\ninterface PackageManifest {\n private?: boolean;\n type?: string;\n files?: string[];\n exports?: Record<string, unknown>;\n publishConfig?: { access?: string };\n peerDependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction readText(filePath: string): string | null {\n return fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : null;\n}\n\nfunction readManifest(filePath: string): PackageManifest | null {\n const text = readText(filePath);\n return text ? (JSON.parse(text) as PackageManifest) : null;\n}\n\nexport const doomPackageShape: RuleDefinition = {\n preflight: true,\n rule: 'Doom packages are public ESM packages with publish allowlists and closed, explicit exports',\n rationale:\n 'A publishable, closed package surface prevents accidental deep-import contracts and keeps host loading predictable.',\n check(filePath) {\n if (path.basename(filePath) !== PACKAGE_MANIFEST_NAME) return null;\n const manifest = readManifest(filePath);\n if (!manifest) return null;\n const problems: string[] = [];\n if (manifest.private === true) problems.push('private: true is not allowed');\n if (manifest.type !== 'module') problems.push('type must be module');\n if (!manifest.files || manifest.files.length === 0) problems.push('files publish allowlist is required');\n if (manifest.publishConfig?.access !== 'public') problems.push('publishConfig.access must be public');\n if (!manifest.exports || Object.keys(manifest.exports).length === 0) problems.push('exports must be explicit');\n if (manifest.exports && Object.keys(manifest.exports).some((key) => key.includes('*'))) {\n problems.push('wildcard exports are not allowed');\n }\n return problems.length > 0 ? `Invalid Doom extension package: ${problems.join('; ')}` : null;\n },\n};\n\nexport const piPeerVersion: RuleDefinition = {\n preflight: true,\n rule: `Doom extension Pi peer and development dependencies must use exactly ${PI_VERSION}`,\n rationale: 'Pi extension APIs are host-version-specific, so exact pins prevent runtime contract drift.',\n check(filePath) {\n if (path.basename(filePath) !== PACKAGE_MANIFEST_NAME) return null;\n const manifest = readManifest(filePath);\n if (!manifest) return null;\n const mismatches = PI_PACKAGES.flatMap((packageName) => {\n const peer = manifest.peerDependencies?.[packageName];\n const development = manifest.devDependencies?.[packageName];\n if (!peer && !development) return [];\n const peerMatches = peer === undefined || peer === PI_VERSION;\n const developmentMatches = development === undefined || development === PI_VERSION;\n return peerMatches && developmentMatches ? [] : [packageName];\n });\n return mismatches.length > 0 ? `Pi dependencies must be pinned to ${PI_VERSION}: ${mismatches.join(', ')}` : null;\n },\n};\n\nexport const thinPiAdapter: RuleDefinition = {\n preflight: true,\n rule: 'Manifest-declared Pi entries remain thin host adapters and delegate implementation work',\n rationale: 'Thin adapters isolate Pi lifecycle wiring from testable extension behavior.',\n check(filePath, configRoot) {\n const relativePath = projectPath(filePath, configRoot);\n const stem = relativePath ? sourceStem(relativePath) : null;\n if (!stem || !piDiscoveryEntryStems(configRoot).has(stem)) return null;\n const text = readText(filePath);\n if (!text) return null;\n const lines = text.split('\\n').length;\n const ownsImplementation = /\\b(class|interface)\\s+\\w+|registerTool\\s*\\(\\s*\\{/.test(text);\n return lines > 80 || ownsImplementation\n ? 'Pi adapter is too broad. Move tools, services, schemas, and UI behavior into named implementation modules.'\n : null;\n },\n};\n\nexport const noRawPiEvents: RuleDefinition = {\n preflight: true,\n rule: 'Doom extensions must use typed protocol clients and providers instead of raw pi.events calls',\n rationale: 'Typed protocol runtime validation prevents silent event payload and channel drift.',\n check(filePath) {\n const text = readText(filePath);\n if (!text || filePath.includes(`${path.sep}doompi-extension-contracts${path.sep}`)) return null;\n return /\\b(?:pi|ctx|context)\\.events\\.(?:emit|on)\\s*\\(/.test(text)\n ? 'Raw Pi event bus access is not allowed. Use @agimon-ai/doompi-extension-contracts.'\n : null;\n },\n};\n\nexport const noProtocolChannelLiterals: RuleDefinition = {\n preflight: true,\n rule: 'Doom protocol channel literals may only be declared in doompi-extension-contracts',\n rationale: 'Central channel ownership makes versioning and cross-extension discovery type-safe.',\n check(filePath) {\n if (!['.ts', '.tsx', '.mts', '.cts'].includes(path.extname(filePath))) return null;\n const text = readText(filePath);\n if (!text || filePath.includes(`${path.sep}doompi-extension-contracts${path.sep}`)) return null;\n return /['\"`]doom:[^'\"`]+['\"`]/.test(text)\n ? 'Move Doom protocol channel literals to @agimon-ai/doompi-extension-contracts.'\n : null;\n },\n};\n\nexport const disposeExternalSubscriptions: RuleDefinition = {\n preflight: true,\n rule: 'External event subscriptions must retain and invoke their disposer during shutdown',\n rationale: 'Pi can reload extensions in-process, so leaked listeners duplicate work and retain stale session state.',\n check(filePath) {\n const text = readText(filePath);\n if (!text || !/\\.events\\.on\\s*\\(/.test(text)) return null;\n const retainsDisposer = /(?:const|let)\\s+\\w*(?:dispose|unsubscribe|cleanup)\\w*\\s*=\\s*[^;]*\\.events\\.on\\s*\\(/i.test(\n text,\n );\n const hasShutdown = /['\"]session_shutdown['\"]/.test(text);\n return retainsDisposer && hasShutdown\n ? null\n : 'Retain the external subscription disposer and invoke it from session_shutdown.';\n },\n};\n\nexport const providerOwnedPolicy: RuleDefinition = {\n preflight: true,\n rule: 'Consumers register semantic subagent policy and must not mutate foreign tool calls',\n rationale:\n 'The Team provider owns tool shapes and policy merging so consumers remain decoupled from implementation details.',\n check(filePath) {\n const text = readText(filePath);\n if (!text) return null;\n return /['\"]tool_call['\"]/.test(text) &&\n /(?:event|input)\\.(?:input|params)\\s*=|Object\\.assign\\s*\\(\\s*(?:event|input)/.test(text)\n ? 'Do not mutate foreign tool calls. Register typed subagent policy with the Team provider.'\n : null;\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RuleDefinition } from "@agimon-ai/vibe-lint";
|
|
2
|
+
//#region src/rules/conventions.d.ts
|
|
3
|
+
declare const doomPackageShape: RuleDefinition;
|
|
4
|
+
declare const piPeerVersion: RuleDefinition;
|
|
5
|
+
declare const thinPiAdapter: RuleDefinition;
|
|
6
|
+
declare const noRawPiEvents: RuleDefinition;
|
|
7
|
+
declare const noProtocolChannelLiterals: RuleDefinition;
|
|
8
|
+
declare const disposeExternalSubscriptions: RuleDefinition;
|
|
9
|
+
declare const providerOwnedPolicy: RuleDefinition;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { disposeExternalSubscriptions, doomPackageShape, noProtocolChannelLiterals, noRawPiEvents, piPeerVersion, providerOwnedPolicy, thinPiAdapter };
|
|
12
|
+
//# sourceMappingURL=conventions.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conventions.d.cts","names":[],"sources":["../../src/rules/conventions.ts"],"mappings":";;cAiCa,kBAAkB;cAsBlB,eAAe;cAoBf,eAAe;cAkBf,eAAe;cAaf,2BAA2B;cAc3B,8BAA8B;cAiB9B,qBAAqB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RuleDefinition } from "@agimon-ai/vibe-lint";
|
|
2
|
+
//#region src/rules/conventions.d.ts
|
|
3
|
+
declare const doomPackageShape: RuleDefinition;
|
|
4
|
+
declare const piPeerVersion: RuleDefinition;
|
|
5
|
+
declare const thinPiAdapter: RuleDefinition;
|
|
6
|
+
declare const noRawPiEvents: RuleDefinition;
|
|
7
|
+
declare const noProtocolChannelLiterals: RuleDefinition;
|
|
8
|
+
declare const disposeExternalSubscriptions: RuleDefinition;
|
|
9
|
+
declare const providerOwnedPolicy: RuleDefinition;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { disposeExternalSubscriptions, doomPackageShape, noProtocolChannelLiterals, noRawPiEvents, piPeerVersion, providerOwnedPolicy, thinPiAdapter };
|
|
12
|
+
//# sourceMappingURL=conventions.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conventions.d.mts","names":[],"sources":["../../src/rules/conventions.ts"],"mappings":";;cAiCa,kBAAkB;cAsBlB,eAAe;cAoBf,eAAe;cAkBf,eAAe;cAaf,2BAA2B;cAc3B,8BAA8B;cAiB9B,qBAAqB"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{piDiscoveryEntryStems as e,projectPath as t,sourceStem as n}from"./manifestEntries.mjs";import*as r from"node:fs";import*as i from"node:path";const a=`package.json`,o=`0.84.1`,s=[`@earendil-works/pi-agent-core`,`@earendil-works/pi-ai`,`@earendil-works/pi-coding-agent`,`@earendil-works/pi-tui`];function c(e){return r.existsSync(e)?r.readFileSync(e,`utf8`):null}function l(e){let t=c(e);return t?JSON.parse(t):null}const u={preflight:!0,rule:`Doom packages are public ESM packages with publish allowlists and closed, explicit exports`,rationale:`A publishable, closed package surface prevents accidental deep-import contracts and keeps host loading predictable.`,check(e){if(i.basename(e)!==a)return null;let t=l(e);if(!t)return null;let n=[];return t.private===!0&&n.push(`private: true is not allowed`),t.type!==`module`&&n.push(`type must be module`),(!t.files||t.files.length===0)&&n.push(`files publish allowlist is required`),t.publishConfig?.access!==`public`&&n.push(`publishConfig.access must be public`),(!t.exports||Object.keys(t.exports).length===0)&&n.push(`exports must be explicit`),t.exports&&Object.keys(t.exports).some(e=>e.includes(`*`))&&n.push(`wildcard exports are not allowed`),n.length>0?`Invalid Doom extension package: ${n.join(`; `)}`:null}},d={preflight:!0,rule:`Doom extension Pi peer and development dependencies must use exactly ${o}`,rationale:`Pi extension APIs are host-version-specific, so exact pins prevent runtime contract drift.`,check(e){if(i.basename(e)!==a)return null;let t=l(e);if(!t)return null;let n=s.flatMap(e=>{let n=t.peerDependencies?.[e],r=t.devDependencies?.[e];return!n&&!r||(n===void 0||n===o)&&(r===void 0||r===o)?[]:[e]});return n.length>0?`Pi dependencies must be pinned to ${o}: ${n.join(`, `)}`:null}},f={preflight:!0,rule:`Manifest-declared Pi entries remain thin host adapters and delegate implementation work`,rationale:`Thin adapters isolate Pi lifecycle wiring from testable extension behavior.`,check(r,i){let a=t(r,i),o=a?n(a):null;if(!o||!e(i).has(o))return null;let s=c(r);if(!s)return null;let l=s.split(`
|
|
2
|
+
`).length,u=/\b(class|interface)\s+\w+|registerTool\s*\(\s*\{/.test(s);return l>80||u?`Pi adapter is too broad. Move tools, services, schemas, and UI behavior into named implementation modules.`:null}},p={preflight:!0,rule:`Doom extensions must use typed protocol clients and providers instead of raw pi.events calls`,rationale:`Typed protocol runtime validation prevents silent event payload and channel drift.`,check(e){let t=c(e);return!t||e.includes(`${i.sep}doompi-extension-contracts${i.sep}`)?null:/\b(?:pi|ctx|context)\.events\.(?:emit|on)\s*\(/.test(t)?`Raw Pi event bus access is not allowed. Use @agimon-ai/doompi-extension-contracts.`:null}},m={preflight:!0,rule:`Doom protocol channel literals may only be declared in doompi-extension-contracts`,rationale:`Central channel ownership makes versioning and cross-extension discovery type-safe.`,check(e){if(![`.ts`,`.tsx`,`.mts`,`.cts`].includes(i.extname(e)))return null;let t=c(e);return!t||e.includes(`${i.sep}doompi-extension-contracts${i.sep}`)?null:/['"`]doom:[^'"`]+['"`]/.test(t)?`Move Doom protocol channel literals to @agimon-ai/doompi-extension-contracts.`:null}},h={preflight:!0,rule:`External event subscriptions must retain and invoke their disposer during shutdown`,rationale:`Pi can reload extensions in-process, so leaked listeners duplicate work and retain stale session state.`,check(e){let t=c(e);if(!t||!/\.events\.on\s*\(/.test(t))return null;let n=/(?:const|let)\s+\w*(?:dispose|unsubscribe|cleanup)\w*\s*=\s*[^;]*\.events\.on\s*\(/i.test(t),r=/['"]session_shutdown['"]/.test(t);return n&&r?null:`Retain the external subscription disposer and invoke it from session_shutdown.`}},g={preflight:!0,rule:`Consumers register semantic subagent policy and must not mutate foreign tool calls`,rationale:`The Team provider owns tool shapes and policy merging so consumers remain decoupled from implementation details.`,check(e){let t=c(e);return t&&/['"]tool_call['"]/.test(t)&&/(?:event|input)\.(?:input|params)\s*=|Object\.assign\s*\(\s*(?:event|input)/.test(t)?`Do not mutate foreign tool calls. Register typed subagent policy with the Team provider.`:null}};export{h as disposeExternalSubscriptions,u as doomPackageShape,m as noProtocolChannelLiterals,p as noRawPiEvents,d as piPeerVersion,g as providerOwnedPolicy,f as thinPiAdapter};
|
|
3
|
+
//# sourceMappingURL=conventions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conventions.mjs","names":[],"sources":["../../src/rules/conventions.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport { piDiscoveryEntryStems, projectPath, sourceStem } from './manifestEntries.js';\n\nconst PACKAGE_MANIFEST_NAME = 'package.json';\nconst PI_VERSION = '0.84.1';\nconst PI_PACKAGES = [\n '@earendil-works/pi-agent-core',\n '@earendil-works/pi-ai',\n '@earendil-works/pi-coding-agent',\n '@earendil-works/pi-tui',\n] as const;\n\ninterface PackageManifest {\n private?: boolean;\n type?: string;\n files?: string[];\n exports?: Record<string, unknown>;\n publishConfig?: { access?: string };\n peerDependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction readText(filePath: string): string | null {\n return fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : null;\n}\n\nfunction readManifest(filePath: string): PackageManifest | null {\n const text = readText(filePath);\n return text ? (JSON.parse(text) as PackageManifest) : null;\n}\n\nexport const doomPackageShape: RuleDefinition = {\n preflight: true,\n rule: 'Doom packages are public ESM packages with publish allowlists and closed, explicit exports',\n rationale:\n 'A publishable, closed package surface prevents accidental deep-import contracts and keeps host loading predictable.',\n check(filePath) {\n if (path.basename(filePath) !== PACKAGE_MANIFEST_NAME) return null;\n const manifest = readManifest(filePath);\n if (!manifest) return null;\n const problems: string[] = [];\n if (manifest.private === true) problems.push('private: true is not allowed');\n if (manifest.type !== 'module') problems.push('type must be module');\n if (!manifest.files || manifest.files.length === 0) problems.push('files publish allowlist is required');\n if (manifest.publishConfig?.access !== 'public') problems.push('publishConfig.access must be public');\n if (!manifest.exports || Object.keys(manifest.exports).length === 0) problems.push('exports must be explicit');\n if (manifest.exports && Object.keys(manifest.exports).some((key) => key.includes('*'))) {\n problems.push('wildcard exports are not allowed');\n }\n return problems.length > 0 ? `Invalid Doom extension package: ${problems.join('; ')}` : null;\n },\n};\n\nexport const piPeerVersion: RuleDefinition = {\n preflight: true,\n rule: `Doom extension Pi peer and development dependencies must use exactly ${PI_VERSION}`,\n rationale: 'Pi extension APIs are host-version-specific, so exact pins prevent runtime contract drift.',\n check(filePath) {\n if (path.basename(filePath) !== PACKAGE_MANIFEST_NAME) return null;\n const manifest = readManifest(filePath);\n if (!manifest) return null;\n const mismatches = PI_PACKAGES.flatMap((packageName) => {\n const peer = manifest.peerDependencies?.[packageName];\n const development = manifest.devDependencies?.[packageName];\n if (!peer && !development) return [];\n const peerMatches = peer === undefined || peer === PI_VERSION;\n const developmentMatches = development === undefined || development === PI_VERSION;\n return peerMatches && developmentMatches ? [] : [packageName];\n });\n return mismatches.length > 0 ? `Pi dependencies must be pinned to ${PI_VERSION}: ${mismatches.join(', ')}` : null;\n },\n};\n\nexport const thinPiAdapter: RuleDefinition = {\n preflight: true,\n rule: 'Manifest-declared Pi entries remain thin host adapters and delegate implementation work',\n rationale: 'Thin adapters isolate Pi lifecycle wiring from testable extension behavior.',\n check(filePath, configRoot) {\n const relativePath = projectPath(filePath, configRoot);\n const stem = relativePath ? sourceStem(relativePath) : null;\n if (!stem || !piDiscoveryEntryStems(configRoot).has(stem)) return null;\n const text = readText(filePath);\n if (!text) return null;\n const lines = text.split('\\n').length;\n const ownsImplementation = /\\b(class|interface)\\s+\\w+|registerTool\\s*\\(\\s*\\{/.test(text);\n return lines > 80 || ownsImplementation\n ? 'Pi adapter is too broad. Move tools, services, schemas, and UI behavior into named implementation modules.'\n : null;\n },\n};\n\nexport const noRawPiEvents: RuleDefinition = {\n preflight: true,\n rule: 'Doom extensions must use typed protocol clients and providers instead of raw pi.events calls',\n rationale: 'Typed protocol runtime validation prevents silent event payload and channel drift.',\n check(filePath) {\n const text = readText(filePath);\n if (!text || filePath.includes(`${path.sep}doompi-extension-contracts${path.sep}`)) return null;\n return /\\b(?:pi|ctx|context)\\.events\\.(?:emit|on)\\s*\\(/.test(text)\n ? 'Raw Pi event bus access is not allowed. Use @agimon-ai/doompi-extension-contracts.'\n : null;\n },\n};\n\nexport const noProtocolChannelLiterals: RuleDefinition = {\n preflight: true,\n rule: 'Doom protocol channel literals may only be declared in doompi-extension-contracts',\n rationale: 'Central channel ownership makes versioning and cross-extension discovery type-safe.',\n check(filePath) {\n if (!['.ts', '.tsx', '.mts', '.cts'].includes(path.extname(filePath))) return null;\n const text = readText(filePath);\n if (!text || filePath.includes(`${path.sep}doompi-extension-contracts${path.sep}`)) return null;\n return /['\"`]doom:[^'\"`]+['\"`]/.test(text)\n ? 'Move Doom protocol channel literals to @agimon-ai/doompi-extension-contracts.'\n : null;\n },\n};\n\nexport const disposeExternalSubscriptions: RuleDefinition = {\n preflight: true,\n rule: 'External event subscriptions must retain and invoke their disposer during shutdown',\n rationale: 'Pi can reload extensions in-process, so leaked listeners duplicate work and retain stale session state.',\n check(filePath) {\n const text = readText(filePath);\n if (!text || !/\\.events\\.on\\s*\\(/.test(text)) return null;\n const retainsDisposer = /(?:const|let)\\s+\\w*(?:dispose|unsubscribe|cleanup)\\w*\\s*=\\s*[^;]*\\.events\\.on\\s*\\(/i.test(\n text,\n );\n const hasShutdown = /['\"]session_shutdown['\"]/.test(text);\n return retainsDisposer && hasShutdown\n ? null\n : 'Retain the external subscription disposer and invoke it from session_shutdown.';\n },\n};\n\nexport const providerOwnedPolicy: RuleDefinition = {\n preflight: true,\n rule: 'Consumers register semantic subagent policy and must not mutate foreign tool calls',\n rationale:\n 'The Team provider owns tool shapes and policy merging so consumers remain decoupled from implementation details.',\n check(filePath) {\n const text = readText(filePath);\n if (!text) return null;\n return /['\"]tool_call['\"]/.test(text) &&\n /(?:event|input)\\.(?:input|params)\\s*=|Object\\.assign\\s*\\(\\s*(?:event|input)/.test(text)\n ? 'Do not mutate foreign tool calls. Register typed subagent policy with the Team provider.'\n : null;\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { compatibilityWrapperOnly, doomFolderLayout, doomLayerBoundary, noInternalPublicImport, publicExportBoundary, schemaPlacement, serviceBoundary } from "./architecture.cjs";
|
|
2
|
+
import { disposeExternalSubscriptions, doomPackageShape, noProtocolChannelLiterals, noRawPiEvents, piPeerVersion, providerOwnedPolicy, thinPiAdapter } from "./conventions.cjs";
|
|
3
|
+
import { piExtensionDefaultFactory } from "./piExtensionContract.cjs";
|
|
4
|
+
import { rules } from "./registry.cjs";
|
|
5
|
+
export { compatibilityWrapperOnly, disposeExternalSubscriptions, doomFolderLayout, doomLayerBoundary, doomPackageShape, noInternalPublicImport, noProtocolChannelLiterals, noRawPiEvents, piExtensionDefaultFactory, piPeerVersion, providerOwnedPolicy, publicExportBoundary, rules, schemaPlacement, serviceBoundary, thinPiAdapter };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { compatibilityWrapperOnly, doomFolderLayout, doomLayerBoundary, noInternalPublicImport, publicExportBoundary, schemaPlacement, serviceBoundary } from "./architecture.mjs";
|
|
2
|
+
import { disposeExternalSubscriptions, doomPackageShape, noProtocolChannelLiterals, noRawPiEvents, piPeerVersion, providerOwnedPolicy, thinPiAdapter } from "./conventions.mjs";
|
|
3
|
+
import { piExtensionDefaultFactory } from "./piExtensionContract.mjs";
|
|
4
|
+
import { rules } from "./registry.mjs";
|
|
5
|
+
export { compatibilityWrapperOnly, disposeExternalSubscriptions, doomFolderLayout, doomLayerBoundary, doomPackageShape, noInternalPublicImport, noProtocolChannelLiterals, noRawPiEvents, piExtensionDefaultFactory, piPeerVersion, providerOwnedPolicy, publicExportBoundary, rules, schemaPlacement, serviceBoundary, thinPiAdapter };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:path");n=e.__toESM(n,1);const r=/\.(?:cts|mts|ts|tsx)$/,i=/\.(?:cjs|js|mjs)$/;function a(e,t){let r=n.resolve(t),i=n.resolve(e);return i!==r&&!i.startsWith(`${r}${n.sep}`)?null:n.relative(r,i).split(n.sep).join(`/`)}function o(e){let r=n.join(e,`package.json`);if(!t.existsSync(r))return null;try{return JSON.parse(t.readFileSync(r,`utf8`))}catch{return null}}function s(e){return typeof e==`string`?i.test(e)?[e]:[]:Array.isArray(e)?e.flatMap(s):!e||typeof e!=`object`?[]:Object.values(e).flatMap(s)}function c(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\//,``);return!t.startsWith(`dist/`)||!i.test(t)?null:t.slice(5).replace(i,``)}function l(e){let t=e.replaceAll(`\\`,`/`);if(!t.startsWith(`src/`)||!r.test(t))return null;let n=t.slice(4);return(n.startsWith(`exports/`)?n.slice(8):n).replace(r,``)}function u(e){let t=o(e);return t?new Set(s(t.pi?.extensions).map(c).filter(e=>e!==null)):new Set}function d(e){let t=o(e);if(!t)return new Set;let n=s(t.pi?.extensions);if(t.exports&&typeof t.exports==`object`&&!Array.isArray(t.exports))for(let[e,r]of Object.entries(t.exports))(e===`./pi`||e.startsWith(`./extensions/`))&&n.push(...s(r));return new Set(n.map(c).filter(e=>e!==null))}exports.hostEntryStems=d,exports.piDiscoveryEntryStems=u,exports.projectPath=a,exports.readPackageManifest=o,exports.runtimeStem=c,exports.runtimeTargets=s,exports.sourceStem=l;
|
|
2
|
+
//# sourceMappingURL=manifestEntries.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifestEntries.cjs","names":["path","fs"],"sources":["../../src/rules/manifestEntries.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nconst SOURCE_EXTENSION_PATTERN = /\\.(?:cts|mts|ts|tsx)$/;\nconst RUNTIME_EXTENSION_PATTERN = /\\.(?:cjs|js|mjs)$/;\n\nexport interface DoomPackageManifest {\n name?: string;\n exports?: unknown;\n pi?: { extensions?: unknown };\n}\n\nexport function projectPath(filePath: string, configRoot: string): string | null {\n const root = path.resolve(configRoot);\n const target = path.resolve(filePath);\n if (target !== root && !target.startsWith(`${root}${path.sep}`)) return null;\n return path.relative(root, target).split(path.sep).join('/');\n}\n\nexport function readPackageManifest(configRoot: string): DoomPackageManifest | null {\n const manifestPath = path.join(configRoot, 'package.json');\n if (!fs.existsSync(manifestPath)) return null;\n try {\n return JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as DoomPackageManifest;\n } catch {\n return null;\n }\n}\n\nexport function runtimeTargets(value: unknown): string[] {\n if (typeof value === 'string') return RUNTIME_EXTENSION_PATTERN.test(value) ? [value] : [];\n if (Array.isArray(value)) return value.flatMap(runtimeTargets);\n if (!value || typeof value !== 'object') return [];\n return Object.values(value).flatMap(runtimeTargets);\n}\n\nexport function runtimeStem(target: string): string | null {\n const normalized = target.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n if (!normalized.startsWith('dist/') || !RUNTIME_EXTENSION_PATTERN.test(normalized)) return null;\n return normalized.slice('dist/'.length).replace(RUNTIME_EXTENSION_PATTERN, '');\n}\n\nexport function sourceStem(relativePath: string): string | null {\n const normalized = relativePath.replaceAll('\\\\', '/');\n if (!normalized.startsWith('src/') || !SOURCE_EXTENSION_PATTERN.test(normalized)) return null;\n const sourceRelative = normalized.slice('src/'.length);\n const entryRelative = sourceRelative.startsWith('exports/')\n ? sourceRelative.slice('exports/'.length)\n : sourceRelative;\n return entryRelative.replace(SOURCE_EXTENSION_PATTERN, '');\n}\n\nexport function piDiscoveryEntryStems(configRoot: string): Set<string> {\n const manifest = readPackageManifest(configRoot);\n if (!manifest) return new Set();\n return new Set(\n runtimeTargets(manifest.pi?.extensions)\n .map(runtimeStem)\n .filter((stem): stem is string => stem !== null),\n );\n}\n\nexport function hostEntryStems(configRoot: string): Set<string> {\n const manifest = readPackageManifest(configRoot);\n if (!manifest) return new Set();\n const targets = runtimeTargets(manifest.pi?.extensions);\n if (manifest.exports && typeof manifest.exports === 'object' && !Array.isArray(manifest.exports)) {\n for (const [subpath, target] of Object.entries(manifest.exports)) {\n if (subpath === './pi' || subpath.startsWith('./extensions/')) targets.push(...runtimeTargets(target));\n }\n }\n return new Set(targets.map(runtimeStem).filter((stem): stem is string => stem !== null));\n}\n"],"mappings":"2IAGA,MAAM,EAA2B,wBAC3B,EAA4B,oBAQlC,SAAgB,EAAY,EAAkB,EAAmC,CAC/E,IAAM,EAAOA,EAAK,QAAQ,CAAU,EAC9B,EAASA,EAAK,QAAQ,CAAQ,EAEpC,OADI,IAAW,GAAQ,CAAC,EAAO,WAAW,GAAG,IAAOA,EAAK,KAAK,EAAU,KACjEA,EAAK,SAAS,EAAM,CAAM,CAAC,CAAC,MAAMA,EAAK,GAAG,CAAC,CAAC,KAAK,GAAG,CAC7D,CAEA,SAAgB,EAAoB,EAAgD,CAClF,IAAM,EAAeA,EAAK,KAAK,EAAY,cAAc,EACzD,GAAI,CAACC,EAAG,WAAW,CAAY,EAAG,OAAO,KACzC,GAAI,CACF,OAAO,KAAK,MAAMA,EAAG,aAAa,EAAc,MAAM,CAAC,CACzD,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAAgB,EAAe,EAA0B,CAIvD,OAHI,OAAO,GAAU,SAAiB,EAA0B,KAAK,CAAK,EAAI,CAAC,CAAK,EAAI,CAAC,EACrF,MAAM,QAAQ,CAAK,EAAU,EAAM,QAAQ,CAAc,EACzD,CAAC,GAAS,OAAO,GAAU,SAAiB,CAAC,EAC1C,OAAO,OAAO,CAAK,CAAC,CAAC,QAAQ,CAAc,CACpD,CAEA,SAAgB,EAAY,EAA+B,CACzD,IAAM,EAAa,EAAO,WAAW,KAAM,GAAG,CAAC,CAAC,QAAQ,QAAS,EAAE,EAEnE,MADI,CAAC,EAAW,WAAW,OAAO,GAAK,CAAC,EAA0B,KAAK,CAAU,EAAU,KACpF,EAAW,MAAM,CAAc,CAAC,CAAC,QAAQ,EAA2B,EAAE,CAC/E,CAEA,SAAgB,EAAW,EAAqC,CAC9D,IAAM,EAAa,EAAa,WAAW,KAAM,GAAG,EACpD,GAAI,CAAC,EAAW,WAAW,MAAM,GAAK,CAAC,EAAyB,KAAK,CAAU,EAAG,OAAO,KACzF,IAAM,EAAiB,EAAW,MAAM,CAAa,EAIrD,OAHsB,EAAe,WAAW,UAAU,EACtD,EAAe,MAAM,CAAiB,EACtC,EAAA,CACiB,QAAQ,EAA0B,EAAE,CAC3D,CAEA,SAAgB,EAAsB,EAAiC,CACrE,IAAM,EAAW,EAAoB,CAAU,EAE/C,OADK,EACE,IAAI,IACT,EAAe,EAAS,IAAI,UAAU,CAAC,CACpC,IAAI,CAAW,CAAC,CAChB,OAAQ,GAAyB,IAAS,IAAI,CACnD,EALsB,IAAI,GAM5B,CAEA,SAAgB,EAAe,EAAiC,CAC9D,IAAM,EAAW,EAAoB,CAAU,EAC/C,GAAI,CAAC,EAAU,OAAO,IAAI,IAC1B,IAAM,EAAU,EAAe,EAAS,IAAI,UAAU,EACtD,GAAI,EAAS,SAAW,OAAO,EAAS,SAAY,UAAY,CAAC,MAAM,QAAQ,EAAS,OAAO,EACxF,IAAA,GAAM,CAAC,EAAS,KAAW,OAAO,QAAQ,EAAS,OAAO,GACzD,IAAY,QAAU,EAAQ,WAAW,eAAe,IAAG,EAAQ,KAAK,GAAG,EAAe,CAAM,CAAC,EAGzG,OAAO,IAAI,IAAI,EAAQ,IAAI,CAAW,CAAC,CAAC,OAAQ,GAAyB,IAAS,IAAI,CAAC,CACzF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import*as e from"node:fs";import*as t from"node:path";const n=/\.(?:cts|mts|ts|tsx)$/,r=/\.(?:cjs|js|mjs)$/;function i(e,n){let r=t.resolve(n),i=t.resolve(e);return i!==r&&!i.startsWith(`${r}${t.sep}`)?null:t.relative(r,i).split(t.sep).join(`/`)}function a(n){let r=t.join(n,`package.json`);if(!e.existsSync(r))return null;try{return JSON.parse(e.readFileSync(r,`utf8`))}catch{return null}}function o(e){return typeof e==`string`?r.test(e)?[e]:[]:Array.isArray(e)?e.flatMap(o):!e||typeof e!=`object`?[]:Object.values(e).flatMap(o)}function s(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\//,``);return!t.startsWith(`dist/`)||!r.test(t)?null:t.slice(5).replace(r,``)}function c(e){let t=e.replaceAll(`\\`,`/`);if(!t.startsWith(`src/`)||!n.test(t))return null;let r=t.slice(4);return(r.startsWith(`exports/`)?r.slice(8):r).replace(n,``)}function l(e){let t=a(e);return t?new Set(o(t.pi?.extensions).map(s).filter(e=>e!==null)):new Set}function u(e){let t=a(e);if(!t)return new Set;let n=o(t.pi?.extensions);if(t.exports&&typeof t.exports==`object`&&!Array.isArray(t.exports))for(let[e,r]of Object.entries(t.exports))(e===`./pi`||e.startsWith(`./extensions/`))&&n.push(...o(r));return new Set(n.map(s).filter(e=>e!==null))}export{u as hostEntryStems,l as piDiscoveryEntryStems,i as projectPath,a as readPackageManifest,s as runtimeStem,o as runtimeTargets,c as sourceStem};
|
|
2
|
+
//# sourceMappingURL=manifestEntries.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifestEntries.mjs","names":[],"sources":["../../src/rules/manifestEntries.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nconst SOURCE_EXTENSION_PATTERN = /\\.(?:cts|mts|ts|tsx)$/;\nconst RUNTIME_EXTENSION_PATTERN = /\\.(?:cjs|js|mjs)$/;\n\nexport interface DoomPackageManifest {\n name?: string;\n exports?: unknown;\n pi?: { extensions?: unknown };\n}\n\nexport function projectPath(filePath: string, configRoot: string): string | null {\n const root = path.resolve(configRoot);\n const target = path.resolve(filePath);\n if (target !== root && !target.startsWith(`${root}${path.sep}`)) return null;\n return path.relative(root, target).split(path.sep).join('/');\n}\n\nexport function readPackageManifest(configRoot: string): DoomPackageManifest | null {\n const manifestPath = path.join(configRoot, 'package.json');\n if (!fs.existsSync(manifestPath)) return null;\n try {\n return JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as DoomPackageManifest;\n } catch {\n return null;\n }\n}\n\nexport function runtimeTargets(value: unknown): string[] {\n if (typeof value === 'string') return RUNTIME_EXTENSION_PATTERN.test(value) ? [value] : [];\n if (Array.isArray(value)) return value.flatMap(runtimeTargets);\n if (!value || typeof value !== 'object') return [];\n return Object.values(value).flatMap(runtimeTargets);\n}\n\nexport function runtimeStem(target: string): string | null {\n const normalized = target.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n if (!normalized.startsWith('dist/') || !RUNTIME_EXTENSION_PATTERN.test(normalized)) return null;\n return normalized.slice('dist/'.length).replace(RUNTIME_EXTENSION_PATTERN, '');\n}\n\nexport function sourceStem(relativePath: string): string | null {\n const normalized = relativePath.replaceAll('\\\\', '/');\n if (!normalized.startsWith('src/') || !SOURCE_EXTENSION_PATTERN.test(normalized)) return null;\n const sourceRelative = normalized.slice('src/'.length);\n const entryRelative = sourceRelative.startsWith('exports/')\n ? sourceRelative.slice('exports/'.length)\n : sourceRelative;\n return entryRelative.replace(SOURCE_EXTENSION_PATTERN, '');\n}\n\nexport function piDiscoveryEntryStems(configRoot: string): Set<string> {\n const manifest = readPackageManifest(configRoot);\n if (!manifest) return new Set();\n return new Set(\n runtimeTargets(manifest.pi?.extensions)\n .map(runtimeStem)\n .filter((stem): stem is string => stem !== null),\n );\n}\n\nexport function hostEntryStems(configRoot: string): Set<string> {\n const manifest = readPackageManifest(configRoot);\n if (!manifest) return new Set();\n const targets = runtimeTargets(manifest.pi?.extensions);\n if (manifest.exports && typeof manifest.exports === 'object' && !Array.isArray(manifest.exports)) {\n for (const [subpath, target] of Object.entries(manifest.exports)) {\n if (subpath === './pi' || subpath.startsWith('./extensions/')) targets.push(...runtimeTargets(target));\n }\n }\n return new Set(targets.map(runtimeStem).filter((stem): stem is string => stem !== null));\n}\n"],"mappings":"sDAGA,MAAM,EAA2B,wBAC3B,EAA4B,oBAQlC,SAAgB,EAAY,EAAkB,EAAmC,CAC/E,IAAM,EAAO,EAAK,QAAQ,CAAU,EAC9B,EAAS,EAAK,QAAQ,CAAQ,EAEpC,OADI,IAAW,GAAQ,CAAC,EAAO,WAAW,GAAG,IAAO,EAAK,KAAK,EAAU,KACjE,EAAK,SAAS,EAAM,CAAM,CAAC,CAAC,MAAM,EAAK,GAAG,CAAC,CAAC,KAAK,GAAG,CAC7D,CAEA,SAAgB,EAAoB,EAAgD,CAClF,IAAM,EAAe,EAAK,KAAK,EAAY,cAAc,EACzD,GAAI,CAAC,EAAG,WAAW,CAAY,EAAG,OAAO,KACzC,GAAI,CACF,OAAO,KAAK,MAAM,EAAG,aAAa,EAAc,MAAM,CAAC,CACzD,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAAgB,EAAe,EAA0B,CAIvD,OAHI,OAAO,GAAU,SAAiB,EAA0B,KAAK,CAAK,EAAI,CAAC,CAAK,EAAI,CAAC,EACrF,MAAM,QAAQ,CAAK,EAAU,EAAM,QAAQ,CAAc,EACzD,CAAC,GAAS,OAAO,GAAU,SAAiB,CAAC,EAC1C,OAAO,OAAO,CAAK,CAAC,CAAC,QAAQ,CAAc,CACpD,CAEA,SAAgB,EAAY,EAA+B,CACzD,IAAM,EAAa,EAAO,WAAW,KAAM,GAAG,CAAC,CAAC,QAAQ,QAAS,EAAE,EAEnE,MADI,CAAC,EAAW,WAAW,OAAO,GAAK,CAAC,EAA0B,KAAK,CAAU,EAAU,KACpF,EAAW,MAAM,CAAc,CAAC,CAAC,QAAQ,EAA2B,EAAE,CAC/E,CAEA,SAAgB,EAAW,EAAqC,CAC9D,IAAM,EAAa,EAAa,WAAW,KAAM,GAAG,EACpD,GAAI,CAAC,EAAW,WAAW,MAAM,GAAK,CAAC,EAAyB,KAAK,CAAU,EAAG,OAAO,KACzF,IAAM,EAAiB,EAAW,MAAM,CAAa,EAIrD,OAHsB,EAAe,WAAW,UAAU,EACtD,EAAe,MAAM,CAAiB,EACtC,EAAA,CACiB,QAAQ,EAA0B,EAAE,CAC3D,CAEA,SAAgB,EAAsB,EAAiC,CACrE,IAAM,EAAW,EAAoB,CAAU,EAE/C,OADK,EACE,IAAI,IACT,EAAe,EAAS,IAAI,UAAU,CAAC,CACpC,IAAI,CAAW,CAAC,CAChB,OAAQ,GAAyB,IAAS,IAAI,CACnD,EALsB,IAAI,GAM5B,CAEA,SAAgB,EAAe,EAAiC,CAC9D,IAAM,EAAW,EAAoB,CAAU,EAC/C,GAAI,CAAC,EAAU,OAAO,IAAI,IAC1B,IAAM,EAAU,EAAe,EAAS,IAAI,UAAU,EACtD,GAAI,EAAS,SAAW,OAAO,EAAS,SAAY,UAAY,CAAC,MAAM,QAAQ,EAAS,OAAO,EACxF,IAAA,GAAM,CAAC,EAAS,KAAW,OAAO,QAAQ,EAAS,OAAO,GACzD,IAAY,QAAU,EAAQ,WAAW,eAAe,IAAG,EAAQ,KAAK,GAAG,EAAe,CAAM,CAAC,EAGzG,OAAO,IAAI,IAAI,EAAQ,IAAI,CAAW,CAAC,CAAC,OAAQ,GAAyB,IAAS,IAAI,CAAC,CACzF"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./manifestEntries.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("typescript");r=e.__toESM(r,1);const i=/^src\/exports\/(?:[^/]+\/)*[^/]+\.(?:cts|mts|ts|tsx)$/,a=/\.(?:cts|mts|ts|tsx)$/;function o(e){return!n.existsSync(e)||!a.test(e)?null:r.default.createSourceFile(e,n.readFileSync(e,`utf8`),r.default.ScriptTarget.Latest,!0)}function s(e){return e.statements.some(e=>{if(!r.default.isImportDeclaration(e)||!r.default.isStringLiteralLike(e.moduleSpecifier)||e.moduleSpecifier.text!==`@earendil-works/pi-coding-agent`)return!1;let t=e.importClause?.namedBindings;return t!==void 0&&r.default.isNamedImports(t)&&t.elements.some(e=>(e.propertyName??e.name).text===`ExtensionAPI`)})}function c(e,n,r){let a=t.sourceStem(e);return a&&r.has(a)?!0:i.test(e)&&s(n)}function l(e){let t={aliases:new Map,callable:new Set,imported:new Set};for(let n of e.statements){if(r.default.isFunctionDeclaration(n)&&n.name&&t.callable.add(n.name.text),r.default.isImportDeclaration(n)&&n.importClause){n.importClause.name&&t.imported.add(n.importClause.name.text);let e=n.importClause.namedBindings;if(e&&r.default.isNamedImports(e))for(let n of e.elements)t.imported.add(n.name.text)}if(r.default.isVariableStatement(n))for(let e of n.declarationList.declarations)!r.default.isIdentifier(e.name)||!e.initializer||(r.default.isArrowFunction(e.initializer)||r.default.isFunctionExpression(e.initializer)?t.callable.add(e.name.text):t.aliases.set(e.name.text,e.initializer))}return t}function u(e){let t=e;for(;r.default.isParenthesizedExpression(t)||r.default.isAsExpression(t)||r.default.isTypeAssertionExpression(t)||r.default.isSatisfiesExpression(t)||r.default.isNonNullExpression(t);)t=t.expression;return t}function d(e,t,n=new Set){let i=u(e);if(r.default.isArrowFunction(i)||r.default.isFunctionExpression(i)||r.default.isCallExpression(i))return!0;if(!r.default.isIdentifier(i))return!1;let a=i.text;if(t.callable.has(a)||t.imported.has(a))return!0;if(n.has(a))return!1;let o=t.aliases.get(a);return o?(n.add(a),d(o,t,n)):!1}function f(e){let t=l(e);return e.statements.some(e=>r.default.isFunctionDeclaration(e)&&e.modifiers?.some(e=>e.kind===r.default.SyntaxKind.DefaultKeyword)?!0:r.default.isExportAssignment(e)&&!e.isExportEquals?d(e.expression,t):!r.default.isExportDeclaration(e)||!e.exportClause||!r.default.isNamedExports(e.exportClause)?!1:e.exportClause.elements.some(n=>{if(n.name.text!=="default")return!1;if(e.moduleSpecifier)return!0;let i=(n.propertyName??n.name).text;return d(r.default.factory.createIdentifier(i),t)}))}const p={preflight:!0,rule:`Pi-loaded extension entries must expose a callable default factory export`,rationale:`Pi and DoomPi loaders invoke module.default, so a named-only factory silently leaves the requested extension inactive.`,passExamples:[`export function activate(pi: ExtensionAPI): void { /* ... */ }
|
|
2
|
+
export { activate as default };`],failExamples:[`export function activate(pi: ExtensionAPI): void { /* ... */ }`],check(e,n){let r=t.projectPath(e,n),i=o(e);return!r||!i||!c(r,i,t.hostEntryStems(n))||f(i)?null:`Pi-loaded extension entry must expose a callable default factory; named-only factories are not loaded.`}};exports.piExtensionDefaultFactory=p;
|
|
3
|
+
//# sourceMappingURL=piExtensionContract.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piExtensionContract.cjs","names":["fs","ts","sourceStem","projectPath","hostEntryStems"],"sources":["../../src/rules/piExtensionContract.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport ts from 'typescript';\nimport { hostEntryStems, projectPath, sourceStem } from './manifestEntries.js';\n\nconst PI_CODING_AGENT_PACKAGE = '@earendil-works/pi-coding-agent';\nconst SOURCE_ENTRY_PATTERN = /^src\\/exports\\/(?:[^/]+\\/)*[^/]+\\.(?:cts|mts|ts|tsx)$/;\nconst SOURCE_EXTENSION_PATTERN = /\\.(?:cts|mts|ts|tsx)$/;\n\ninterface FactoryBindings {\n aliases: Map<string, ts.Expression>;\n callable: Set<string>;\n imported: Set<string>;\n}\n\nfunction readSource(filePath: string): ts.SourceFile | null {\n if (!fs.existsSync(filePath) || !SOURCE_EXTENSION_PATTERN.test(filePath)) return null;\n return ts.createSourceFile(filePath, fs.readFileSync(filePath, 'utf8'), ts.ScriptTarget.Latest, true);\n}\n\nfunction importsExtensionApi(sourceFile: ts.SourceFile): boolean {\n return sourceFile.statements.some((statement) => {\n if (\n !ts.isImportDeclaration(statement) ||\n !ts.isStringLiteralLike(statement.moduleSpecifier) ||\n statement.moduleSpecifier.text !== PI_CODING_AGENT_PACKAGE\n ) {\n return false;\n }\n const bindings = statement.importClause?.namedBindings;\n return (\n bindings !== undefined &&\n ts.isNamedImports(bindings) &&\n bindings.elements.some((element) => (element.propertyName ?? element.name).text === 'ExtensionAPI')\n );\n });\n}\n\nfunction isHostLoadedEntry(relativePath: string, sourceFile: ts.SourceFile, declaredEntries: Set<string>): boolean {\n const stem = sourceStem(relativePath);\n if (stem && declaredEntries.has(stem)) return true;\n return SOURCE_ENTRY_PATTERN.test(relativePath) && importsExtensionApi(sourceFile);\n}\n\nfunction factoryBindings(sourceFile: ts.SourceFile): FactoryBindings {\n const bindings: FactoryBindings = { aliases: new Map(), callable: new Set(), imported: new Set() };\n for (const statement of sourceFile.statements) {\n if (ts.isFunctionDeclaration(statement) && statement.name) bindings.callable.add(statement.name.text);\n if (ts.isImportDeclaration(statement) && statement.importClause) {\n if (statement.importClause.name) bindings.imported.add(statement.importClause.name.text);\n const namedBindings = statement.importClause.namedBindings;\n if (namedBindings && ts.isNamedImports(namedBindings)) {\n for (const element of namedBindings.elements) bindings.imported.add(element.name.text);\n }\n }\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue;\n if (ts.isArrowFunction(declaration.initializer) || ts.isFunctionExpression(declaration.initializer)) {\n bindings.callable.add(declaration.name.text);\n } else {\n bindings.aliases.set(declaration.name.text, declaration.initializer);\n }\n }\n }\n return bindings;\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (\n ts.isParenthesizedExpression(current) ||\n ts.isAsExpression(current) ||\n ts.isTypeAssertionExpression(current) ||\n ts.isSatisfiesExpression(current) ||\n ts.isNonNullExpression(current)\n ) {\n current = current.expression;\n }\n return current;\n}\n\nfunction isFactoryExpression(expression: ts.Expression, bindings: FactoryBindings, seen = new Set<string>()): boolean {\n const unwrapped = unwrapExpression(expression);\n if (ts.isArrowFunction(unwrapped) || ts.isFunctionExpression(unwrapped) || ts.isCallExpression(unwrapped)) {\n return true;\n }\n if (!ts.isIdentifier(unwrapped)) return false;\n const name = unwrapped.text;\n if (bindings.callable.has(name) || bindings.imported.has(name)) return true;\n if (seen.has(name)) return false;\n const alias = bindings.aliases.get(name);\n if (!alias) return false;\n seen.add(name);\n return isFactoryExpression(alias, bindings, seen);\n}\n\nfunction hasDefaultFactory(sourceFile: ts.SourceFile): boolean {\n const bindings = factoryBindings(sourceFile);\n return sourceFile.statements.some((statement) => {\n if (\n ts.isFunctionDeclaration(statement) &&\n statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword)\n ) {\n return true;\n }\n if (ts.isExportAssignment(statement) && !statement.isExportEquals) {\n return isFactoryExpression(statement.expression, bindings);\n }\n if (!ts.isExportDeclaration(statement) || !statement.exportClause || !ts.isNamedExports(statement.exportClause)) {\n return false;\n }\n return statement.exportClause.elements.some((element) => {\n if (element.name.text !== 'default') return false;\n if (statement.moduleSpecifier) return true;\n const localName = (element.propertyName ?? element.name).text;\n return isFactoryExpression(ts.factory.createIdentifier(localName), bindings);\n });\n });\n}\n\nexport const piExtensionDefaultFactory: RuleDefinition = {\n preflight: true,\n rule: 'Pi-loaded extension entries must expose a callable default factory export',\n rationale:\n 'Pi and DoomPi loaders invoke module.default, so a named-only factory silently leaves the requested extension inactive.',\n passExamples: ['export function activate(pi: ExtensionAPI): void { /* ... */ }\\nexport { activate as default };'],\n failExamples: ['export function activate(pi: ExtensionAPI): void { /* ... */ }'],\n check(filePath, configRoot) {\n const relativePath = projectPath(filePath, configRoot);\n const sourceFile = readSource(filePath);\n if (!relativePath || !sourceFile || !isHostLoadedEntry(relativePath, sourceFile, hostEntryStems(configRoot))) {\n return null;\n }\n return hasDefaultFactory(sourceFile)\n ? null\n : 'Pi-loaded extension entry must expose a callable default factory; named-only factories are not loaded.';\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piExtensionContract.d.cts","names":[],"sources":["../../src/rules/piExtensionContract.ts"],"mappings":";;cAyHa,2BAA2B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piExtensionContract.d.mts","names":[],"sources":["../../src/rules/piExtensionContract.ts"],"mappings":";;cAyHa,2BAA2B"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{hostEntryStems as e,projectPath as t,sourceStem as n}from"./manifestEntries.mjs";import*as r from"node:fs";import i from"typescript";const a=/^src\/exports\/(?:[^/]+\/)*[^/]+\.(?:cts|mts|ts|tsx)$/,o=/\.(?:cts|mts|ts|tsx)$/;function s(e){return!r.existsSync(e)||!o.test(e)?null:i.createSourceFile(e,r.readFileSync(e,`utf8`),i.ScriptTarget.Latest,!0)}function c(e){return e.statements.some(e=>{if(!i.isImportDeclaration(e)||!i.isStringLiteralLike(e.moduleSpecifier)||e.moduleSpecifier.text!==`@earendil-works/pi-coding-agent`)return!1;let t=e.importClause?.namedBindings;return t!==void 0&&i.isNamedImports(t)&&t.elements.some(e=>(e.propertyName??e.name).text===`ExtensionAPI`)})}function l(e,t,r){let i=n(e);return i&&r.has(i)?!0:a.test(e)&&c(t)}function u(e){let t={aliases:new Map,callable:new Set,imported:new Set};for(let n of e.statements){if(i.isFunctionDeclaration(n)&&n.name&&t.callable.add(n.name.text),i.isImportDeclaration(n)&&n.importClause){n.importClause.name&&t.imported.add(n.importClause.name.text);let e=n.importClause.namedBindings;if(e&&i.isNamedImports(e))for(let n of e.elements)t.imported.add(n.name.text)}if(i.isVariableStatement(n))for(let e of n.declarationList.declarations)!i.isIdentifier(e.name)||!e.initializer||(i.isArrowFunction(e.initializer)||i.isFunctionExpression(e.initializer)?t.callable.add(e.name.text):t.aliases.set(e.name.text,e.initializer))}return t}function d(e){let t=e;for(;i.isParenthesizedExpression(t)||i.isAsExpression(t)||i.isTypeAssertionExpression(t)||i.isSatisfiesExpression(t)||i.isNonNullExpression(t);)t=t.expression;return t}function f(e,t,n=new Set){let r=d(e);if(i.isArrowFunction(r)||i.isFunctionExpression(r)||i.isCallExpression(r))return!0;if(!i.isIdentifier(r))return!1;let a=r.text;if(t.callable.has(a)||t.imported.has(a))return!0;if(n.has(a))return!1;let o=t.aliases.get(a);return o?(n.add(a),f(o,t,n)):!1}function p(e){let t=u(e);return e.statements.some(e=>i.isFunctionDeclaration(e)&&e.modifiers?.some(e=>e.kind===i.SyntaxKind.DefaultKeyword)?!0:i.isExportAssignment(e)&&!e.isExportEquals?f(e.expression,t):!i.isExportDeclaration(e)||!e.exportClause||!i.isNamedExports(e.exportClause)?!1:e.exportClause.elements.some(n=>{if(n.name.text!=="default")return!1;if(e.moduleSpecifier)return!0;let r=(n.propertyName??n.name).text;return f(i.factory.createIdentifier(r),t)}))}const m={preflight:!0,rule:`Pi-loaded extension entries must expose a callable default factory export`,rationale:`Pi and DoomPi loaders invoke module.default, so a named-only factory silently leaves the requested extension inactive.`,passExamples:[`export function activate(pi: ExtensionAPI): void { /* ... */ }
|
|
2
|
+
export { activate as default };`],failExamples:[`export function activate(pi: ExtensionAPI): void { /* ... */ }`],check(n,r){let i=t(n,r),a=s(n);return!i||!a||!l(i,a,e(r))||p(a)?null:`Pi-loaded extension entry must expose a callable default factory; named-only factories are not loaded.`}};export{m as piExtensionDefaultFactory};
|
|
3
|
+
//# sourceMappingURL=piExtensionContract.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piExtensionContract.mjs","names":[],"sources":["../../src/rules/piExtensionContract.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport ts from 'typescript';\nimport { hostEntryStems, projectPath, sourceStem } from './manifestEntries.js';\n\nconst PI_CODING_AGENT_PACKAGE = '@earendil-works/pi-coding-agent';\nconst SOURCE_ENTRY_PATTERN = /^src\\/exports\\/(?:[^/]+\\/)*[^/]+\\.(?:cts|mts|ts|tsx)$/;\nconst SOURCE_EXTENSION_PATTERN = /\\.(?:cts|mts|ts|tsx)$/;\n\ninterface FactoryBindings {\n aliases: Map<string, ts.Expression>;\n callable: Set<string>;\n imported: Set<string>;\n}\n\nfunction readSource(filePath: string): ts.SourceFile | null {\n if (!fs.existsSync(filePath) || !SOURCE_EXTENSION_PATTERN.test(filePath)) return null;\n return ts.createSourceFile(filePath, fs.readFileSync(filePath, 'utf8'), ts.ScriptTarget.Latest, true);\n}\n\nfunction importsExtensionApi(sourceFile: ts.SourceFile): boolean {\n return sourceFile.statements.some((statement) => {\n if (\n !ts.isImportDeclaration(statement) ||\n !ts.isStringLiteralLike(statement.moduleSpecifier) ||\n statement.moduleSpecifier.text !== PI_CODING_AGENT_PACKAGE\n ) {\n return false;\n }\n const bindings = statement.importClause?.namedBindings;\n return (\n bindings !== undefined &&\n ts.isNamedImports(bindings) &&\n bindings.elements.some((element) => (element.propertyName ?? element.name).text === 'ExtensionAPI')\n );\n });\n}\n\nfunction isHostLoadedEntry(relativePath: string, sourceFile: ts.SourceFile, declaredEntries: Set<string>): boolean {\n const stem = sourceStem(relativePath);\n if (stem && declaredEntries.has(stem)) return true;\n return SOURCE_ENTRY_PATTERN.test(relativePath) && importsExtensionApi(sourceFile);\n}\n\nfunction factoryBindings(sourceFile: ts.SourceFile): FactoryBindings {\n const bindings: FactoryBindings = { aliases: new Map(), callable: new Set(), imported: new Set() };\n for (const statement of sourceFile.statements) {\n if (ts.isFunctionDeclaration(statement) && statement.name) bindings.callable.add(statement.name.text);\n if (ts.isImportDeclaration(statement) && statement.importClause) {\n if (statement.importClause.name) bindings.imported.add(statement.importClause.name.text);\n const namedBindings = statement.importClause.namedBindings;\n if (namedBindings && ts.isNamedImports(namedBindings)) {\n for (const element of namedBindings.elements) bindings.imported.add(element.name.text);\n }\n }\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue;\n if (ts.isArrowFunction(declaration.initializer) || ts.isFunctionExpression(declaration.initializer)) {\n bindings.callable.add(declaration.name.text);\n } else {\n bindings.aliases.set(declaration.name.text, declaration.initializer);\n }\n }\n }\n return bindings;\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (\n ts.isParenthesizedExpression(current) ||\n ts.isAsExpression(current) ||\n ts.isTypeAssertionExpression(current) ||\n ts.isSatisfiesExpression(current) ||\n ts.isNonNullExpression(current)\n ) {\n current = current.expression;\n }\n return current;\n}\n\nfunction isFactoryExpression(expression: ts.Expression, bindings: FactoryBindings, seen = new Set<string>()): boolean {\n const unwrapped = unwrapExpression(expression);\n if (ts.isArrowFunction(unwrapped) || ts.isFunctionExpression(unwrapped) || ts.isCallExpression(unwrapped)) {\n return true;\n }\n if (!ts.isIdentifier(unwrapped)) return false;\n const name = unwrapped.text;\n if (bindings.callable.has(name) || bindings.imported.has(name)) return true;\n if (seen.has(name)) return false;\n const alias = bindings.aliases.get(name);\n if (!alias) return false;\n seen.add(name);\n return isFactoryExpression(alias, bindings, seen);\n}\n\nfunction hasDefaultFactory(sourceFile: ts.SourceFile): boolean {\n const bindings = factoryBindings(sourceFile);\n return sourceFile.statements.some((statement) => {\n if (\n ts.isFunctionDeclaration(statement) &&\n statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword)\n ) {\n return true;\n }\n if (ts.isExportAssignment(statement) && !statement.isExportEquals) {\n return isFactoryExpression(statement.expression, bindings);\n }\n if (!ts.isExportDeclaration(statement) || !statement.exportClause || !ts.isNamedExports(statement.exportClause)) {\n return false;\n }\n return statement.exportClause.elements.some((element) => {\n if (element.name.text !== 'default') return false;\n if (statement.moduleSpecifier) return true;\n const localName = (element.propertyName ?? element.name).text;\n return isFactoryExpression(ts.factory.createIdentifier(localName), bindings);\n });\n });\n}\n\nexport const piExtensionDefaultFactory: RuleDefinition = {\n preflight: true,\n rule: 'Pi-loaded extension entries must expose a callable default factory export',\n rationale:\n 'Pi and DoomPi loaders invoke module.default, so a named-only factory silently leaves the requested extension inactive.',\n passExamples: ['export function activate(pi: ExtensionAPI): void { /* ... */ }\\nexport { activate as default };'],\n failExamples: ['export function activate(pi: ExtensionAPI): void { /* ... */ }'],\n check(filePath, configRoot) {\n const relativePath = projectPath(filePath, configRoot);\n const sourceFile = readSource(filePath);\n if (!relativePath || !sourceFile || !isHostLoadedEntry(relativePath, sourceFile, hostEntryStems(configRoot))) {\n return null;\n }\n return hasDefaultFactory(sourceFile)\n ? null\n : 'Pi-loaded extension entry must expose a callable default factory; named-only factories are not loaded.';\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./architecture.cjs"),t=require("./conventions.cjs"),n=require("./piExtensionContract.cjs"),r={"doom-folder-layout":e.doomFolderLayout,"compatibility-wrapper-only":e.compatibilityWrapperOnly,"public-export-boundary":e.publicExportBoundary,"no-internal-public-import":e.noInternalPublicImport,"doom-layer-boundary":e.doomLayerBoundary,"service-boundary":e.serviceBoundary,"schema-placement":e.schemaPlacement,"doom-package-shape":t.doomPackageShape,"pi-peer-version":t.piPeerVersion,"pi-extension-default-factory":n.piExtensionDefaultFactory,"thin-pi-adapter":t.thinPiAdapter,"no-raw-pi-events":t.noRawPiEvents,"no-protocol-channel-literals":t.noProtocolChannelLiterals,"dispose-external-subscriptions":t.disposeExternalSubscriptions,"provider-owned-policy":t.providerOwnedPolicy};exports.rules=r;
|
|
2
|
+
//# sourceMappingURL=registry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.cjs","names":["doomFolderLayout","compatibilityWrapperOnly","publicExportBoundary","noInternalPublicImport","doomLayerBoundary","serviceBoundary","schemaPlacement","doomPackageShape","piPeerVersion","piExtensionDefaultFactory","thinPiAdapter","noRawPiEvents","noProtocolChannelLiterals","disposeExternalSubscriptions","providerOwnedPolicy"],"sources":["../../src/rules/registry.ts"],"sourcesContent":["import type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport {\n compatibilityWrapperOnly,\n doomFolderLayout,\n doomLayerBoundary,\n noInternalPublicImport,\n publicExportBoundary,\n schemaPlacement,\n serviceBoundary,\n} from './architecture.js';\nimport {\n disposeExternalSubscriptions,\n doomPackageShape,\n noProtocolChannelLiterals,\n noRawPiEvents,\n piPeerVersion,\n providerOwnedPolicy,\n thinPiAdapter,\n} from './conventions.js';\nimport { piExtensionDefaultFactory } from './piExtensionContract.js';\n\nexport const rules: Record<string, RuleDefinition> = {\n 'doom-folder-layout': doomFolderLayout,\n 'compatibility-wrapper-only': compatibilityWrapperOnly,\n 'public-export-boundary': publicExportBoundary,\n 'no-internal-public-import': noInternalPublicImport,\n 'doom-layer-boundary': doomLayerBoundary,\n 'service-boundary': serviceBoundary,\n 'schema-placement': schemaPlacement,\n 'doom-package-shape': doomPackageShape,\n 'pi-peer-version': piPeerVersion,\n 'pi-extension-default-factory': piExtensionDefaultFactory,\n 'thin-pi-adapter': thinPiAdapter,\n 'no-raw-pi-events': noRawPiEvents,\n 'no-protocol-channel-literals': noProtocolChannelLiterals,\n 'dispose-external-subscriptions': disposeExternalSubscriptions,\n 'provider-owned-policy': providerOwnedPolicy,\n};\n"],"mappings":"4GAqBa,EAAwC,CACnD,qBAAsBA,EAAAA,iBACtB,6BAA8BC,EAAAA,yBAC9B,yBAA0BC,EAAAA,qBAC1B,4BAA6BC,EAAAA,uBAC7B,sBAAuBC,EAAAA,kBACvB,mBAAoBC,EAAAA,gBACpB,mBAAoBC,EAAAA,gBACpB,qBAAsBC,EAAAA,iBACtB,kBAAmBC,EAAAA,cACnB,+BAAgCC,EAAAA,0BAChC,kBAAmBC,EAAAA,cACnB,mBAAoBC,EAAAA,cACpB,+BAAgCC,EAAAA,0BAChC,iCAAkCC,EAAAA,6BAClC,wBAAyBC,EAAAA,mBAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.cts","names":[],"sources":["../../src/rules/registry.ts"],"mappings":";;cAqBa,OAAO,eAAe"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.mts","names":[],"sources":["../../src/rules/registry.ts"],"mappings":";;cAqBa,OAAO,eAAe"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{compatibilityWrapperOnly as e,doomFolderLayout as t,doomLayerBoundary as n,noInternalPublicImport as r,publicExportBoundary as i,schemaPlacement as a,serviceBoundary as o}from"./architecture.mjs";import{disposeExternalSubscriptions as s,doomPackageShape as c,noProtocolChannelLiterals as l,noRawPiEvents as u,piPeerVersion as d,providerOwnedPolicy as f,thinPiAdapter as p}from"./conventions.mjs";import{piExtensionDefaultFactory as m}from"./piExtensionContract.mjs";const h={"doom-folder-layout":t,"compatibility-wrapper-only":e,"public-export-boundary":i,"no-internal-public-import":r,"doom-layer-boundary":n,"service-boundary":o,"schema-placement":a,"doom-package-shape":c,"pi-peer-version":d,"pi-extension-default-factory":m,"thin-pi-adapter":p,"no-raw-pi-events":u,"no-protocol-channel-literals":l,"dispose-external-subscriptions":s,"provider-owned-policy":f};export{h as rules};
|
|
2
|
+
//# sourceMappingURL=registry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.mjs","names":[],"sources":["../../src/rules/registry.ts"],"sourcesContent":["import type { RuleDefinition } from '@agimon-ai/vibe-lint';\nimport {\n compatibilityWrapperOnly,\n doomFolderLayout,\n doomLayerBoundary,\n noInternalPublicImport,\n publicExportBoundary,\n schemaPlacement,\n serviceBoundary,\n} from './architecture.js';\nimport {\n disposeExternalSubscriptions,\n doomPackageShape,\n noProtocolChannelLiterals,\n noRawPiEvents,\n piPeerVersion,\n providerOwnedPolicy,\n thinPiAdapter,\n} from './conventions.js';\nimport { piExtensionDefaultFactory } from './piExtensionContract.js';\n\nexport const rules: Record<string, RuleDefinition> = {\n 'doom-folder-layout': doomFolderLayout,\n 'compatibility-wrapper-only': compatibilityWrapperOnly,\n 'public-export-boundary': publicExportBoundary,\n 'no-internal-public-import': noInternalPublicImport,\n 'doom-layer-boundary': doomLayerBoundary,\n 'service-boundary': serviceBoundary,\n 'schema-placement': schemaPlacement,\n 'doom-package-shape': doomPackageShape,\n 'pi-peer-version': piPeerVersion,\n 'pi-extension-default-factory': piExtensionDefaultFactory,\n 'thin-pi-adapter': thinPiAdapter,\n 'no-raw-pi-events': noRawPiEvents,\n 'no-protocol-channel-literals': noProtocolChannelLiterals,\n 'dispose-external-subscriptions': disposeExternalSubscriptions,\n 'provider-owned-policy': providerOwnedPolicy,\n};\n"],"mappings":"ydAqBA,MAAa,EAAwC,CACnD,qBAAsB,EACtB,6BAA8B,EAC9B,yBAA0B,EAC1B,4BAA6B,EAC7B,sBAAuB,EACvB,mBAAoB,EACpB,mBAAoB,EACpB,qBAAsB,EACtB,kBAAmB,EACnB,+BAAgC,EAChC,kBAAmB,EACnB,mBAAoB,EACpB,+BAAgC,EAChC,iCAAkC,EAClC,wBAAyB,CAC3B"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agimon-ai/vibe-lint-plugin-doom-extension",
|
|
3
|
+
"version": "0.0.1-alpha.15",
|
|
4
|
+
"description": "Deterministic Vibe-Lint rules for DoomPi extension packages",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"doompi",
|
|
7
|
+
"lint",
|
|
8
|
+
"typescript",
|
|
9
|
+
"vibe-lint"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://agimon.ai",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Vuong Ngo",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"main": "./dist/index.cjs",
|
|
21
|
+
"module": "./dist/index.mjs",
|
|
22
|
+
"types": "./dist/index.d.mts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.mts",
|
|
26
|
+
"import": "./dist/index.mjs",
|
|
27
|
+
"require": "./dist/index.cjs"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"typescript": "6.0.3"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "26.1.1",
|
|
39
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
40
|
+
"tsdown": "0.22.14",
|
|
41
|
+
"vitest": "4.1.10",
|
|
42
|
+
"@agimon-ai/vibe-lint": "0.0.1-alpha.15"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@agimon-ai/vibe-lint": "0.0.1-alpha.15"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=22.19.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsdown",
|
|
52
|
+
"test": "vitest --run",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"lint": "oxlint . && oxfmt . --check",
|
|
55
|
+
"fixcode": "oxlint . --fix && oxfmt ."
|
|
56
|
+
}
|
|
57
|
+
}
|