@orkestrel/scaffold 0.0.107 → 0.0.109
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/dist/agents/skills/orkestrel-dispatch/scripts/bench.js +326 -91
- package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +110 -14
- package/dist/agents/skills/orkestrel-dispatch/scripts/chain.js +280 -0
- package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +188 -26
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +142 -43
- package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +240 -62
- package/dist/agents/skills/orkestrel-dispatch/scripts/patch.js +323 -0
- package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +169 -32
- package/dist/agents/skills/orkestrel-dispatch/scripts/sweep.js +368 -27
- package/dist/agents/skills/orkestrel-falsify/scripts/mutate.js +560 -0
- package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +1052 -205
- package/dist/agents/skills/orkestrel-harden/scripts/measure.js +361 -0
- package/dist/agents/skills/orkestrel-harden/scripts/titles.js +455 -80
- package/dist/agents/skills/orkestrel-parallel/scripts/cases.js +327 -0
- package/dist/agents/skills/orkestrel-publish/scripts/compare.js +298 -51
- package/dist/agents/skills/orkestrel-publish/scripts/pins.js +170 -13
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +956 -191
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +707 -112
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +235 -41
- package/dist/agents/skills/orkestrel-scout/scripts/map.js +341 -54
- package/dist/agents/templates/brief.md +1 -1
- package/dist/bin/main.js +51 -46
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +26 -20
- package/dist/host/agents/orchestration.md +98 -58
- package/dist/host/agents/platforms/posix.md +15 -0
- package/dist/host/agents/platforms/windows.md +37 -0
- package/dist/host/agents/skills/orkestrel-align/SKILL.md +10 -13
- package/dist/host/agents/skills/orkestrel-align/references/fleet.md +4 -10
- package/dist/host/agents/skills/orkestrel-align/references/integration.md +1 -1
- package/dist/host/agents/skills/orkestrel-build/SKILL.md +16 -48
- package/dist/host/agents/skills/orkestrel-build/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +19 -16
- package/dist/host/agents/skills/orkestrel-debrief/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +15 -28
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +5 -6
- package/dist/host/agents/skills/orkestrel-debrief/references/retention.md +12 -14
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +36 -24
- package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +14 -11
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/bench.ts +366 -75
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +126 -16
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/chain.ts +323 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +220 -31
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +176 -33
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +294 -59
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/patch.ts +401 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +199 -34
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/sweep.ts +428 -27
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +10 -8
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +1 -5
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +1 -1
- package/dist/host/agents/skills/orkestrel-falsify/scripts/mutate.ts +701 -0
- package/dist/host/agents/skills/orkestrel-harden/SKILL.md +16 -12
- package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +23 -81
- package/dist/host/agents/skills/orkestrel-harden/references/centralization.md +4 -5
- package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -0
- package/dist/host/agents/skills/orkestrel-harden/references/document.md +33 -0
- package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +6 -3
- package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +8 -4
- package/dist/host/agents/skills/orkestrel-harden/references/research.md +2 -0
- package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +1272 -279
- package/dist/host/agents/skills/orkestrel-harden/scripts/measure.ts +425 -0
- package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +603 -98
- package/dist/host/agents/skills/orkestrel-journey/SKILL.md +75 -98
- package/dist/host/agents/skills/orkestrel-journey/references/captures.md +54 -17
- package/dist/host/agents/skills/orkestrel-journey/references/decide.md +1 -20
- package/dist/host/agents/skills/orkestrel-journey/references/layer.md +21 -31
- package/dist/host/agents/skills/orkestrel-journey/references/styles.md +1 -1
- package/dist/host/agents/skills/orkestrel-parallel/SKILL.md +91 -30
- package/dist/host/agents/skills/orkestrel-parallel/agents/openai.yaml +2 -2
- package/dist/host/agents/skills/orkestrel-parallel/references/claude.md +34 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/codex.md +29 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/cursor.md +29 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/t3.md +31 -0
- package/dist/host/agents/skills/orkestrel-parallel/scripts/cases.ts +389 -0
- package/dist/host/agents/skills/orkestrel-polish/SKILL.md +16 -20
- package/dist/host/agents/skills/orkestrel-polish/references/capture-harness.md +16 -26
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +12 -26
- package/dist/host/agents/skills/orkestrel-publish/agents/openai.yaml +2 -2
- package/dist/host/agents/skills/orkestrel-publish/references/adopt.md +23 -0
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +4 -4
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +12 -10
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +20 -25
- package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +348 -59
- package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +202 -22
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1061 -191
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +812 -140
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +280 -38
- package/dist/host/agents/skills/orkestrel-scout/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +428 -70
- package/dist/host/agents/templates/brief.md +1 -1
- package/dist/host/agents/transports/claude-cli.md +3 -3
- package/dist/host/agents/transports/codex.md +3 -8
- package/dist/host/agents/transports/cursor.md +2 -3
- package/dist/host/claude/AGENTS.md +7 -10
- package/dist/host/claude/agents/analyst.md +3 -3
- package/dist/host/claude/agents/astra.md +3 -3
- package/dist/host/claude/agents/builder.md +1 -1
- package/dist/host/claude/agents/checker.md +1 -1
- package/dist/host/claude/agents/distiller.md +1 -1
- package/dist/host/claude/agents/grok.md +1 -1
- package/dist/host/claude/agents/opus.md +2 -2
- package/dist/host/claude/agents/orkestrel.md +57 -90
- package/dist/host/claude/agents/researcher.md +1 -1
- package/dist/host/claude/agents/reviewer.md +4 -0
- package/dist/host/claude/agents/scout.md +1 -1
- package/dist/host/claude/agents/verifier.md +1 -1
- package/dist/host/claude/rules/application.md +14 -21
- package/dist/host/claude/rules/architecture.md +34 -44
- package/dist/host/claude/rules/browser.md +3 -4
- package/dist/host/claude/rules/campaign.md +55 -0
- package/dist/host/claude/rules/documentation.md +26 -11
- package/dist/host/claude/rules/names.md +9 -4
- package/dist/host/claude/rules/patterns.md +6 -7
- package/dist/host/claude/rules/portability.md +2 -3
- package/dist/host/claude/rules/quality.md +4 -5
- package/dist/host/claude/rules/styles.md +2 -2
- package/dist/host/claude/rules/tests.md +57 -114
- package/dist/host/claude/rules/typescript.md +8 -10
- package/dist/host/claude/rules/workspace.md +21 -19
- package/dist/host/claude/rules/writing.md +3 -3
- package/dist/host/claude/skills/orkestrel-dispatch/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-harden/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-parallel/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-publish/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-scout/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +9 -3
- package/dist/host/codex/agents/astra.toml +3 -4
- package/dist/host/codex/agents/builder.toml +1 -1
- package/dist/host/codex/agents/opus.toml +3 -4
- package/dist/host/codex/agents/orkestrel.toml +1 -1
- package/dist/host/codex/agents/researcher.toml +2 -2
- package/dist/host/codex/agents/verifier.toml +1 -1
- package/dist/host/codex/config.toml +3 -3
- package/dist/host/configs/helpers.ts +21 -1
- package/dist/host/configs/policy.ts +405 -16
- package/dist/host/cursor/rules/orchestration.mdc +1 -0
- package/dist/host/dotfiles/oxlintrc.json +141 -5
- package/dist/host/guides/agent.md +111 -134
- package/dist/host/guides/capture.md +801 -0
- package/dist/host/guides/probe.md +27 -8
- package/dist/host/guides/scaffold.md +152 -19
- package/dist/host/guides/study.md +534 -440
- package/dist/host/guides/test.md +111 -44
- package/dist/host/manifest.json +199 -242
- package/dist/host/tests/config.test.ts +1558 -219
- package/dist/host/tests/policy.test.ts +127 -1
- package/dist/host/tests/setupPolicy.ts +1389 -39
- package/dist/src/core/index.cjs +239 -87
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +123 -39
- package/dist/src/core/index.d.ts +123 -39
- package/dist/src/core/index.js +234 -86
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +20 -27
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js +21 -28
- package/dist/src/server/index.js.map +1 -1
- package/package.json +11 -11
- package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +0 -283
- package/dist/host/agents/skills/orkestrel-dispatch/references/bench.md +0 -25
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +0 -333
- package/dist/host/agents/skills/orkestrel-parallel/references/harnesses.md +0 -19
- package/dist/host/guides/supervisor.md +0 -4890
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
name = "verifier"
|
|
2
2
|
description = "Independent gate runner that runs the exact commands the dispatch names, scoped first, and reports exit-code truth with exact failure excerpts without fixing anything."
|
|
3
3
|
model = "gpt-6-luna"
|
|
4
|
-
model_reasoning_effort = "
|
|
4
|
+
model_reasoning_effort = "low"
|
|
5
5
|
sandbox_mode = "workspace-write"
|
|
6
6
|
developer_instructions = """
|
|
7
7
|
Run the requested gates and report their results. Write only the evidence artifacts and the declared
|
|
@@ -15,9 +15,9 @@ files you touch; Codex does not load them for you. Follow a skill under .agents/
|
|
|
15
15
|
trigger fires.
|
|
16
16
|
|
|
17
17
|
Use the role mapping and continuation rules in .agents/orchestration.md. Before using native or
|
|
18
|
-
T3 collaboration, read .agents/skills/orkestrel-parallel/references/
|
|
19
|
-
mechanics
|
|
20
|
-
capability
|
|
18
|
+
T3 collaboration, read .agents/skills/orkestrel-parallel/references/codex.md and t3.md for the
|
|
19
|
+
channel mechanics, retained identifiers, and quirks, and read the installed tool descriptions
|
|
20
|
+
before relying on a capability those pages name. .agents/platforms/ owns the host shell.
|
|
21
21
|
|
|
22
22
|
Hooks: .codex/hooks.json runs the orkestrel-dispatch sweep script (node
|
|
23
23
|
.agents/skills/orkestrel-dispatch/scripts/sweep.ts --report) on SessionStart and git diff --check
|
|
@@ -756,6 +756,26 @@ export function readCompilerOutput(compiler: string, args: readonly string[]): s
|
|
|
756
756
|
return result.stdout ?? ''
|
|
757
757
|
}
|
|
758
758
|
|
|
759
|
+
/**
|
|
760
|
+
* Resolves the TypeScript command from its exported package manifest.
|
|
761
|
+
* @param path - The module or manifest path whose installation supplies TypeScript.
|
|
762
|
+
* @returns The absolute compiler command path on TypeScript 6 and 7.
|
|
763
|
+
* @throws An error when the package declares no `bin.tsc` command.
|
|
764
|
+
*/
|
|
765
|
+
export function resolveCompiler(path: string): string {
|
|
766
|
+
const load = createRequire(path)
|
|
767
|
+
const manifest = load.resolve('typescript/package.json')
|
|
768
|
+
const declared: unknown = load(manifest)
|
|
769
|
+
if (typeof declared !== 'object' || declared === null || !('bin' in declared)) {
|
|
770
|
+
throw new Error('The TypeScript package declares no bin.tsc command')
|
|
771
|
+
}
|
|
772
|
+
const bin = declared.bin
|
|
773
|
+
if (typeof bin !== 'object' || bin === null || !('tsc' in bin) || typeof bin.tsc !== 'string') {
|
|
774
|
+
throw new Error('The TypeScript package declares no bin.tsc command')
|
|
775
|
+
}
|
|
776
|
+
return resolvePath(dirname(manifest), bin.tsc)
|
|
777
|
+
}
|
|
778
|
+
|
|
759
779
|
/**
|
|
760
780
|
* Parses a `tsc --showConfig` reading into the compiler scope a face's roll-up requires.
|
|
761
781
|
*
|
|
@@ -886,7 +906,7 @@ export function declarationRollup(options: DeclarationRollupOptions): Plugin {
|
|
|
886
906
|
)
|
|
887
907
|
}
|
|
888
908
|
const load = createRequire(import.meta.url)
|
|
889
|
-
const compiler =
|
|
909
|
+
const compiler = resolveCompiler(import.meta.url)
|
|
890
910
|
const scope = parseProjectScope(
|
|
891
911
|
readCompilerOutput(compiler, ['--showConfig', '-p', options.project]),
|
|
892
912
|
options.project,
|
|
@@ -12,8 +12,20 @@ export interface PolicyExpression extends PolicyNode {
|
|
|
12
12
|
readonly key?: PolicyExpression
|
|
13
13
|
readonly id?: PolicyExpression | null
|
|
14
14
|
readonly method?: boolean
|
|
15
|
-
readonly kind?:
|
|
15
|
+
readonly kind?:
|
|
16
|
+
| 'const'
|
|
17
|
+
| 'get'
|
|
18
|
+
| 'global'
|
|
19
|
+
| 'init'
|
|
20
|
+
| 'let'
|
|
21
|
+
| 'module'
|
|
22
|
+
| 'namespace'
|
|
23
|
+
| 'set'
|
|
24
|
+
| 'var'
|
|
16
25
|
readonly expression?: boolean
|
|
26
|
+
readonly readonly?: boolean
|
|
27
|
+
readonly test?: PolicyExpression
|
|
28
|
+
readonly alternate?: PolicyExpression | null
|
|
17
29
|
readonly object?: PolicyExpression
|
|
18
30
|
readonly property?: PolicyExpression
|
|
19
31
|
readonly computed?: boolean
|
|
@@ -25,10 +37,11 @@ export interface PolicyExpression extends PolicyNode {
|
|
|
25
37
|
readonly quasis?: readonly PolicyExpression[]
|
|
26
38
|
readonly expressions?: readonly PolicyExpression[]
|
|
27
39
|
readonly accessibility?: 'private' | 'protected' | 'public' | null
|
|
40
|
+
readonly declare?: boolean
|
|
28
41
|
readonly declaration?: PolicyExpression
|
|
29
42
|
readonly declarations?: readonly PolicyExpression[]
|
|
30
43
|
readonly init?: PolicyExpression | null
|
|
31
|
-
readonly source?: PolicyExpression
|
|
44
|
+
readonly source?: PolicyExpression | null
|
|
32
45
|
readonly specifiers?: readonly PolicyExpression[]
|
|
33
46
|
readonly imported?: PolicyExpression
|
|
34
47
|
readonly exported?: PolicyExpression
|
|
@@ -52,12 +65,30 @@ export interface PolicyComment extends PolicyNode {
|
|
|
52
65
|
readonly value: string
|
|
53
66
|
}
|
|
54
67
|
|
|
68
|
+
/** Describes one reference the scope manager records to a declared variable. */
|
|
69
|
+
export interface PolicyReference {
|
|
70
|
+
readonly identifier: PolicyNode
|
|
71
|
+
readonly init?: boolean
|
|
72
|
+
isWrite(): boolean
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Describes one variable the scope manager records for a declaration. */
|
|
76
|
+
export interface PolicyVariable {
|
|
77
|
+
readonly identifiers: readonly PolicyNode[]
|
|
78
|
+
readonly references: readonly PolicyReference[]
|
|
79
|
+
}
|
|
80
|
+
|
|
55
81
|
/** Lists the Oxlint source-text operations the comment rules read. */
|
|
56
82
|
export interface PolicySourceCode {
|
|
57
83
|
readonly text: string
|
|
58
84
|
getAllComments(): readonly PolicyComment[]
|
|
59
85
|
}
|
|
60
86
|
|
|
87
|
+
/** Adds the Oxlint scope operation the binding rule reads. */
|
|
88
|
+
export interface PolicyScopeCode extends PolicySourceCode {
|
|
89
|
+
getDeclaredVariables(node: PolicyNode): readonly PolicyVariable[]
|
|
90
|
+
}
|
|
91
|
+
|
|
61
92
|
/** Pairs one doc block with the declared name its first sentence must not repeat. */
|
|
62
93
|
export interface PolicyDoc {
|
|
63
94
|
readonly comment: PolicyComment
|
|
@@ -89,7 +120,7 @@ export interface PolicyContext {
|
|
|
89
120
|
readonly filename: string
|
|
90
121
|
/** Names the directory Oxlint resolves `filename` against. */
|
|
91
122
|
readonly cwd: string
|
|
92
|
-
readonly sourceCode:
|
|
123
|
+
readonly sourceCode: PolicyScopeCode
|
|
93
124
|
report(diagnostic: PolicyDiagnostic): void
|
|
94
125
|
}
|
|
95
126
|
|
|
@@ -116,6 +147,9 @@ export interface PolicyVisitor {
|
|
|
116
147
|
readonly FunctionExpression?: (node: PolicyNode) => void
|
|
117
148
|
readonly ArrowFunctionExpression?: (node: PolicyNode) => void
|
|
118
149
|
readonly ImportDeclaration?: (node: PolicyNode) => void
|
|
150
|
+
readonly ImportExpression?: (node: PolicyNode) => void
|
|
151
|
+
readonly ExportNamedDeclaration?: (node: PolicyNode) => void
|
|
152
|
+
readonly ExportAllDeclaration?: (node: PolicyNode) => void
|
|
119
153
|
readonly MemberExpression?: (node: PolicyNode) => void
|
|
120
154
|
readonly MethodDefinition?: (node: PolicyNode) => void
|
|
121
155
|
readonly PropertyDefinition?: (node: PolicyNode) => void
|
|
@@ -127,6 +161,7 @@ export interface PolicyVisitor {
|
|
|
127
161
|
readonly TSEnumDeclaration?: (node: PolicyNode) => void
|
|
128
162
|
readonly TSInterfaceDeclaration?: (node: PolicyNode) => void
|
|
129
163
|
readonly TSModuleDeclaration?: (node: PolicyNode) => void
|
|
164
|
+
readonly TSPropertySignature?: (node: PolicyNode) => void
|
|
130
165
|
readonly TSTypeAliasDeclaration?: (node: PolicyNode) => void
|
|
131
166
|
readonly VariableDeclaration?: (node: PolicyNode) => void
|
|
132
167
|
}
|
|
@@ -205,9 +240,25 @@ export const DATA_EXEMPT_FILES: readonly string[] = Object.freeze(['helpers.ts']
|
|
|
205
240
|
/** Lists the fleet-registered folders whose direct modules each contain one named function. */
|
|
206
241
|
export const FUNCTION_DOMAIN_FOLDERS: readonly string[] = Object.freeze([
|
|
207
242
|
'app/browser/composables',
|
|
243
|
+
'app/vue/composables',
|
|
208
244
|
'src/server/execution',
|
|
209
245
|
])
|
|
210
246
|
|
|
247
|
+
/** Lists the published destinations a Vue relative import may reach before independent restrictions. */
|
|
248
|
+
export const VUE_SOURCE_ROOTS: readonly string[] = Object.freeze([
|
|
249
|
+
'src/core',
|
|
250
|
+
'src/browser',
|
|
251
|
+
'src/vue',
|
|
252
|
+
])
|
|
253
|
+
|
|
254
|
+
/** Lists the additional private destinations an application Vue relative import may reach. */
|
|
255
|
+
export const VUE_APPLICATION_ROOTS: readonly string[] = Object.freeze([
|
|
256
|
+
...VUE_SOURCE_ROOTS,
|
|
257
|
+
'app/core',
|
|
258
|
+
'app/browser',
|
|
259
|
+
'app/vue',
|
|
260
|
+
])
|
|
261
|
+
|
|
211
262
|
/** Lists the registered function-domain names no source file may take as its stem. */
|
|
212
263
|
export const FUNCTION_DOMAIN_NAMES: readonly string[] = Object.freeze(
|
|
213
264
|
FUNCTION_DOMAIN_FOLDERS.map((folder) => folder.slice(folder.lastIndexOf('/') + 1)),
|
|
@@ -247,6 +298,68 @@ export const POLICY_ENDING_GLOBS: readonly string[] = Object.freeze([
|
|
|
247
298
|
'src/**/*.ts',
|
|
248
299
|
])
|
|
249
300
|
|
|
301
|
+
/** Lists every source extension the nested-function rule reads. */
|
|
302
|
+
export const POLICY_CODE_EXTENSIONS: readonly string[] = Object.freeze([
|
|
303
|
+
'cjs',
|
|
304
|
+
'cts',
|
|
305
|
+
'js',
|
|
306
|
+
'jsx',
|
|
307
|
+
'mjs',
|
|
308
|
+
'mts',
|
|
309
|
+
'ts',
|
|
310
|
+
'tsx',
|
|
311
|
+
'vue',
|
|
312
|
+
])
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Matches the lint population the nested-function rule runs over, as the Oxlint configuration
|
|
316
|
+
* declares it.
|
|
317
|
+
*/
|
|
318
|
+
export const POLICY_NESTED_GLOBS: readonly string[] = Object.freeze(
|
|
319
|
+
['src', 'app', 'tests', 'configs'].map(
|
|
320
|
+
(root) => `${root}/**/*.{${POLICY_CODE_EXTENSIONS.join(',')}}`,
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Matches the lint population the skill-script rules run over, as the Oxlint configuration declares
|
|
326
|
+
* it.
|
|
327
|
+
*/
|
|
328
|
+
export const POLICY_SCRIPT_GLOBS: readonly string[] = Object.freeze([
|
|
329
|
+
'.agents/skills/*/scripts/*.ts',
|
|
330
|
+
])
|
|
331
|
+
|
|
332
|
+
/** Matches the workspace-relative path of a skill script, the file shape the script rule reads. */
|
|
333
|
+
export const POLICY_SCRIPT_PATTERN = /^\.agents\/skills\/[^/]+\/scripts\/[^/]+\.ts$/u
|
|
334
|
+
|
|
335
|
+
/** Holds the one entry guard a skill script runs `main` under, as its source text reads. */
|
|
336
|
+
export const POLICY_ENTRY_GUARD =
|
|
337
|
+
'process.argv[1] !== undefined && realpathSync(process.argv[1]) === import.meta.filename'
|
|
338
|
+
|
|
339
|
+
/** Lists every statement type that declares a name at module scope. */
|
|
340
|
+
export const POLICY_DECLARATION_TYPES: readonly string[] = Object.freeze([
|
|
341
|
+
'ClassDeclaration',
|
|
342
|
+
'FunctionDeclaration',
|
|
343
|
+
'TSDeclareFunction',
|
|
344
|
+
'TSEnumDeclaration',
|
|
345
|
+
'TSInterfaceDeclaration',
|
|
346
|
+
'TSModuleDeclaration',
|
|
347
|
+
'TSTypeAliasDeclaration',
|
|
348
|
+
'VariableDeclaration',
|
|
349
|
+
])
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Lists the type nodes a property signature's search for its owning declaration never crosses,
|
|
353
|
+
* because a parameter, call, or construct signature beyond one is an inline type.
|
|
354
|
+
*/
|
|
355
|
+
export const POLICY_INLINE_TYPES: readonly string[] = Object.freeze([
|
|
356
|
+
'TSCallSignatureDeclaration',
|
|
357
|
+
'TSConstructSignatureDeclaration',
|
|
358
|
+
'TSConstructorType',
|
|
359
|
+
'TSFunctionType',
|
|
360
|
+
'TSMethodSignature',
|
|
361
|
+
])
|
|
362
|
+
|
|
250
363
|
/**
|
|
251
364
|
* Matches the file name shape an implementation file takes, holding the class that matches its
|
|
252
365
|
* stem.
|
|
@@ -439,6 +552,69 @@ export function pathToPolicyRelative(filename: string, cwd: string): string {
|
|
|
439
552
|
return normalizedFile.startsWith(prefix) ? normalizedFile.slice(prefix.length) : normalizedFile
|
|
440
553
|
}
|
|
441
554
|
|
|
555
|
+
/**
|
|
556
|
+
* Computes a lexical workspace-relative destination from an absolute Vue importer and its cwd.
|
|
557
|
+
* Refuses unclassifiable locations, noncanonical relative segments, and traversal above the
|
|
558
|
+
* workspace. Query and fragment text is excluded from the path without decoding it; callers retain
|
|
559
|
+
* the original specifier for independent restrictions. No filesystem or module resolution occurs.
|
|
560
|
+
*/
|
|
561
|
+
export function computePolicyTarget(
|
|
562
|
+
filename: string,
|
|
563
|
+
cwd: string,
|
|
564
|
+
specifier: string,
|
|
565
|
+
): string | undefined {
|
|
566
|
+
const relative = pathToPolicyRelative(filename, cwd)
|
|
567
|
+
const location = relative.split('/')
|
|
568
|
+
if (
|
|
569
|
+
!/^(?:\/|[A-Za-z]:\/)/u.test(cwd.replaceAll('\\', '/')) ||
|
|
570
|
+
/(?:^|\/)\.{1,2}(?:\/|$)/u.test(cwd.replaceAll('\\', '/')) ||
|
|
571
|
+
relative === filename.replaceAll('\\', '/') ||
|
|
572
|
+
location.length < 3 ||
|
|
573
|
+
(location[0] !== 'src' && location[0] !== 'app') ||
|
|
574
|
+
location[1] !== 'vue' ||
|
|
575
|
+
location.some((part) => part === '' || part === '.' || part === '..')
|
|
576
|
+
) {
|
|
577
|
+
return undefined
|
|
578
|
+
}
|
|
579
|
+
const path = specifier.split(/[?#]/u)[0] ?? ''
|
|
580
|
+
if (!/^\.{1,2}(?:\/|$)/u.test(path) || path.includes('\\') || path.includes('//')) {
|
|
581
|
+
return undefined
|
|
582
|
+
}
|
|
583
|
+
const parts = path.replace(/\/$/u, '').split('/')
|
|
584
|
+
const first = parts.findIndex((part) => part !== '.' && part !== '..')
|
|
585
|
+
const boundary = first === -1 ? parts.length : first
|
|
586
|
+
const leading = parts.slice(0, boundary)
|
|
587
|
+
const parents = leading.filter((part) => part === '..').length
|
|
588
|
+
const remaining = parts.slice(boundary)
|
|
589
|
+
const directory = pathToPolicyFolder(relative).split('/')
|
|
590
|
+
if (
|
|
591
|
+
(parents === 0 && leading.length !== 1) ||
|
|
592
|
+
(parents !== 0 && parents !== leading.length) ||
|
|
593
|
+
parents > directory.length ||
|
|
594
|
+
remaining.some((part) => part === '' || part === '.' || part === '..')
|
|
595
|
+
) {
|
|
596
|
+
return undefined
|
|
597
|
+
}
|
|
598
|
+
return [...directory.slice(0, directory.length - parents), ...remaining].join('/')
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/** Reports a literal relative import or re-export whose actual destination leaves its Vue boundary. */
|
|
602
|
+
export function reportVueImport(context: PolicyContext, node: PolicyExpression): void {
|
|
603
|
+
const source = node.source
|
|
604
|
+
if (source?.type !== 'Literal' || typeof source.value !== 'string') return
|
|
605
|
+
if (!/^\.{1,2}(?:[/?#]|$)/u.test(source.value)) return
|
|
606
|
+
const target = computePolicyTarget(context.filename, context.cwd, source.value)
|
|
607
|
+
const roots = pathToPolicyRelative(context.filename, context.cwd).startsWith('app/vue/')
|
|
608
|
+
? VUE_APPLICATION_ROOTS
|
|
609
|
+
: VUE_SOURCE_ROOTS
|
|
610
|
+
if (
|
|
611
|
+
target !== undefined &&
|
|
612
|
+
roots.some((root) => target === root || target.startsWith(root + '/'))
|
|
613
|
+
)
|
|
614
|
+
return
|
|
615
|
+
context.report({ node, messageId: 'vue' })
|
|
616
|
+
}
|
|
617
|
+
|
|
442
618
|
/** Returns the extensionless stem of one policy file name. */
|
|
443
619
|
export function fileToPolicyStem(file: string): string {
|
|
444
620
|
const boundary = file.lastIndexOf('.')
|
|
@@ -788,12 +964,37 @@ export function isPolicyVoiced(word: string): boolean {
|
|
|
788
964
|
}
|
|
789
965
|
|
|
790
966
|
/**
|
|
791
|
-
*
|
|
967
|
+
* Reads the doc block written directly above one top-level statement.
|
|
792
968
|
*
|
|
793
969
|
* @remarks
|
|
794
970
|
* A statement takes the last comment that closes before it, and takes it only where that comment is
|
|
795
971
|
* a doc block and nothing but whitespace separates the two. A blank line between them is still
|
|
796
|
-
* whitespace, so the pairing survives one.
|
|
972
|
+
* whitespace, so the pairing survives one. Every comment is read where a `findLast` would stop at
|
|
973
|
+
* the nearest one.
|
|
974
|
+
*
|
|
975
|
+
* @param statement - The top-level statement to pair.
|
|
976
|
+
* @param comments - Every comment of the linted file, in source order.
|
|
977
|
+
* @param sourceCode - The source-text reader supplying the text between a comment and the statement.
|
|
978
|
+
* @returns The paired doc block, or `undefined` where the statement has none.
|
|
979
|
+
*/
|
|
980
|
+
export function statementToPolicyDoc(
|
|
981
|
+
statement: PolicyExpression,
|
|
982
|
+
comments: readonly PolicyComment[],
|
|
983
|
+
sourceCode: PolicySourceCode,
|
|
984
|
+
): PolicyComment | undefined {
|
|
985
|
+
const start = statement.range[0]
|
|
986
|
+
const previous = Iterator.from(comments)
|
|
987
|
+
.flatMap((comment) => (comment.range[1] <= start ? [comment] : []))
|
|
988
|
+
.toArray()
|
|
989
|
+
.at(-1)
|
|
990
|
+
if (previous === undefined || previous.type !== 'Block') return undefined
|
|
991
|
+
if (!previous.value.startsWith('*')) return undefined
|
|
992
|
+
if (sourceCode.text.slice(previous.range[1], start).trim() !== '') return undefined
|
|
993
|
+
return previous
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Pairs every exported top-level statement with the doc block written directly above it.
|
|
797
998
|
*
|
|
798
999
|
* @param node - The program node whose top-level statements are read.
|
|
799
1000
|
* @param sourceCode - The source-text reader supplying the comments and the text between them.
|
|
@@ -804,24 +1005,18 @@ export function programToPolicyDocs(
|
|
|
804
1005
|
sourceCode: PolicySourceCode,
|
|
805
1006
|
): readonly PolicyDoc[] {
|
|
806
1007
|
// The iterator consumes one entry at a time and reads a hole as an `undefined` entry, as a
|
|
807
|
-
// `for…of` over the list would. The comments are read
|
|
808
|
-
//
|
|
1008
|
+
// `for…of` over the list would. The comments are read once, and a statement pairs with one only
|
|
1009
|
+
// where it is an export.
|
|
809
1010
|
const comments = sourceCode.getAllComments()
|
|
810
1011
|
return Iterator.from(programToPolicyStatements(node))
|
|
811
1012
|
.flatMap((statement) => {
|
|
812
1013
|
if (!statement.type.startsWith('Export')) return []
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
.flatMap((comment) => (comment.range[1] <= start ? [comment] : []))
|
|
816
|
-
.toArray()
|
|
817
|
-
.at(-1)
|
|
818
|
-
if (previous === undefined || previous.type !== 'Block') return []
|
|
819
|
-
if (!previous.value.startsWith('*')) return []
|
|
820
|
-
if (sourceCode.text.slice(previous.range[1], start).trim() !== '') return []
|
|
1014
|
+
const comment = statementToPolicyDoc(statement, comments, sourceCode)
|
|
1015
|
+
if (comment === undefined) return []
|
|
821
1016
|
const declaration = statement.declaration
|
|
822
1017
|
return [
|
|
823
1018
|
{
|
|
824
|
-
comment
|
|
1019
|
+
comment,
|
|
825
1020
|
name:
|
|
826
1021
|
identifierToPolicyName(declaration?.id) ??
|
|
827
1022
|
identifierToPolicyName(declaration?.declarations?.[0]?.id),
|
|
@@ -941,6 +1136,54 @@ export function reportPrivacy(context: PolicyContext, node: PolicyExpression): v
|
|
|
941
1136
|
}
|
|
942
1137
|
}
|
|
943
1138
|
|
|
1139
|
+
/** Checks whether code writes a declared variable anywhere but in its own declaration. */
|
|
1140
|
+
export function isPolicyReassigned(variable: PolicyVariable): boolean {
|
|
1141
|
+
return variable.references.some(
|
|
1142
|
+
(reference) =>
|
|
1143
|
+
reference.isWrite() &&
|
|
1144
|
+
reference.init !== true &&
|
|
1145
|
+
!variable.identifiers.includes(reference.identifier),
|
|
1146
|
+
)
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Checks whether a node sits inside a `declare` module, namespace, or global augmentation.
|
|
1151
|
+
*
|
|
1152
|
+
* @remarks
|
|
1153
|
+
* A declaration inside such a block carries no `declare` flag of its own and no value, because the
|
|
1154
|
+
* block is the ambient context. A `global` block is ambient wherever it stands.
|
|
1155
|
+
*/
|
|
1156
|
+
export function isPolicyInDeclaredModule(node: PolicyExpression): boolean {
|
|
1157
|
+
const parent = node.parent
|
|
1158
|
+
if (parent === undefined || parent === null) return false
|
|
1159
|
+
return (
|
|
1160
|
+
(parent.type === 'TSModuleDeclaration' &&
|
|
1161
|
+
(parent.declare === true || parent.kind === 'global')) ||
|
|
1162
|
+
isPolicyInDeclaredModule(parent)
|
|
1163
|
+
)
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
/** Reports a let declaration that prefer-const leaves: one reassigned or declared without a value. */
|
|
1167
|
+
export function reportLet(context: PolicyContext, node: PolicyExpression): void {
|
|
1168
|
+
if (
|
|
1169
|
+
node.kind !== 'let' ||
|
|
1170
|
+
node.declare === true ||
|
|
1171
|
+
isPolicyAmbient(context.filename) ||
|
|
1172
|
+
isPolicyInDeclaredModule(node)
|
|
1173
|
+
) {
|
|
1174
|
+
return
|
|
1175
|
+
}
|
|
1176
|
+
const head = node.parent?.type === 'ForInStatement' || node.parent?.type === 'ForOfStatement'
|
|
1177
|
+
const bare =
|
|
1178
|
+
!head &&
|
|
1179
|
+
(node.declarations ?? []).some(
|
|
1180
|
+
(declarator) => declarator.init === undefined || declarator.init === null,
|
|
1181
|
+
)
|
|
1182
|
+
if (bare || context.sourceCode.getDeclaredVariables(node).some(isPolicyReassigned)) {
|
|
1183
|
+
context.report({ node, messageId: 'let' })
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
944
1187
|
/** Reports a centralized declaration that carries no export. */
|
|
945
1188
|
export function reportHidden(context: PolicyContext, node: PolicyExpression): void {
|
|
946
1189
|
if (isPolicyAmbient(context.filename)) return
|
|
@@ -1111,6 +1354,64 @@ export function reportEndingImport(context: PolicyContext, node: PolicyExpressio
|
|
|
1111
1354
|
if (importsPolicyTerminator(node)) context.report({ node, messageId: 'terminator' })
|
|
1112
1355
|
}
|
|
1113
1356
|
|
|
1357
|
+
/** Reports whether a path is a skill script, the one file shape the script rule reads. */
|
|
1358
|
+
export function isPolicyScript(filename: string, cwd: string): boolean {
|
|
1359
|
+
return POLICY_SCRIPT_PATTERN.test(pathToPolicyRelative(filename, cwd))
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
/** Reports whether a statement is the one entry guard a skill script runs its main under. */
|
|
1363
|
+
export function isPolicyGuard(statement: PolicyExpression, sourceCode: PolicySourceCode): boolean {
|
|
1364
|
+
const test = statement.test
|
|
1365
|
+
if (statement.type !== 'IfStatement' || test === undefined) return false
|
|
1366
|
+
if (statement.alternate !== undefined && statement.alternate !== null) return false
|
|
1367
|
+
const text = sourceCode.text.slice(test.range[0], test.range[1]).replace(/\s+/gu, ' ')
|
|
1368
|
+
return text === POLICY_ENTRY_GUARD
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
/** Reports a skill script's top-level statement that is hidden, undocumented, or runs at import. */
|
|
1372
|
+
export function reportScript(context: PolicyContext, node: PolicyExpression): void {
|
|
1373
|
+
if (isPolicyAmbient(context.filename) || !isPolicyScript(context.filename, context.cwd)) return
|
|
1374
|
+
const sourceCode = context.sourceCode
|
|
1375
|
+
const comments = sourceCode.getAllComments()
|
|
1376
|
+
const statements = programToPolicyStatements(node)
|
|
1377
|
+
const guard = statements.findIndex((statement) => isPolicyGuard(statement, sourceCode))
|
|
1378
|
+
for (const [index, statement] of statements.entries()) {
|
|
1379
|
+
if (statement.type === 'ImportDeclaration' || index === guard) continue
|
|
1380
|
+
const declaration = statement.declaration
|
|
1381
|
+
if (
|
|
1382
|
+
statement.type === 'ExportNamedDeclaration' &&
|
|
1383
|
+
declaration !== undefined &&
|
|
1384
|
+
declaration !== null
|
|
1385
|
+
) {
|
|
1386
|
+
if (statementToPolicyDoc(statement, comments, sourceCode) === undefined) {
|
|
1387
|
+
context.report({ node: statement, messageId: 'doc' })
|
|
1388
|
+
}
|
|
1389
|
+
continue
|
|
1390
|
+
}
|
|
1391
|
+
context.report({
|
|
1392
|
+
node: statement,
|
|
1393
|
+
messageId: POLICY_DECLARATION_TYPES.includes(statement.type) ? 'hidden' : 'entry',
|
|
1394
|
+
})
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/** Reports whether a property signature sits in an interface or in a type alias's object type. */
|
|
1399
|
+
export function isPolicyOwned(node: PolicyExpression): boolean {
|
|
1400
|
+
const parent = node.parent
|
|
1401
|
+
if (parent === undefined || parent === null) return false
|
|
1402
|
+
if (parent.type === 'TSInterfaceDeclaration' || parent.type === 'TSTypeAliasDeclaration') {
|
|
1403
|
+
return true
|
|
1404
|
+
}
|
|
1405
|
+
if (POLICY_INLINE_TYPES.includes(parent.type)) return false
|
|
1406
|
+
return isPolicyOwned(parent)
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/** Reports a property signature of an interface or type alias that is not readonly. */
|
|
1410
|
+
export function reportMutable(context: PolicyContext, node: PolicyExpression): void {
|
|
1411
|
+
if (isPolicyAmbient(context.filename) || node.readonly === true) return
|
|
1412
|
+
if (isPolicyOwned(node)) context.report({ node, messageId: 'mutable' })
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1114
1415
|
/** Bans function declarations and assignments inside another function body. */
|
|
1115
1416
|
export const NESTED_RULE: PolicyRuleInterface = {
|
|
1116
1417
|
meta: {
|
|
@@ -1180,6 +1481,25 @@ export const PRIVACY_RULE: PolicyRuleInterface = {
|
|
|
1180
1481
|
},
|
|
1181
1482
|
}
|
|
1182
1483
|
|
|
1484
|
+
/** Bans a let declaration that prefer-const does not already report. */
|
|
1485
|
+
export const LET_RULE: PolicyRuleInterface = {
|
|
1486
|
+
meta: {
|
|
1487
|
+
type: 'problem',
|
|
1488
|
+
docs: {
|
|
1489
|
+
description:
|
|
1490
|
+
'Disallow a let declaration that is reassigned or declared without a value; prefer-const reports the rest.',
|
|
1491
|
+
},
|
|
1492
|
+
messages: {
|
|
1493
|
+
let: 'Declare this binding with const and derive its value: an expression, a helper that returns it, or a for…of over entries() in place of a counter.',
|
|
1494
|
+
},
|
|
1495
|
+
},
|
|
1496
|
+
create(context) {
|
|
1497
|
+
return {
|
|
1498
|
+
VariableDeclaration: (node) => reportLet(context, node),
|
|
1499
|
+
}
|
|
1500
|
+
},
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1183
1503
|
/** Bans a centralized declaration that no export reaches. */
|
|
1184
1504
|
export const HIDDEN_RULE: PolicyRuleInterface = {
|
|
1185
1505
|
meta: {
|
|
@@ -1399,6 +1719,28 @@ export const DOMAIN_RULE: PolicyRuleInterface = {
|
|
|
1399
1719
|
},
|
|
1400
1720
|
}
|
|
1401
1721
|
|
|
1722
|
+
/** Bans literal relative imports and re-exports outside the importing Vue face's permitted roots. */
|
|
1723
|
+
export const VUE_IMPORT_RULE: PolicyRuleInterface = {
|
|
1724
|
+
meta: {
|
|
1725
|
+
type: 'problem',
|
|
1726
|
+
docs: {
|
|
1727
|
+
description:
|
|
1728
|
+
'Disallow Vue relative imports outside the faces their importing file may reach.',
|
|
1729
|
+
},
|
|
1730
|
+
messages: {
|
|
1731
|
+
vue: 'Keep this Vue relative import within the permitted source and application faces.',
|
|
1732
|
+
},
|
|
1733
|
+
},
|
|
1734
|
+
create(context) {
|
|
1735
|
+
return {
|
|
1736
|
+
ImportDeclaration: (node) => reportVueImport(context, node),
|
|
1737
|
+
ImportExpression: (node) => reportVueImport(context, node),
|
|
1738
|
+
ExportNamedDeclaration: (node) => reportVueImport(context, node),
|
|
1739
|
+
ExportAllDeclaration: (node) => reportVueImport(context, node),
|
|
1740
|
+
}
|
|
1741
|
+
},
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1402
1744
|
/** Bans host-specific line-ending handling. */
|
|
1403
1745
|
export const ENDING_RULE: PolicyRuleInterface = {
|
|
1404
1746
|
meta: {
|
|
@@ -1442,6 +1784,49 @@ export const VOICE_RULE: PolicyRuleInterface = {
|
|
|
1442
1784
|
},
|
|
1443
1785
|
}
|
|
1444
1786
|
|
|
1787
|
+
/** Bans a skill script top-level statement that is hidden, undocumented, or runs at import. */
|
|
1788
|
+
export const SCRIPT_RULE: PolicyRuleInterface = {
|
|
1789
|
+
meta: {
|
|
1790
|
+
type: 'problem',
|
|
1791
|
+
docs: {
|
|
1792
|
+
description:
|
|
1793
|
+
'Disallow an unexported declaration, an undocumented export, and a statement beyond the one guarded entry in a skill script.',
|
|
1794
|
+
},
|
|
1795
|
+
messages: {
|
|
1796
|
+
hidden:
|
|
1797
|
+
'Export this declaration; a skill script exports every declaration so its proof can test each one.',
|
|
1798
|
+
doc: 'Write a one-sentence TSDoc summary directly above this export.',
|
|
1799
|
+
entry:
|
|
1800
|
+
'Move this statement into a function; a skill script holds imports, exported declarations, and the one process.argv[1] guard that runs main, and an import runs nothing.',
|
|
1801
|
+
},
|
|
1802
|
+
},
|
|
1803
|
+
create(context) {
|
|
1804
|
+
return {
|
|
1805
|
+
Program: (node) => reportScript(context, node),
|
|
1806
|
+
}
|
|
1807
|
+
},
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
/** Bans a property signature in an interface or type alias that is not readonly. */
|
|
1811
|
+
export const MUTABLE_RULE: PolicyRuleInterface = {
|
|
1812
|
+
meta: {
|
|
1813
|
+
type: 'problem',
|
|
1814
|
+
docs: {
|
|
1815
|
+
description:
|
|
1816
|
+
'Disallow a property signature without readonly in an interface or in the object type of a type alias.',
|
|
1817
|
+
},
|
|
1818
|
+
messages: {
|
|
1819
|
+
mutable:
|
|
1820
|
+
'Declare this property readonly; a contract exposes its members and no holder rewrites them.',
|
|
1821
|
+
},
|
|
1822
|
+
},
|
|
1823
|
+
create(context) {
|
|
1824
|
+
return {
|
|
1825
|
+
TSPropertySignature: (node) => reportMutable(context, node),
|
|
1826
|
+
}
|
|
1827
|
+
},
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1445
1830
|
/** Bans a comment carrying a term the substitution table bans unconditionally. */
|
|
1446
1831
|
export const TERM_RULE: PolicyRuleInterface = {
|
|
1447
1832
|
meta: {
|
|
@@ -1467,6 +1852,7 @@ export default {
|
|
|
1467
1852
|
rules: {
|
|
1468
1853
|
'no-mocking': MOCKING_RULE,
|
|
1469
1854
|
'no-keyword-privacy': PRIVACY_RULE,
|
|
1855
|
+
'no-let': LET_RULE,
|
|
1470
1856
|
'no-nested-functions': NESTED_RULE,
|
|
1471
1857
|
'no-hidden-declaration': HIDDEN_RULE,
|
|
1472
1858
|
'no-misplaced-type': TYPE_RULE,
|
|
@@ -1478,8 +1864,11 @@ export default {
|
|
|
1478
1864
|
'no-misnamed-factory': FACTORY_RULE,
|
|
1479
1865
|
'no-misnamed-plugin': PLUGIN_RULE,
|
|
1480
1866
|
'no-malformed-domain': DOMAIN_RULE,
|
|
1867
|
+
'no-cross-vue-face': VUE_IMPORT_RULE,
|
|
1481
1868
|
'no-host-line-endings': ENDING_RULE,
|
|
1482
1869
|
'no-malformed-summary': VOICE_RULE,
|
|
1483
1870
|
'no-banned-term': TERM_RULE,
|
|
1871
|
+
'no-malformed-script': SCRIPT_RULE,
|
|
1872
|
+
'no-mutable-property': MUTABLE_RULE,
|
|
1484
1873
|
},
|
|
1485
1874
|
}
|
|
@@ -11,6 +11,7 @@ alwaysApply: true
|
|
|
11
11
|
|
|
12
12
|
- Invoked through the `grok` bridge (`agent -p --mode=ask`): act as a read-only executor. Return distilled evidence with `file:line` pointers. Never edit, decide, or accept.
|
|
13
13
|
- Driven by the user: act as the Orchestrator per `.agents/orchestration.md`, on Grok.
|
|
14
|
+
- `.agents/skills/orkestrel-parallel/references/cursor.md` owns Cursor's lane mechanics and quirks; `.agents/platforms/` owns the host shell.
|
|
14
15
|
|
|
15
16
|
## Reaching the other engines
|
|
16
17
|
|