@sayoriqwq/effect-harness 0.0.5 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -77
- package/diagnostics/effect-routes.md +6 -0
- package/diagnostics/index.md +10 -0
- package/diagnostics/tsgo-routes.md +5 -0
- package/dist/src/eslint.d.ts +57 -0
- package/dist/src/eslint.js +42 -0
- package/dist/src/eslint.js.map +1 -0
- package/dist/src/index.d.ts +2 -8
- package/dist/src/index.js +2 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/prelude.d.ts +6 -0
- package/dist/src/prelude.js +161 -0
- package/dist/src/prelude.js.map +1 -0
- package/package.json +18 -17
- package/prelude-assets/effect/managed/docs/diagnostics.md +6 -0
- package/prelude-assets/effect/managed/docs/editor-policy.md +5 -0
- package/prelude-assets/effect/managed/docs/effect-code.md +5 -0
- package/prelude-assets/effect/managed/docs/index.md +14 -0
- package/prelude-assets/effect/managed/docs/managed-surfaces.md +5 -0
- package/prelude-assets/effect/managed/docs/package-config.md +20 -0
- package/prelude-assets/effect/managed/docs/quality-policy.md +5 -0
- package/prelude-assets/effect/managed/docs/source-identity.md +5 -0
- package/prelude-assets/guidance/eslint.md +15 -0
- package/HARNESS.md +0 -66
- package/dist/bin/effect-harness.d.ts +0 -2
- package/dist/bin/effect-harness.js +0 -23
- package/dist/bin/effect-harness.js.map +0 -1
- package/dist/src/cli/Main.d.ts +0 -7
- package/dist/src/cli/Main.js +0 -45
- package/dist/src/cli/Main.js.map +0 -1
- package/dist/src/harness/Errors.d.ts +0 -24
- package/dist/src/harness/Errors.js +0 -26
- package/dist/src/harness/Errors.js.map +0 -1
- package/dist/src/harness/Guardrails.d.ts +0 -7
- package/dist/src/harness/Guardrails.js +0 -50
- package/dist/src/harness/Guardrails.js.map +0 -1
- package/dist/src/harness/Model.d.ts +0 -52
- package/dist/src/harness/Model.js +0 -170
- package/dist/src/harness/Model.js.map +0 -1
- package/dist/src/harness/ModuleSources.d.ts +0 -5
- package/dist/src/harness/ModuleSources.js +0 -47
- package/dist/src/harness/ModuleSources.js.map +0 -1
- package/dist/src/harness/ProviderDiscovery.d.ts +0 -255
- package/dist/src/harness/ProviderDiscovery.js +0 -242
- package/dist/src/harness/ProviderDiscovery.js.map +0 -1
- package/dist/src/harness/SourcePin.d.ts +0 -4
- package/dist/src/harness/SourcePin.js +0 -214
- package/dist/src/harness/SourcePin.js.map +0 -1
- package/dist/src/harness/verify/JsonFields.d.ts +0 -1
- package/dist/src/harness/verify/JsonFields.js +0 -4
- package/dist/src/harness/verify/JsonFields.js.map +0 -1
- package/dist/src/harness/verify/Pipeline.d.ts +0 -7
- package/dist/src/harness/verify/Pipeline.js +0 -55
- package/dist/src/harness/verify/Pipeline.js.map +0 -1
- package/dist/src/harness/verify/ProviderProfile.d.ts +0 -3
- package/dist/src/harness/verify/ProviderProfile.js +0 -732
- package/dist/src/harness/verify/ProviderProfile.js.map +0 -1
- package/dist/src/harness/verify/ProviderRepository.d.ts +0 -4
- package/dist/src/harness/verify/ProviderRepository.js +0 -127
- package/dist/src/harness/verify/ProviderRepository.js.map +0 -1
- package/dist/src/harness/verify/Tsgo.d.ts +0 -3
- package/dist/src/harness/verify/Tsgo.js +0 -166
- package/dist/src/harness/verify/Tsgo.js.map +0 -1
- package/dist/src/harness/verify/TsgoMetadata.d.ts +0 -4
- package/dist/src/harness/verify/TsgoMetadata.js +0 -50
- package/dist/src/harness/verify/TsgoMetadata.js.map +0 -1
- package/dist/src/harness/verify/TsgoPolicy.d.ts +0 -208
- package/dist/src/harness/verify/TsgoPolicy.js +0 -143
- package/dist/src/harness/verify/TsgoPolicy.js.map +0 -1
- package/dist/src/harness/verify/TsgoSuppressions.d.ts +0 -2
- package/dist/src/harness/verify/TsgoSuppressions.js +0 -24
- package/dist/src/harness/verify/TsgoSuppressions.js.map +0 -1
- package/dist/src/harness/verify/VerifyStage.d.ts +0 -62
- package/dist/src/harness/verify/VerifyStage.js +0 -85
- package/dist/src/harness/verify/VerifyStage.js.map +0 -1
- package/dist/src/platform/Json.d.ts +0 -4
- package/dist/src/platform/Json.js +0 -16
- package/dist/src/platform/Json.js.map +0 -1
- package/dist/src/platform/Process.d.ts +0 -6
- package/dist/src/platform/Process.js +0 -35
- package/dist/src/platform/Process.js.map +0 -1
- package/harness/code.md +0 -83
- package/harness/diagnostic-layers.md +0 -94
- package/harness/effect-routes.md +0 -50
- package/harness/feedback-loop.md +0 -156
- package/harness/index.md +0 -83
- package/harness/offcial-guide.md +0 -50
- package/harness/offcial-migrate.md +0 -220
- package/harness/source.md +0 -91
- package/harness/tsgo-routes.md +0 -58
- package/harness/tsgo.md +0 -241
- package/provider/docs/diagnostics.md +0 -48
- package/provider/docs/discovery.md +0 -130
- package/provider/docs/editor-policy.md +0 -55
- package/provider/docs/effect-code.md +0 -41
- package/provider/docs/index.md +0 -48
- package/provider/docs/managed-surfaces.md +0 -51
- package/provider/docs/package-config.md +0 -71
- package/provider/docs/quality-policy.md +0 -68
- package/provider/docs/source-identity.md +0 -48
- package/provider/effect-harness.provider.json +0 -1021
- package/provider/index.md +0 -193
- package/provider/snippets/agents.md +0 -34
package/README.md
CHANGED
|
@@ -1,83 +1,15 @@
|
|
|
1
1
|
# Effect Harness
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Effect Harness publishes a Prelude Harness Module for Effect v4 beta targets.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
2. Provider 层:描述任意 target 接入 effect-harness 时应该接收的受管能力。
|
|
9
|
-
|
|
10
|
-
本仓是自身 provider contract 的第一个 conforming repository。`pnpm verify` 证明
|
|
11
|
-
self-conformance,但本仓不会 self-materialize Prelude target surface。
|
|
12
|
-
|
|
13
|
-
通用外部仓库 pin 流程由 Partita 负责;本仓只承载 Effect/tsgo 源入口实例、Effect 基线、
|
|
14
|
-
strict tsgo policy、读取路线、provider profile、docs bundle 和 snippets。
|
|
15
|
-
|
|
16
|
-
## Harness 层
|
|
17
|
-
|
|
18
|
-
这一层只服务 `effect-harness` 自身的维护:
|
|
19
|
-
|
|
20
|
-
- `harness/offcial-guide.md`:仓内 guide 唯一真源。
|
|
21
|
-
- `harness/offcial-migrate.md`:官方 source access 与 LSP/tsgo 阶段的本仓实现说明。
|
|
22
|
-
- `harness/feedback-loop.md`:第二阶段 Codex feedback loop 和统一 verify pipeline。
|
|
23
|
-
- `harness/diagnostic-layers.md`:tsgo diagnostics、ESLint 和 harness guardrails 的分层职责。
|
|
24
|
-
- `repos/effect/`:已 pin 的官方 Effect 源码,只供 agent 读取参考。
|
|
25
|
-
- `repos/effect.subtree.json`:Partita 管理的 GitHub subtree pin 契约,是 Effect 源入口唯一真源。
|
|
26
|
-
- `harness/effect-routes.md`:agent 读取 `repos/effect/` 的路线表。
|
|
27
|
-
- `repos/tsgo/`:已 pin 的 `Effect-TS/tsgo` 源码,只供 agent 读取参考。
|
|
28
|
-
- `repos/tsgo.subtree.json`:Partita 管理的 GitHub subtree pin 契约,是 tsgo 源入口真源。
|
|
29
|
-
- `harness/tsgo.md`:strict tsgo ADR、policy、rule map 和 upgrade loop。
|
|
30
|
-
- `harness/tsgo-routes.md`:agent 读取 `repos/tsgo/` 的路线表。
|
|
31
|
-
- `src/`:本仓最小验证器,只验证 provider 仓自身边界。
|
|
32
|
-
|
|
33
|
-
## Provider 层
|
|
34
|
-
|
|
35
|
-
这一层不是本仓直接散落脚本来维护目标项目,而是提供结构化 provider profile 和 target-facing
|
|
36
|
-
模板:
|
|
37
|
-
|
|
38
|
-
- delivery modes:区分 internal harness、provider artifact reference 和 exported harness。
|
|
39
|
-
- self-conformance:声明本仓只验证自己符合 exported harness,不生成 `.prelude/**`。
|
|
40
|
-
- provider contract:`provider/effect-harness.provider.json` 声明 package/config contributions、
|
|
41
|
-
docs bundle、snippets、source identity 和 self-conformance。
|
|
42
|
-
- provider profile:声明 target 应该接收的 managed surfaces。
|
|
43
|
-
- provider record:记录接入的 `effect-harness` profile、artifact 与 source identity。
|
|
44
|
-
- provider discovery:通过 `effect-harness provider-discover` 输出 machine-readable provider envelope。
|
|
45
|
-
- package 基线:维护 `effect`、`@effect/platform-node`、`@effect/tsgo`、
|
|
46
|
-
`@effect/language-service` 等版本约束。
|
|
47
|
-
- `tsconfig.json` 指针:维护 strict `@effect/language-service` 插件。
|
|
48
|
-
- 诊断路径:目标项目以 `tsgo --noEmit` 作为主要 Effect 诊断路径,warning 和 suggestion 也参与
|
|
49
|
-
hard gate。
|
|
50
|
-
- docs bundle:维护 target 可读的 Effect 编码、诊断和 source identity 文档。
|
|
51
|
-
- snippets:维护 target 可引用的 agent instruction snippet。
|
|
52
|
-
|
|
53
|
-
目标项目不接收 `repos/effect/`、`repos/tsgo/`、subtree contracts、`.codex/skills`、目标 runtime
|
|
54
|
-
模板、反馈入口、`.effect-harness.json` 或 effect-harness 管理的 `AGENTS.md` 管理块。
|
|
55
|
-
|
|
56
|
-
`effect-harness` 本仓也不接收 `.prelude/**`。这些路径只属于 Prelude 在真实 target 中的
|
|
57
|
-
materialization 和 maintain lifecycle。
|
|
58
|
-
|
|
59
|
-
## 职责边界
|
|
60
|
-
|
|
61
|
-
- Partita:通用外部源入口 pin/status/update/verify。
|
|
62
|
-
- effect-harness:Effect/tsgo 源入口实例、路线表、baseline、provider profile、受管模板、本仓验证。
|
|
63
|
-
- Prelude:消费 provider profile,并维护 target lifecycle、provider record、目标项目落地生成、
|
|
64
|
-
drift/verify/maintain。
|
|
65
|
-
|
|
66
|
-
## 验证命令
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
pnpm install
|
|
70
|
-
pnpm verify
|
|
5
|
+
```ts
|
|
6
|
+
import effectHarnessEslintConfig from '@sayoriqwq/effect-harness/eslint'
|
|
7
|
+
import { harnessModule } from '@sayoriqwq/effect-harness/prelude'
|
|
71
8
|
```
|
|
72
9
|
|
|
73
|
-
|
|
74
|
-
|
|
10
|
+
`harnessModule` plans a complete `effect/managed/**` documentation tree, a
|
|
11
|
+
bounded root agent-routing block, TypeScript/editor configuration, direct
|
|
12
|
+
package requirements, checks, and target-state Issues. Planning is read-only.
|
|
75
13
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
[harness/feedback-loop.md](./harness/feedback-loop.md)。更新 source entries 前先读
|
|
79
|
-
[harness/source.md](./harness/source.md)。agent 需要读取 pinned Effect 源码时先读
|
|
80
|
-
[harness/effect-routes.md](./harness/effect-routes.md)。agent 需要调整 strict tsgo policy 或读取
|
|
81
|
-
tsgo source 时,先读 [harness/tsgo.md](./harness/tsgo.md) 和
|
|
82
|
-
[harness/tsgo-routes.md](./harness/tsgo-routes.md)。修改 provider contribution、docs bundle 或
|
|
83
|
-
snippets 前先读 [provider/index.md](./provider/index.md)。
|
|
14
|
+
`effect/feedback/**` is target-owned. Pinned Effect and tsgo sources are
|
|
15
|
+
Artifact-internal diagnostics and are not normal target assets.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Effect source route
|
|
2
|
+
|
|
3
|
+
For an exceptional Effect API diagnosis, read `../repos/effect/LLMS.md` first,
|
|
4
|
+
then inspect the relevant package under `../repos/effect/packages/`. These
|
|
5
|
+
files are Artifact-internal references; normal target code imports installed
|
|
6
|
+
packages instead.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Artifact-internal source diagnostics
|
|
2
|
+
|
|
3
|
+
This directory routes exceptional diagnosis into the pinned Effect and tsgo
|
|
4
|
+
source trees shipped inside this npm Artifact. It is not part of the normal
|
|
5
|
+
`effect/managed/**` Target bundle.
|
|
6
|
+
|
|
7
|
+
- [Effect source route](./effect-routes.md)
|
|
8
|
+
- [tsgo source route](./tsgo-routes.md)
|
|
9
|
+
- `../repos/effect.subtree.json` and `../repos/tsgo.subtree.json` identify
|
|
10
|
+
the exact pinned source entries.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable Effect guardrails for a target-owned ESLint flat config.
|
|
3
|
+
*
|
|
4
|
+
* Targets import this value from `@sayoriqwq/effect-harness/eslint`; Prelude
|
|
5
|
+
* intentionally never rewrites executable config files.
|
|
6
|
+
*/
|
|
7
|
+
declare const effectHarnessEslintConfig: readonly [{
|
|
8
|
+
readonly name: "effect-harness/guardrails";
|
|
9
|
+
readonly rules: {
|
|
10
|
+
readonly 'no-restricted-imports': readonly ["error", {
|
|
11
|
+
readonly paths: readonly [{
|
|
12
|
+
readonly name: "node:test";
|
|
13
|
+
readonly message: "Use @effect/vitest for Effect test entries.";
|
|
14
|
+
}, {
|
|
15
|
+
readonly name: "@effect/cli";
|
|
16
|
+
readonly message: "Use effect/unstable/cli for Effect v4 beta.";
|
|
17
|
+
}];
|
|
18
|
+
readonly patterns: readonly [{
|
|
19
|
+
readonly group: readonly ["@effect/cli/*"];
|
|
20
|
+
readonly message: "Use effect/unstable/cli for Effect v4 beta.";
|
|
21
|
+
}, {
|
|
22
|
+
readonly group: readonly ["repos/effect/**", "**/repos/effect/**"];
|
|
23
|
+
readonly message: "Import installed packages, never pinned source trees.";
|
|
24
|
+
}, {
|
|
25
|
+
readonly group: readonly ["repos/tsgo/**", "**/repos/tsgo/**"];
|
|
26
|
+
readonly message: "Use tsgo through its installed package.";
|
|
27
|
+
}];
|
|
28
|
+
}];
|
|
29
|
+
readonly 'no-restricted-syntax': readonly ["error", {
|
|
30
|
+
readonly selector: "MemberExpression[object.name=\"Context\"][property.name=\"Tag\"]";
|
|
31
|
+
readonly message: "Use Context.Service for Effect v4 services.";
|
|
32
|
+
}, {
|
|
33
|
+
readonly selector: "MemberExpression[object.name=\"Effect\"][property.name=/^(catchAllCause|ignore|serviceOption)$/]";
|
|
34
|
+
readonly message: "Use the Effect-native safer pattern.";
|
|
35
|
+
}];
|
|
36
|
+
};
|
|
37
|
+
}, {
|
|
38
|
+
readonly name: "effect-harness/tests";
|
|
39
|
+
readonly files: readonly ["tests/**/*.test.{js,mjs,ts}"];
|
|
40
|
+
readonly rules: {
|
|
41
|
+
readonly 'no-restricted-imports': readonly ["error", {
|
|
42
|
+
readonly paths: readonly [{
|
|
43
|
+
readonly name: "node:test";
|
|
44
|
+
readonly message: "Use @effect/vitest.";
|
|
45
|
+
}, {
|
|
46
|
+
readonly name: "vitest";
|
|
47
|
+
readonly importNames: readonly ["describe", "it", "test"];
|
|
48
|
+
readonly message: "Use @effect/vitest Effect entries.";
|
|
49
|
+
}];
|
|
50
|
+
}];
|
|
51
|
+
readonly 'no-restricted-syntax': readonly ["error", {
|
|
52
|
+
readonly selector: "CallExpression[callee.name=\"it\"]";
|
|
53
|
+
readonly message: "Use it.effect, it.live, or layer from @effect/vitest.";
|
|
54
|
+
}];
|
|
55
|
+
};
|
|
56
|
+
}];
|
|
57
|
+
export default effectHarnessEslintConfig;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable Effect guardrails for a target-owned ESLint flat config.
|
|
3
|
+
*
|
|
4
|
+
* Targets import this value from `@sayoriqwq/effect-harness/eslint`; Prelude
|
|
5
|
+
* intentionally never rewrites executable config files.
|
|
6
|
+
*/
|
|
7
|
+
const effectHarnessEslintConfig = [
|
|
8
|
+
{
|
|
9
|
+
name: 'effect-harness/guardrails',
|
|
10
|
+
rules: {
|
|
11
|
+
'no-restricted-imports': [
|
|
12
|
+
'error',
|
|
13
|
+
{
|
|
14
|
+
paths: [
|
|
15
|
+
{ name: 'node:test', message: 'Use @effect/vitest for Effect test entries.' },
|
|
16
|
+
{ name: '@effect/cli', message: 'Use effect/unstable/cli for Effect v4 beta.' },
|
|
17
|
+
],
|
|
18
|
+
patterns: [
|
|
19
|
+
{ group: ['@effect/cli/*'], message: 'Use effect/unstable/cli for Effect v4 beta.' },
|
|
20
|
+
{ group: ['repos/effect/**', '**/repos/effect/**'], message: 'Import installed packages, never pinned source trees.' },
|
|
21
|
+
{ group: ['repos/tsgo/**', '**/repos/tsgo/**'], message: 'Use tsgo through its installed package.' },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
'no-restricted-syntax': [
|
|
26
|
+
'error',
|
|
27
|
+
{ selector: 'MemberExpression[object.name="Context"][property.name="Tag"]', message: 'Use Context.Service for Effect v4 services.' },
|
|
28
|
+
{ selector: 'MemberExpression[object.name="Effect"][property.name=/^(catchAllCause|ignore|serviceOption)$/]', message: 'Use the Effect-native safer pattern.' },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'effect-harness/tests',
|
|
34
|
+
files: ['tests/**/*.test.{js,mjs,ts}'],
|
|
35
|
+
rules: {
|
|
36
|
+
'no-restricted-imports': ['error', { paths: [{ name: 'node:test', message: 'Use @effect/vitest.' }, { name: 'vitest', importNames: ['describe', 'it', 'test'], message: 'Use @effect/vitest Effect entries.' }] }],
|
|
37
|
+
'no-restricted-syntax': ['error', { selector: 'CallExpression[callee.name="it"]', message: 'Use it.effect, it.live, or layer from @effect/vitest.' }],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
export default effectHarnessEslintConfig;
|
|
42
|
+
//# sourceMappingURL=eslint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eslint.js","sourceRoot":"","sources":["../../src/eslint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,yBAAyB,GAAG;IAChC;QACE,IAAI,EAAE,2BAA2B;QACjC,KAAK,EAAE;YACL,uBAAuB,EAAE;gBACvB,OAAO;gBACP;oBACE,KAAK,EAAE;wBACL,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,6CAA6C,EAAE;wBAC7E,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,6CAA6C,EAAE;qBAChF;oBACD,QAAQ,EAAE;wBACR,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,6CAA6C,EAAE;wBACpF,EAAE,KAAK,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,EAAE,OAAO,EAAE,uDAAuD,EAAE;wBACtH,EAAE,KAAK,EAAE,CAAC,eAAe,EAAE,kBAAkB,CAAC,EAAE,OAAO,EAAE,yCAAyC,EAAE;qBACrG;iBACF;aACF;YACD,sBAAsB,EAAE;gBACtB,OAAO;gBACP,EAAE,QAAQ,EAAE,8DAA8D,EAAE,OAAO,EAAE,6CAA6C,EAAE;gBACpI,EAAE,QAAQ,EAAE,gGAAgG,EAAE,OAAO,EAAE,sCAAsC,EAAE;aAChK;SACF;KACF;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,CAAC,6BAA6B,CAAC;QACtC,KAAK,EAAE;YACL,uBAAuB,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,EAAE,CAAC;YAClN,sBAAsB,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,kCAAkC,EAAE,OAAO,EAAE,uDAAuD,EAAE,CAAC;SACtJ;KACF;CACO,CAAA;AAEV,eAAe,yBAAyB,CAAA","sourcesContent":["/**\n * Composable Effect guardrails for a target-owned ESLint flat config.\n *\n * Targets import this value from `@sayoriqwq/effect-harness/eslint`; Prelude\n * intentionally never rewrites executable config files.\n */\nconst effectHarnessEslintConfig = [\n {\n name: 'effect-harness/guardrails',\n rules: {\n 'no-restricted-imports': [\n 'error',\n {\n paths: [\n { name: 'node:test', message: 'Use @effect/vitest for Effect test entries.' },\n { name: '@effect/cli', message: 'Use effect/unstable/cli for Effect v4 beta.' },\n ],\n patterns: [\n { group: ['@effect/cli/*'], message: 'Use effect/unstable/cli for Effect v4 beta.' },\n { group: ['repos/effect/**', '**/repos/effect/**'], message: 'Import installed packages, never pinned source trees.' },\n { group: ['repos/tsgo/**', '**/repos/tsgo/**'], message: 'Use tsgo through its installed package.' },\n ],\n },\n ],\n 'no-restricted-syntax': [\n 'error',\n { selector: 'MemberExpression[object.name=\"Context\"][property.name=\"Tag\"]', message: 'Use Context.Service for Effect v4 services.' },\n { selector: 'MemberExpression[object.name=\"Effect\"][property.name=/^(catchAllCause|ignore|serviceOption)$/]', message: 'Use the Effect-native safer pattern.' },\n ],\n },\n },\n {\n name: 'effect-harness/tests',\n files: ['tests/**/*.test.{js,mjs,ts}'],\n rules: {\n 'no-restricted-imports': ['error', { paths: [{ name: 'node:test', message: 'Use @effect/vitest.' }, { name: 'vitest', importNames: ['describe', 'it', 'test'], message: 'Use @effect/vitest Effect entries.' }] }],\n 'no-restricted-syntax': ['error', { selector: 'CallExpression[callee.name=\"it\"]', message: 'Use it.effect, it.live, or layer from @effect/vitest.' }],\n },\n },\n] as const\n\nexport default effectHarnessEslintConfig\n"]}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export type { ProviderDiscovery, ProviderDiscoveryFailure, ProviderDiscoveryFailureInput, };
|
|
4
|
-
export { classifyProviderDiscoveryFailure, discoverProvider, resolvePackageArtifactRoot, };
|
|
5
|
-
export interface DiscoverProviderArtifactOptions {
|
|
6
|
-
readonly artifactRoot?: string;
|
|
7
|
-
}
|
|
8
|
-
export declare function discoverProviderArtifact(options?: DiscoverProviderArtifactOptions): Promise<ProviderDiscovery>;
|
|
1
|
+
/** The Harness Module is deliberately available only through `./prelude`. */
|
|
2
|
+
export {};
|
package/dist/src/index.js
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { Effect, Layer } from 'effect';
|
|
4
|
-
import { classifyProviderDiscoveryFailure, discoverProvider, resolvePackageArtifactRoot, } from "./harness/ProviderDiscovery.js";
|
|
5
|
-
export { classifyProviderDiscoveryFailure, discoverProvider, resolvePackageArtifactRoot, };
|
|
6
|
-
export function discoverProviderArtifact(options = {}) {
|
|
7
|
-
const artifactRoot = options.artifactRoot ?? resolvePackageArtifactRoot(fileURLToPath(import.meta.url));
|
|
8
|
-
return runWithNodeServices(discoverProvider(artifactRoot));
|
|
9
|
-
}
|
|
10
|
-
function runWithNodeServices(effect) {
|
|
11
|
-
return Effect.runPromise(Effect.scoped(Effect.gen(function* () {
|
|
12
|
-
const context = yield* Layer.build(NodeServices.layer);
|
|
13
|
-
return yield* Effect.promise(() => Effect.runPromiseWith(context)(effect));
|
|
14
|
-
})));
|
|
15
|
-
}
|
|
1
|
+
/** The Harness Module is deliberately available only through `./prelude`. */
|
|
2
|
+
export {};
|
|
16
3
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,OAAO,EAAE,CAAA","sourcesContent":["/** The Harness Module is deliberately available only through `./prelude`. */\nexport {}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const harnessModule: import("@sayoriqwq/prelude-contract").HarnessModule<import("effect/Schema").Struct.ReadonlySide<{
|
|
2
|
+
readonly _tag: import("effect/Schema").tag<"ObservationError">;
|
|
3
|
+
readonly operation: import("effect/Schema").Literals<readonly ["readBytes", "readText", "readDirectory", "readPackageManifest"]>;
|
|
4
|
+
readonly path: import("effect/Schema").String;
|
|
5
|
+
readonly message: import("effect/Schema").String;
|
|
6
|
+
}, "Type">>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { defineHarnessModule, MODULE_PROTOCOL_V1, PRELUDE_V1_SUPPORTED_FEATURES, } from '@sayoriqwq/prelude-contract';
|
|
2
|
+
import { Effect } from 'effect';
|
|
3
|
+
import * as TypeScript from 'typescript';
|
|
4
|
+
const effectLanguageServicePlugin = {
|
|
5
|
+
name: '@effect/language-service',
|
|
6
|
+
diagnostics: true,
|
|
7
|
+
includeSuggestionsInTsc: true,
|
|
8
|
+
ignoreEffectSuggestionsInTscExitCode: false,
|
|
9
|
+
ignoreEffectWarningsInTscExitCode: false,
|
|
10
|
+
ignoreEffectErrorsInTscExitCode: false,
|
|
11
|
+
};
|
|
12
|
+
const routingBlock = `## Effect Harness\n\nFor Effect application, test, package, TypeScript, editor, or lint changes, read \`effect/managed/docs/index.md\` first. For ESLint or package-config repair, read \`effect/managed/docs/package-config.md\`; Antfu v9 integrations use its \`antfu().append(...effectHarness)\` form. Keep \`effect/feedback/**\` target-owned. Use installed Effect packages; never import pinned source diagnostics.\n`;
|
|
13
|
+
function eslintIntegrationIssue(content) {
|
|
14
|
+
if (typeof content === 'string') {
|
|
15
|
+
if (hasEffectHarnessEslintComposition(content)) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return [{
|
|
20
|
+
id: 'effect.eslint.integration',
|
|
21
|
+
summary: 'Target ESLint config does not compose Effect Harness guardrails',
|
|
22
|
+
detail: 'The target-owned eslint.config.mjs must import and include @sayoriqwq/effect-harness/eslint.',
|
|
23
|
+
evidence: content === undefined ? 'eslint.config.mjs is absent.' : 'eslint.config.mjs does not reference the stable Effect Harness ESLint export.',
|
|
24
|
+
guidance: 'prelude-assets/guidance/eslint.md',
|
|
25
|
+
}];
|
|
26
|
+
}
|
|
27
|
+
function hasEffectHarnessEslintComposition(content) {
|
|
28
|
+
const source = TypeScript.createSourceFile('eslint.config.mjs', content, TypeScript.ScriptTarget.Latest, false, TypeScript.ScriptKind.JS);
|
|
29
|
+
let antfuBinding = '';
|
|
30
|
+
for (const statement of source.statements) {
|
|
31
|
+
if (TypeScript.isImportDeclaration(statement)
|
|
32
|
+
&& TypeScript.isStringLiteral(statement.moduleSpecifier)
|
|
33
|
+
&& statement.moduleSpecifier.text === '@antfu/eslint-config') {
|
|
34
|
+
antfuBinding = statement.importClause?.name?.text ?? '';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const statement of source.statements) {
|
|
38
|
+
if (!TypeScript.isImportDeclaration(statement)
|
|
39
|
+
|| !TypeScript.isStringLiteral(statement.moduleSpecifier)
|
|
40
|
+
|| statement.moduleSpecifier.text !== '@sayoriqwq/effect-harness/eslint') {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const binding = statement.importClause?.name?.text ?? '';
|
|
44
|
+
if (binding.length > 0 && composesEslintBinding(source, binding, antfuBinding)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
function composesEslintBinding(source, binding, antfuBinding) {
|
|
51
|
+
return source.statements.some((statement) => {
|
|
52
|
+
if (TypeScript.isExportAssignment(statement) === false)
|
|
53
|
+
return false;
|
|
54
|
+
if (statement.isExportEquals === true)
|
|
55
|
+
return false;
|
|
56
|
+
if (TypeScript.isArrayLiteralExpression(statement.expression)) {
|
|
57
|
+
const spreadsEffectConfig = statement.expression.elements.some(element => TypeScript.isSpreadElement(element)
|
|
58
|
+
&& TypeScript.isIdentifier(element.expression)
|
|
59
|
+
&& element.expression.text === binding);
|
|
60
|
+
return spreadsEffectConfig && !spreadsAntfuCall(statement.expression, antfuBinding);
|
|
61
|
+
}
|
|
62
|
+
return appendsEffectConfigToAntfu(statement.expression, binding, antfuBinding);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function spreadsAntfuCall(expression, antfuBinding) {
|
|
66
|
+
return antfuBinding.length > 0 && expression.elements.some(element => TypeScript.isSpreadElement(element)
|
|
67
|
+
&& TypeScript.isCallExpression(element.expression)
|
|
68
|
+
&& TypeScript.isIdentifier(element.expression.expression)
|
|
69
|
+
&& element.expression.expression.text === antfuBinding);
|
|
70
|
+
}
|
|
71
|
+
function appendsEffectConfigToAntfu(expression, effectBinding, antfuBinding) {
|
|
72
|
+
if (antfuBinding.length === 0 || !TypeScript.isCallExpression(expression))
|
|
73
|
+
return false;
|
|
74
|
+
const append = expression.expression;
|
|
75
|
+
if (!TypeScript.isPropertyAccessExpression(append) || append.name.text !== 'append')
|
|
76
|
+
return false;
|
|
77
|
+
if (!TypeScript.isCallExpression(append.expression)
|
|
78
|
+
|| !TypeScript.isIdentifier(append.expression.expression)
|
|
79
|
+
|| append.expression.expression.text !== antfuBinding) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return expression.arguments.some(argument => TypeScript.isSpreadElement(argument)
|
|
83
|
+
&& TypeScript.isIdentifier(argument.expression)
|
|
84
|
+
&& argument.expression.text === effectBinding);
|
|
85
|
+
}
|
|
86
|
+
export const harnessModule = defineHarnessModule({
|
|
87
|
+
descriptor: {
|
|
88
|
+
harnessId: 'effect-harness',
|
|
89
|
+
protocolVersion: MODULE_PROTOCOL_V1,
|
|
90
|
+
requiredFeatures: PRELUDE_V1_SUPPORTED_FEATURES,
|
|
91
|
+
},
|
|
92
|
+
plan: context => Effect.gen(function* () {
|
|
93
|
+
const eslintConfig = yield* context.target.readText('eslint.config.mjs');
|
|
94
|
+
return {
|
|
95
|
+
outputs: [
|
|
96
|
+
{
|
|
97
|
+
kind: 'ManagedTree',
|
|
98
|
+
id: 'effect.managed',
|
|
99
|
+
sourceRoot: 'prelude-assets/effect/managed',
|
|
100
|
+
targetRoot: 'effect/managed',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
kind: 'ManagedBlock',
|
|
104
|
+
id: 'effect.agent-routing',
|
|
105
|
+
path: 'AGENTS.md',
|
|
106
|
+
blockId: 'effect-harness-routing',
|
|
107
|
+
content: routingBlock,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
kind: 'JsonKeyedItem',
|
|
111
|
+
id: 'effect.tsconfig.language-service',
|
|
112
|
+
path: 'tsconfig.json',
|
|
113
|
+
collectionPointer: '/compilerOptions/plugins',
|
|
114
|
+
keyField: 'name',
|
|
115
|
+
keyValue: '@effect/language-service',
|
|
116
|
+
item: effectLanguageServicePlugin,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
kind: 'JsonValue',
|
|
120
|
+
id: 'effect.vscode.auto-import-exclude',
|
|
121
|
+
path: '.vscode/settings.json',
|
|
122
|
+
pointer: '/typescript.preferences.autoImportFileExcludePatterns',
|
|
123
|
+
value: ['repos/**'],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
kind: 'JsonValue',
|
|
127
|
+
id: 'effect.vscode.javascript-auto-import-exclude',
|
|
128
|
+
path: '.vscode/settings.json',
|
|
129
|
+
pointer: '/javascript.preferences.autoImportFileExcludePatterns',
|
|
130
|
+
value: ['repos/**'],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
kind: 'JsonValue',
|
|
134
|
+
id: 'effect.zed.auto-import-exclude',
|
|
135
|
+
path: '.zed/settings.json',
|
|
136
|
+
pointer: '/lsp/typescript-language-server/initialization_options/preferences/autoImportFileExcludePatterns',
|
|
137
|
+
value: ['repos/**'],
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
requirements: [
|
|
141
|
+
{ id: 'effect.runtime', packageRoot: context.integration.packageRoot, packageName: 'effect', range: '4.0.0-beta.92', section: 'dependencies' },
|
|
142
|
+
{ id: 'effect.platform-node', packageRoot: context.integration.packageRoot, packageName: '@effect/platform-node', range: '4.0.0-beta.92', section: 'dependencies' },
|
|
143
|
+
{ id: 'effect.vitest', packageRoot: context.integration.packageRoot, packageName: '@effect/vitest', range: '4.0.0-beta.92', section: 'devDependencies' },
|
|
144
|
+
{ id: 'effect.tsgo', packageRoot: context.integration.packageRoot, packageName: '@effect/tsgo', range: '0.15.0', section: 'devDependencies' },
|
|
145
|
+
{ id: 'effect.language-service', packageRoot: context.integration.packageRoot, packageName: '@effect/language-service', range: '0.86.2', section: 'devDependencies' },
|
|
146
|
+
{ id: 'effect.native-typescript', packageRoot: context.integration.packageRoot, packageName: '@typescript/native-preview', range: '7.0.0-dev.20260630.1', section: 'devDependencies' },
|
|
147
|
+
{ id: 'effect.eslint', packageRoot: context.integration.packageRoot, packageName: 'eslint', range: '^10.3.0', section: 'devDependencies' },
|
|
148
|
+
{ id: 'effect.antfu-eslint-config', packageRoot: context.integration.packageRoot, packageName: '@antfu/eslint-config', range: '^9.0.0', section: 'devDependencies' },
|
|
149
|
+
{ id: 'effect.vitest-runner', packageRoot: context.integration.packageRoot, packageName: 'vitest', range: '^4.1.8', section: 'devDependencies' },
|
|
150
|
+
{ id: 'effect.typescript', packageRoot: context.integration.packageRoot, packageName: 'typescript', range: '^6.0.3', section: 'devDependencies' },
|
|
151
|
+
],
|
|
152
|
+
checks: [
|
|
153
|
+
{ id: 'effect.typecheck', summary: 'Run strict Effect diagnostics', packageRoot: context.integration.packageRoot, argv: ['pnpm', 'typecheck'] },
|
|
154
|
+
{ id: 'effect.lint', summary: 'Run Effect lint guardrails', packageRoot: context.integration.packageRoot, argv: ['pnpm', 'lint', '--max-warnings', '0'] },
|
|
155
|
+
{ id: 'effect.verify', summary: 'Run Effect domain verification', packageRoot: context.integration.packageRoot, argv: ['pnpm', 'verify'] },
|
|
156
|
+
],
|
|
157
|
+
issues: eslintIntegrationIssue(eslintConfig),
|
|
158
|
+
};
|
|
159
|
+
}),
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=prelude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prelude.js","sourceRoot":"","sources":["../../src/prelude.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineHarnessModule,\n MODULE_PROTOCOL_V1,\n PRELUDE_V1_SUPPORTED_FEATURES,\n} from '@sayoriqwq/prelude-contract'\nimport { Effect } from 'effect'\nimport * as TypeScript from 'typescript'\n\nconst effectLanguageServicePlugin = {\n name: '@effect/language-service',\n diagnostics: true,\n includeSuggestionsInTsc: true,\n ignoreEffectSuggestionsInTscExitCode: false,\n ignoreEffectWarningsInTscExitCode: false,\n ignoreEffectErrorsInTscExitCode: false,\n}\n\nconst routingBlock = `## Effect Harness\\n\\nFor Effect application, test, package, TypeScript, editor, or lint changes, read \\`effect/managed/docs/index.md\\` first. For ESLint or package-config repair, read \\`effect/managed/docs/package-config.md\\`; Antfu v9 integrations use its \\`antfu().append(...effectHarness)\\` form. Keep \\`effect/feedback/**\\` target-owned. Use installed Effect packages; never import pinned source diagnostics.\\n`\n\nfunction eslintIntegrationIssue(content: string | undefined) {\n if (typeof content === 'string') {\n if (hasEffectHarnessEslintComposition(content)) {\n return []\n }\n }\n\n return [{\n id: 'effect.eslint.integration',\n summary: 'Target ESLint config does not compose Effect Harness guardrails',\n detail: 'The target-owned eslint.config.mjs must import and include @sayoriqwq/effect-harness/eslint.',\n evidence: content === undefined ? 'eslint.config.mjs is absent.' : 'eslint.config.mjs does not reference the stable Effect Harness ESLint export.',\n guidance: 'prelude-assets/guidance/eslint.md',\n }] as const\n}\n\nfunction hasEffectHarnessEslintComposition(content: string): boolean {\n const source = TypeScript.createSourceFile(\n 'eslint.config.mjs',\n content,\n TypeScript.ScriptTarget.Latest,\n false,\n TypeScript.ScriptKind.JS,\n )\n\n let antfuBinding = ''\n for (const statement of source.statements) {\n if (\n TypeScript.isImportDeclaration(statement)\n && TypeScript.isStringLiteral(statement.moduleSpecifier)\n && statement.moduleSpecifier.text === '@antfu/eslint-config'\n ) {\n antfuBinding = statement.importClause?.name?.text ?? ''\n }\n }\n\n for (const statement of source.statements) {\n if (\n !TypeScript.isImportDeclaration(statement)\n || !TypeScript.isStringLiteral(statement.moduleSpecifier)\n || statement.moduleSpecifier.text !== '@sayoriqwq/effect-harness/eslint'\n ) {\n continue\n }\n\n const binding = statement.importClause?.name?.text ?? ''\n if (binding.length > 0 && composesEslintBinding(source, binding, antfuBinding)) {\n return true\n }\n }\n\n return false\n}\n\nfunction composesEslintBinding(\n source: TypeScript.SourceFile,\n binding: string,\n antfuBinding: string,\n): boolean {\n return source.statements.some((statement) => {\n if (TypeScript.isExportAssignment(statement) === false)\n return false\n\n if (statement.isExportEquals === true)\n return false\n\n if (TypeScript.isArrayLiteralExpression(statement.expression)) {\n const spreadsEffectConfig = statement.expression.elements.some(element =>\n TypeScript.isSpreadElement(element)\n && TypeScript.isIdentifier(element.expression)\n && element.expression.text === binding)\n return spreadsEffectConfig && !spreadsAntfuCall(statement.expression, antfuBinding)\n }\n\n return appendsEffectConfigToAntfu(statement.expression, binding, antfuBinding)\n })\n}\n\nfunction spreadsAntfuCall(expression: TypeScript.ArrayLiteralExpression, antfuBinding: string): boolean {\n return antfuBinding.length > 0 && expression.elements.some(element =>\n TypeScript.isSpreadElement(element)\n && TypeScript.isCallExpression(element.expression)\n && TypeScript.isIdentifier(element.expression.expression)\n && element.expression.expression.text === antfuBinding)\n}\n\nfunction appendsEffectConfigToAntfu(\n expression: TypeScript.Expression,\n effectBinding: string,\n antfuBinding: string,\n): boolean {\n if (antfuBinding.length === 0 || !TypeScript.isCallExpression(expression))\n return false\n\n const append = expression.expression\n if (!TypeScript.isPropertyAccessExpression(append) || append.name.text !== 'append')\n return false\n\n if (\n !TypeScript.isCallExpression(append.expression)\n || !TypeScript.isIdentifier(append.expression.expression)\n || append.expression.expression.text !== antfuBinding\n ) {\n return false\n }\n\n return expression.arguments.some(argument =>\n TypeScript.isSpreadElement(argument)\n && TypeScript.isIdentifier(argument.expression)\n && argument.expression.text === effectBinding)\n}\n\nexport const harnessModule = defineHarnessModule({\n descriptor: {\n harnessId: 'effect-harness',\n protocolVersion: MODULE_PROTOCOL_V1,\n requiredFeatures: PRELUDE_V1_SUPPORTED_FEATURES,\n },\n plan: context => Effect.gen(function* () {\n const eslintConfig = yield* context.target.readText('eslint.config.mjs')\n return {\n outputs: [\n {\n kind: 'ManagedTree' as const,\n id: 'effect.managed',\n sourceRoot: 'prelude-assets/effect/managed',\n targetRoot: 'effect/managed',\n },\n {\n kind: 'ManagedBlock' as const,\n id: 'effect.agent-routing',\n path: 'AGENTS.md',\n blockId: 'effect-harness-routing',\n content: routingBlock,\n },\n {\n kind: 'JsonKeyedItem' as const,\n id: 'effect.tsconfig.language-service',\n path: 'tsconfig.json',\n collectionPointer: '/compilerOptions/plugins',\n keyField: 'name',\n keyValue: '@effect/language-service',\n item: effectLanguageServicePlugin,\n },\n {\n kind: 'JsonValue' as const,\n id: 'effect.vscode.auto-import-exclude',\n path: '.vscode/settings.json',\n pointer: '/typescript.preferences.autoImportFileExcludePatterns',\n value: ['repos/**'],\n },\n {\n kind: 'JsonValue' as const,\n id: 'effect.vscode.javascript-auto-import-exclude',\n path: '.vscode/settings.json',\n pointer: '/javascript.preferences.autoImportFileExcludePatterns',\n value: ['repos/**'],\n },\n {\n kind: 'JsonValue' as const,\n id: 'effect.zed.auto-import-exclude',\n path: '.zed/settings.json',\n pointer: '/lsp/typescript-language-server/initialization_options/preferences/autoImportFileExcludePatterns',\n value: ['repos/**'],\n },\n ],\n requirements: [\n { id: 'effect.runtime', packageRoot: context.integration.packageRoot, packageName: 'effect', range: '4.0.0-beta.92', section: 'dependencies' as const },\n { id: 'effect.platform-node', packageRoot: context.integration.packageRoot, packageName: '@effect/platform-node', range: '4.0.0-beta.92', section: 'dependencies' as const },\n { id: 'effect.vitest', packageRoot: context.integration.packageRoot, packageName: '@effect/vitest', range: '4.0.0-beta.92', section: 'devDependencies' as const },\n { id: 'effect.tsgo', packageRoot: context.integration.packageRoot, packageName: '@effect/tsgo', range: '0.15.0', section: 'devDependencies' as const },\n { id: 'effect.language-service', packageRoot: context.integration.packageRoot, packageName: '@effect/language-service', range: '0.86.2', section: 'devDependencies' as const },\n { id: 'effect.native-typescript', packageRoot: context.integration.packageRoot, packageName: '@typescript/native-preview', range: '7.0.0-dev.20260630.1', section: 'devDependencies' as const },\n { id: 'effect.eslint', packageRoot: context.integration.packageRoot, packageName: 'eslint', range: '^10.3.0', section: 'devDependencies' as const },\n { id: 'effect.antfu-eslint-config', packageRoot: context.integration.packageRoot, packageName: '@antfu/eslint-config', range: '^9.0.0', section: 'devDependencies' as const },\n { id: 'effect.vitest-runner', packageRoot: context.integration.packageRoot, packageName: 'vitest', range: '^4.1.8', section: 'devDependencies' as const },\n { id: 'effect.typescript', packageRoot: context.integration.packageRoot, packageName: 'typescript', range: '^6.0.3', section: 'devDependencies' as const },\n ],\n checks: [\n { id: 'effect.typecheck', summary: 'Run strict Effect diagnostics', packageRoot: context.integration.packageRoot, argv: ['pnpm', 'typecheck'] },\n { id: 'effect.lint', summary: 'Run Effect lint guardrails', packageRoot: context.integration.packageRoot, argv: ['pnpm', 'lint', '--max-warnings', '0'] },\n { id: 'effect.verify', summary: 'Run Effect domain verification', packageRoot: context.integration.packageRoot, argv: ['pnpm', 'verify'] },\n ],\n issues: eslintIntegrationIssue(eslintConfig),\n }\n }),\n})\n"]}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sayoriqwq/effect-harness",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public",
|
|
8
8
|
"registry": "https://registry.npmjs.org/"
|
|
9
9
|
},
|
|
10
|
-
"description": "Effect v4 beta
|
|
10
|
+
"description": "Effect v4 beta Prelude Harness Module.",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
@@ -17,21 +17,25 @@
|
|
|
17
17
|
".": {
|
|
18
18
|
"types": "./dist/src/index.d.ts",
|
|
19
19
|
"import": "./dist/src/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./prelude": {
|
|
22
|
+
"types": "./dist/src/prelude.d.ts",
|
|
23
|
+
"import": "./dist/src/prelude.js"
|
|
24
|
+
},
|
|
25
|
+
"./eslint": {
|
|
26
|
+
"types": "./dist/src/eslint.d.ts",
|
|
27
|
+
"import": "./dist/src/eslint.js"
|
|
20
28
|
}
|
|
21
29
|
},
|
|
22
30
|
"main": "dist/src/index.js",
|
|
23
31
|
"types": "dist/src/index.d.ts",
|
|
24
|
-
"bin": {
|
|
25
|
-
"effect-harness": "dist/bin/effect-harness.js"
|
|
26
|
-
},
|
|
27
32
|
"files": [
|
|
28
|
-
"
|
|
29
|
-
"README.md",
|
|
33
|
+
"diagnostics",
|
|
30
34
|
"dist",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"repos",
|
|
35
|
+
"prelude-assets",
|
|
36
|
+
"repos/effect",
|
|
34
37
|
"repos/effect.subtree.json",
|
|
38
|
+
"repos/tsgo",
|
|
35
39
|
"repos/tsgo.subtree.json"
|
|
36
40
|
],
|
|
37
41
|
"engines": {
|
|
@@ -39,6 +43,7 @@
|
|
|
39
43
|
},
|
|
40
44
|
"dependencies": {
|
|
41
45
|
"@effect/platform-node": "4.0.0-beta.92",
|
|
46
|
+
"@sayoriqwq/prelude-contract": "0.1.0",
|
|
42
47
|
"effect": "4.0.0-beta.92",
|
|
43
48
|
"typescript": "^6.0.3"
|
|
44
49
|
},
|
|
@@ -55,17 +60,13 @@
|
|
|
55
60
|
},
|
|
56
61
|
"scripts": {
|
|
57
62
|
"build": "tsc --project tsconfig.build.json",
|
|
58
|
-
"dev": "pnpm build
|
|
59
|
-
"effect:verify": "node bin/effect-harness.ts provider-verify --harness .",
|
|
63
|
+
"dev": "pnpm build",
|
|
60
64
|
"knip": "knip",
|
|
61
65
|
"lint": "eslint",
|
|
62
66
|
"lint:fix": "eslint --fix",
|
|
63
|
-
"
|
|
64
|
-
"source:update": "npx --yes @sayoriqwq/partita pin update --root . --contract repos/effect.subtree.json --name effect --prefix repos/effect --dry-run && npx --yes @sayoriqwq/partita pin update --root . --contract repos/tsgo.subtree.json --name tsgo --prefix repos/tsgo --dry-run",
|
|
65
|
-
"source:verify": "npx --yes @sayoriqwq/partita pin verify --root . --contract repos/effect.subtree.json --name effect --prefix repos/effect && npx --yes @sayoriqwq/partita pin verify --root . --contract repos/tsgo.subtree.json --name tsgo --prefix repos/tsgo",
|
|
66
|
-
"test": "vitest run tests/*.test.ts",
|
|
67
|
+
"test": "pnpm build && vitest run tests/*.test.ts",
|
|
67
68
|
"typecheck": "tsgo --noEmit",
|
|
68
69
|
"typecheck:tsc": "tsc --noEmit",
|
|
69
|
-
"verify": "
|
|
70
|
+
"verify": "pnpm typecheck && pnpm test && pnpm lint && pnpm knip"
|
|
70
71
|
}
|
|
71
72
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Diagnostics
|
|
2
|
+
|
|
3
|
+
Run `effect-tsgo patch` to prepare the backend and `tsgo --noEmit` for primary
|
|
4
|
+
Effect diagnostics. The language-service plugin treats errors, warnings,
|
|
5
|
+
suggestions, and messages as a zero-tolerance gate. Do not suppress or weaken
|
|
6
|
+
the configured policy to evade diagnostics.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Effect managed guidance
|
|
2
|
+
|
|
3
|
+
This directory is the complete Effect Harness managed documentation bundle.
|
|
4
|
+
It is directly maintained by the Artifact and does not require a sibling
|
|
5
|
+
source checkout.
|
|
6
|
+
|
|
7
|
+
- Read [effect-code.md](./effect-code.md) before changing Effect code or tests.
|
|
8
|
+
- Read [diagnostics.md](./diagnostics.md) before changing packages or TypeScript.
|
|
9
|
+
- Read [editor-policy.md](./editor-policy.md) before changing editor settings.
|
|
10
|
+
- Read [package-config.md](./package-config.md) before configuration work.
|
|
11
|
+
- Read [quality-policy.md](./quality-policy.md) before verification work.
|
|
12
|
+
|
|
13
|
+
Pinned Effect and tsgo repositories are Artifact-internal source diagnostics.
|
|
14
|
+
They are never projected here. `effect/feedback/**` is target-owned.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Package and TypeScript configuration
|
|
2
|
+
|
|
3
|
+
Direct requirements cover the Effect runtime, Node platform, Effect Vitest,
|
|
4
|
+
tsgo, language service, native TypeScript backend, ESLint, Antfu config, and
|
|
5
|
+
Vitest. The named language-service plugin is structurally merged by its name.
|
|
6
|
+
|
|
7
|
+
## Antfu v9 ESLint composition
|
|
8
|
+
|
|
9
|
+
`@antfu/eslint-config` v9 returns a `FlatConfigComposer`, not an iterable
|
|
10
|
+
array. Compose the stable Effect Harness export through `append`:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
import antfu from '@antfu/eslint-config'
|
|
14
|
+
import effectHarness from '@sayoriqwq/effect-harness/eslint'
|
|
15
|
+
|
|
16
|
+
export default antfu().append(...effectHarness)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Do not use `export default [...antfu(), ...effectHarness]`; it fails before
|
|
20
|
+
ESLint can lint because the Antfu composer is not iterable.
|