@orkestrel/scaffold 0.0.40 → 0.0.42
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/bin/main.js +8 -1
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +2 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +16 -16
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +3 -3
- package/dist/host/agents/skills/orkestrel-align-packages/references/integration.md +1 -1
- package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +7 -2
- package/dist/host/claude/agents/builder.md +2 -2
- package/dist/host/claude/agents/orkestrel.md +48 -48
- package/dist/host/claude/rules/application.md +6 -4
- package/dist/host/claude/rules/architecture.md +2 -0
- package/dist/host/claude/rules/documentation.md +6 -0
- package/dist/host/claude/rules/tests.md +11 -1
- package/dist/host/claude/rules/typescript.md +15 -1
- package/dist/host/claude/rules/workspace.md +43 -13
- package/dist/host/claude/rules/writing.md +125 -0
- package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +10 -1
- package/dist/host/claude/skills/orkestrel-align-packages/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-build-application/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-harden-package/SKILL.md +1 -1
- package/dist/host/configs/policy.ts +185 -0
- package/dist/host/dotfiles/oxlintrc.json +13 -1
- package/dist/host/dotfiles/prettierignore +3 -0
- package/dist/host/guides/scaffold.md +23 -10
- package/dist/host/manifest.json +11 -7
- package/dist/host/scripts/codex.sh +0 -0
- package/dist/host/scripts/cursor.sh +0 -0
- package/dist/host/scripts/deps.sh +0 -0
- package/dist/host/scripts/ollama.sh +0 -0
- package/dist/host/tests/config.test.ts +217 -4
- package/dist/host/tests/policy.test.ts +82 -0
- package/dist/host/tests/setupPolicy.ts +863 -21
- package/dist/src/core/index.cjs +97 -22
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +45 -29
- package/dist/src/core/index.d.ts +45 -29
- package/dist/src/core/index.js +96 -22
- package/dist/src/core/index.js.map +1 -1
- package/package.json +7 -7
- package/dist/host/agents/skills/orkestrel-build-application/references/application.md +0 -129
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Developer-facing writing rules
|
|
2
|
+
|
|
3
|
+
These rules govern prose a developer reads, including chat replies, reports, guides, README files,
|
|
4
|
+
and commit messages.
|
|
5
|
+
`AGENTS.md` § Writing governs prose everywhere, and this file does not restate it; this file adds
|
|
6
|
+
only what a developer audience decides. An instruction file follows `AGENTS.md` § Instruction files
|
|
7
|
+
first, and these rules wherever a rule here names no different form for it.
|
|
8
|
+
|
|
9
|
+
## Voice and actor
|
|
10
|
+
|
|
11
|
+
- Write `must` for a requirement, `can` for an option or an ability, and `might` for a possibility.
|
|
12
|
+
A recommendation takes the imperative, the same form `AGENTS.md` § Writing fixes for instructions.
|
|
13
|
+
Never write `should`, and never soften a recommendation into `We recommend`.
|
|
14
|
+
- Address the developer as `you`. Name the software component that acts, and make it the subject of
|
|
15
|
+
the sentence. Reserve `user` for someone using software the developer builds. Never write `we`,
|
|
16
|
+
`our`, or `let's` about agent work.
|
|
17
|
+
- Give software no human faculties. A component reports, returns, detects, or refuses; it never
|
|
18
|
+
knows, thinks, wants, or sees.
|
|
19
|
+
- Use the passive voice only where naming the actor adds blame and nothing else, such as a defect
|
|
20
|
+
count. Name the actor wherever the reader needs it.
|
|
21
|
+
- Use negative contractions (`don't`, `isn't`, `can't`) in a reply or a guide. Do not use them in an
|
|
22
|
+
instruction file.
|
|
23
|
+
|
|
24
|
+
## Sentence and paragraph order
|
|
25
|
+
|
|
26
|
+
- Put the condition, the goal, or the location before the instruction, so a reader the instruction
|
|
27
|
+
does not apply to stops at the first clause. Put the result or the reason after it. This governs a
|
|
28
|
+
sentence, not a document: a report still opens with its finding.
|
|
29
|
+
- Put the key point in the first sentence of every paragraph and every list item, not only in the
|
|
30
|
+
opening of the reply or the section.
|
|
31
|
+
- Keep the helper words `that`, `then`, `of`, `a`, and `the`. Do not drop one for brevity.
|
|
32
|
+
- Name the noun after `this`, `these`, or `it` wherever the reader could attach the pronoun to
|
|
33
|
+
another referent.
|
|
34
|
+
- State what the reader can do. Do not write a double negative.
|
|
35
|
+
|
|
36
|
+
## Claims and time
|
|
37
|
+
|
|
38
|
+
- Claim only what the reader can check. Never write `ensure`, `guarantee`, a superlative, or an
|
|
39
|
+
effort adjective as a claim about behavior, and cite the run behind every number. `ensure`
|
|
40
|
+
addressed to an executor as a directive is outside this ban.
|
|
41
|
+
- Write the present tense for what exists. Do not write `currently`, `now`, `new`, `latest`, or
|
|
42
|
+
`soon`; where time matters, give the version or the date.
|
|
43
|
+
- Recommend one path, the shortest one you proved. Rule on every option you list, and drop an option
|
|
44
|
+
equivalent to the one you recommend.
|
|
45
|
+
|
|
46
|
+
## Code tokens, references, and links
|
|
47
|
+
|
|
48
|
+
- Put a code token in backticks and follow it with a noun: the `parse` method, the `vite.config.ts`
|
|
49
|
+
file, the `--check` flag. Never inflect, pluralize, or possessivize a code token, and never use one
|
|
50
|
+
as an English verb.
|
|
51
|
+
- Point to other material with `preceding`, `following`, `earlier`, or `later`, never with `above` or
|
|
52
|
+
`below`. Use `earlier` and `later` for a version range too.
|
|
53
|
+
- Write link text as the destination's title or a descriptive phrase, introduced by `see`. Never
|
|
54
|
+
write `here`, `this document`, or a bare URL in prose.
|
|
55
|
+
- Paraphrase third-party content and link its source; never paste it into prose you author. A
|
|
56
|
+
vendored mirror is fetched bytes rather than authored prose, and `.claude/rules/documentation.md`
|
|
57
|
+
governs it.
|
|
58
|
+
|
|
59
|
+
## Structure
|
|
60
|
+
|
|
61
|
+
- Keep a required fact in the main flow. A note or a notice carries only what the reader can skip,
|
|
62
|
+
never a prerequisite, a step, or a warning the task depends on.
|
|
63
|
+
- In a reply or a guide, introduce every list, table, and code fence with a complete sentence naming
|
|
64
|
+
what follows; a rule file's list sits bare under its heading. Number a list only where order or
|
|
65
|
+
rank matters. Use a table only for rows with comparable fields.
|
|
66
|
+
- Write a heading in sentence case, verb first for a task and a noun phrase for a concept. Identity
|
|
67
|
+
numbering — a claim, an audit verdict, a plan unit — is data rather than a heading style, and
|
|
68
|
+
stays.
|
|
69
|
+
|
|
70
|
+
## Examples, numbers, and abbreviations
|
|
71
|
+
|
|
72
|
+
- Build an example from fictional data with descriptive names and no personally identifiable
|
|
73
|
+
information. Write a placeholder in `UPPER_SNAKE_CASE` and explain it on first use. Never write
|
|
74
|
+
`foo`, `bar`, or `baz`.
|
|
75
|
+
- Expand an abbreviation the reader may not know on first use, with the short form in parentheses.
|
|
76
|
+
Skip the expansion for one this audience reads daily, such as `API`, `CLI`, `JSON`, `URL`, or a
|
|
77
|
+
file format.
|
|
78
|
+
- Write a numeral for a technical quantity, a version, or a count. Write a date as `YYYY-MM-DD` in
|
|
79
|
+
evidence, commit messages, and reports.
|
|
80
|
+
- Use the serial comma. Mark omitted code with a comment in the sample's language, never with `...`.
|
|
81
|
+
|
|
82
|
+
## Substitutions
|
|
83
|
+
|
|
84
|
+
Replace each term in this table with its replacement. Quote a literal code identifier as itself; it
|
|
85
|
+
is exempt from every row.
|
|
86
|
+
|
|
87
|
+
| Term | Replacement |
|
|
88
|
+
| ------------------------ | ----------------------------------------- |
|
|
89
|
+
| `should` | `must`, `can`, `might`, or the imperative |
|
|
90
|
+
| `simply`, `easy`, `just` | Delete |
|
|
91
|
+
| `currently`, `now` | Delete, or give the date |
|
|
92
|
+
| `new`, `latest` | Delete, or give the version |
|
|
93
|
+
| `utilize`, `leverage` | `use` |
|
|
94
|
+
| `via` | `through`, `by using` |
|
|
95
|
+
| `in order to` | `to` |
|
|
96
|
+
| `e.g.`, `i.e.` | `for example`, `that is` |
|
|
97
|
+
| `etc.` | Bound the list, or recast the sentence |
|
|
98
|
+
| `performant`, `robust` | The measured property |
|
|
99
|
+
| `allows you to` | `lets you` |
|
|
100
|
+
| `and/or` | `and`, `or`, or `both` |
|
|
101
|
+
| `since` (causal) | `because` |
|
|
102
|
+
| `once` (temporal) | `after` |
|
|
103
|
+
| `please` | Delete |
|
|
104
|
+
| `sanity check` | `quick check` |
|
|
105
|
+
| `dummy` | `placeholder` |
|
|
106
|
+
| `blacklist`, `whitelist` | `denylist`, `allowlist` |
|
|
107
|
+
| `master`, `slave` | `primary`, `replica` |
|
|
108
|
+
|
|
109
|
+
- Write singular `they` for a person of unstated gender.
|
|
110
|
+
- This table carries no row for `execute`, `abort`, `kill`, `terminate`, or `run`:
|
|
111
|
+
`.claude/rules/names.md` § Fixed lifecycle vocabulary owns those words, and no row here overrides
|
|
112
|
+
it.
|
|
113
|
+
|
|
114
|
+
## Not adopted
|
|
115
|
+
|
|
116
|
+
- Do not add conversational personality, warmth, or memorability to a reply; the prose stays plain.
|
|
117
|
+
- Do not import a license to break these rules where a departure reads better; an exception exists
|
|
118
|
+
only where a rule states it.
|
|
119
|
+
- `We recommend` as a recommendation form — refused in § Voice and actor.
|
|
120
|
+
- Do not apply a source guide's sample indentation or line-length chrome; the repository formatter
|
|
121
|
+
and `.claude/rules/typescript.md` decide code presentation.
|
|
122
|
+
- Do not write an unspaced em dash; this project spaces it.
|
|
123
|
+
- Do not cap a sentence at a word count; `AGENTS.md` § Writing owns sentence length.
|
|
124
|
+
- Do not treat an external word list as vocabulary law; the preceding substitution table is the
|
|
125
|
+
adopted set.
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: enterprise-bootstrap
|
|
3
|
-
description:
|
|
3
|
+
description: >-
|
|
4
|
+
Design and build distinctive, production-grade user interfaces with Bootstrap
|
|
5
|
+
5.3 and intentional frontend craft. Use for ANY UI work — creating, restyling,
|
|
6
|
+
reviewing, or extending pages, screens, components, layouts, app shells,
|
|
7
|
+
dashboards, admin panels, SaaS tools, data tables, filter bars, forms,
|
|
8
|
+
wizards, navigation, modals, empty/loading/error states, dark mode, marketing
|
|
9
|
+
surfaces — whenever the task touches HTML/CSS/visual design, mentions
|
|
10
|
+
Bootstrap or its components, or must look professional and avoid templated
|
|
11
|
+
defaults. Covers aesthetics, typography, color modes, design tokens,
|
|
12
|
+
accessibility (WCAG 2.2 AA), responsive layout, and enterprise app patterns.
|
|
4
13
|
---
|
|
5
14
|
|
|
6
15
|
# Load the canonical workflow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orkestrel-align-packages
|
|
3
|
-
description: Audit and improve how
|
|
3
|
+
description: Audit and improve how two or more Orkestrel packages, or their core, server, browser, and app environments, fit together. Use for coordinated package-stack refactors, cross-package extraction, developer-ergonomics reviews, end-to-end or live integration testing, dependency and guide alignment, and fleet/package-manager campaigns. Preserve host-independent core boundaries, update dependents topologically, and use the package-hardening workflow for each implementation unit.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Load the canonical workflow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orkestrel-build-application
|
|
3
|
-
description: Design, scaffold, extend, or harden Orkestrel app
|
|
3
|
+
description: Design, scaffold, extend, or harden Orkestrel `app/core`, `app/browser`, and `app/server` environments. Use for app-only or mixed src/app workspaces, app environment isolation, Vue browser entries, Node server entries, app aliases/configs/scripts/tests, cross-environment contracts, and application guide parity.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Load the canonical workflow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orkestrel-harden-package
|
|
3
|
-
description: Research, audit, refactor, implement, centralize, test, document, and locally verify an individual Orkestrel TypeScript package to enterprise-grade production readiness. Use
|
|
3
|
+
description: Research, audit, refactor, implement, centralize, test, document, and locally verify an individual Orkestrel TypeScript package to enterprise-grade production readiness under the repository's current AGENTS.md. Use when asked to fill missing or deferred capabilities, compare upstream or legacy implementations, salvage prior art, centralize source or test declarations, eliminate nested functions or superfluous wrappers, maximize declared @orkestrel dependencies—especially @orkestrel/contract—or add rigorous real-implementation and live-service tests. Select only the phases required by a narrow request; run the full workflow for production readiness or comprehensive hardening.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Load the canonical workflow
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/** The expression fields inspected by the policy rules. */
|
|
2
|
+
export interface PolicyExpression {
|
|
3
|
+
readonly type: string
|
|
4
|
+
readonly range: [number, number]
|
|
5
|
+
readonly name?: unknown
|
|
6
|
+
readonly value?: unknown
|
|
7
|
+
readonly object?: PolicyExpression
|
|
8
|
+
readonly property?: PolicyExpression
|
|
9
|
+
readonly computed?: boolean
|
|
10
|
+
readonly callee?: PolicyExpression
|
|
11
|
+
readonly quasis?: readonly PolicyExpression[]
|
|
12
|
+
readonly expressions?: readonly PolicyExpression[]
|
|
13
|
+
readonly accessibility?: 'private' | 'protected' | 'public' | null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** One diagnostic emitted by a policy rule. */
|
|
17
|
+
export interface PolicyDiagnostic {
|
|
18
|
+
readonly node: PolicyExpression
|
|
19
|
+
readonly messageId: string
|
|
20
|
+
readonly data?: Readonly<Record<string, string>>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The Oxlint context operations used by the policy rules. */
|
|
24
|
+
export interface PolicyContext {
|
|
25
|
+
report(diagnostic: PolicyDiagnostic): void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The rule documentation fields supplied to Oxlint. */
|
|
29
|
+
export interface PolicyDocs {
|
|
30
|
+
readonly [key: string]: unknown
|
|
31
|
+
readonly description: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The rule metadata fields supplied to Oxlint. */
|
|
35
|
+
export interface PolicyMeta {
|
|
36
|
+
readonly type: 'problem'
|
|
37
|
+
readonly docs: PolicyDocs
|
|
38
|
+
readonly messages: Readonly<Record<string, string>>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The Oxlint visitor entries used by the policy rules. */
|
|
42
|
+
export interface PolicyVisitor {
|
|
43
|
+
readonly [key: string]: ((node: PolicyExpression) => void) | undefined
|
|
44
|
+
readonly CallExpression?: (node: PolicyExpression) => void
|
|
45
|
+
readonly MethodDefinition?: (node: PolicyExpression) => void
|
|
46
|
+
readonly PropertyDefinition?: (node: PolicyExpression) => void
|
|
47
|
+
readonly AccessorProperty?: (node: PolicyExpression) => void
|
|
48
|
+
readonly TSAbstractMethodDefinition?: (node: PolicyExpression) => void
|
|
49
|
+
readonly TSAbstractPropertyDefinition?: (node: PolicyExpression) => void
|
|
50
|
+
readonly TSAbstractAccessorProperty?: (node: PolicyExpression) => void
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The complete behavior exposed by one policy rule. */
|
|
54
|
+
export interface PolicyRuleInterface {
|
|
55
|
+
readonly meta: PolicyMeta
|
|
56
|
+
create(context: PolicyContext): PolicyVisitor
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Report banned calls on the named Vitest and Jest framework objects. */
|
|
60
|
+
export function reportMocking(context: PolicyContext, node: PolicyExpression): void {
|
|
61
|
+
const callee = node.callee
|
|
62
|
+
if (
|
|
63
|
+
callee === undefined ||
|
|
64
|
+
callee.type !== 'MemberExpression' ||
|
|
65
|
+
callee.object === undefined ||
|
|
66
|
+
callee.property === undefined ||
|
|
67
|
+
callee.computed === undefined
|
|
68
|
+
) {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const object = callee.object
|
|
73
|
+
if (object.type !== 'Identifier' || (object.name !== 'vi' && object.name !== 'jest')) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const property = callee.property
|
|
78
|
+
let member: string | undefined
|
|
79
|
+
if (callee.computed) {
|
|
80
|
+
if (property.type === 'Literal' && typeof property.value === 'string') {
|
|
81
|
+
member = property.value
|
|
82
|
+
} else if (
|
|
83
|
+
property.type === 'TemplateLiteral' &&
|
|
84
|
+
property.quasis?.length === 1 &&
|
|
85
|
+
property.expressions?.length === 0
|
|
86
|
+
) {
|
|
87
|
+
const quasi = property.quasis[0]
|
|
88
|
+
const value = quasi?.value
|
|
89
|
+
if (typeof value === 'object' && value !== null) {
|
|
90
|
+
const cooked: unknown = Object.getOwnPropertyDescriptor(value, 'cooked')?.value
|
|
91
|
+
const raw: unknown = Object.getOwnPropertyDescriptor(value, 'raw')?.value
|
|
92
|
+
member = typeof cooked === 'string' ? cooked : typeof raw === 'string' ? raw : undefined
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} else if (property.type === 'Identifier' && typeof property.name === 'string') {
|
|
96
|
+
member = property.name
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
switch (member) {
|
|
100
|
+
case 'mock':
|
|
101
|
+
case 'doMock':
|
|
102
|
+
case 'unstable_mockModule':
|
|
103
|
+
context.report({ node, messageId: 'mock' })
|
|
104
|
+
break
|
|
105
|
+
case 'fn':
|
|
106
|
+
case 'spyOn':
|
|
107
|
+
context.report({ node, messageId: 'spy' })
|
|
108
|
+
break
|
|
109
|
+
case 'useFakeTimers':
|
|
110
|
+
case 'setSystemTime':
|
|
111
|
+
context.report({ node, messageId: 'clock' })
|
|
112
|
+
break
|
|
113
|
+
case 'stubGlobal':
|
|
114
|
+
case 'stubEnv':
|
|
115
|
+
context.report({ node, messageId: 'stub' })
|
|
116
|
+
break
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Report TypeScript privacy keywords on class members. */
|
|
121
|
+
export function reportPrivacy(context: PolicyContext, node: PolicyExpression): void {
|
|
122
|
+
if (node.accessibility === 'private' || node.accessibility === 'protected') {
|
|
123
|
+
context.report({
|
|
124
|
+
node,
|
|
125
|
+
messageId: 'keyword',
|
|
126
|
+
data: { keyword: node.accessibility },
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Ban framework mocking, spying, fake clocks, and global or environment stubs. */
|
|
132
|
+
export const MOCKING_RULE: PolicyRuleInterface = {
|
|
133
|
+
meta: {
|
|
134
|
+
type: 'problem',
|
|
135
|
+
docs: {
|
|
136
|
+
description:
|
|
137
|
+
'Disallow named vi and jest mocking APIs; a renamed import alias escapes this name-based rule.',
|
|
138
|
+
},
|
|
139
|
+
messages: {
|
|
140
|
+
mock: 'Replace module mocking with a real injected collaborator; a missing seam is a missing injection point, not an untestable truth.',
|
|
141
|
+
spy: 'Use createRecorder from @orkestrel/test; framework spies and mock functions are banned.',
|
|
142
|
+
clock:
|
|
143
|
+
'Use real short timers and waitForDelay from @orkestrel/test; never replace the host clock.',
|
|
144
|
+
stub: 'Drive the real implementation or a protocol-faithful fixture; never stub globals or environment.',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
create(context) {
|
|
148
|
+
return {
|
|
149
|
+
CallExpression: (node) => reportMocking(context, node),
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Ban compile-time-only TypeScript privacy keywords on class members. */
|
|
155
|
+
export const PRIVACY_RULE: PolicyRuleInterface = {
|
|
156
|
+
meta: {
|
|
157
|
+
type: 'problem',
|
|
158
|
+
docs: {
|
|
159
|
+
description:
|
|
160
|
+
'Disallow private and protected class members in favor of runtime-enforced # privacy.',
|
|
161
|
+
},
|
|
162
|
+
messages: {
|
|
163
|
+
keyword: 'Use runtime-enforced # privacy; TypeScript {{keyword}} is compile-time-only.',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
create(context) {
|
|
167
|
+
return {
|
|
168
|
+
MethodDefinition: (node) => reportPrivacy(context, node),
|
|
169
|
+
PropertyDefinition: (node) => reportPrivacy(context, node),
|
|
170
|
+
AccessorProperty: (node) => reportPrivacy(context, node),
|
|
171
|
+
TSAbstractMethodDefinition: (node) => reportPrivacy(context, node),
|
|
172
|
+
TSAbstractPropertyDefinition: (node) => reportPrivacy(context, node),
|
|
173
|
+
TSAbstractAccessorProperty: (node) => reportPrivacy(context, node),
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** The workspace Oxlint plugin. */
|
|
179
|
+
export default {
|
|
180
|
+
meta: { name: 'policy' },
|
|
181
|
+
rules: {
|
|
182
|
+
'no-mocking': MOCKING_RULE,
|
|
183
|
+
'no-keyword-privacy': PRIVACY_RULE,
|
|
184
|
+
},
|
|
185
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
|
|
3
3
|
"plugins": ["import", "typescript", "vitest"],
|
|
4
|
+
"jsPlugins": [{ "name": "policy", "specifier": "./configs/policy.ts" }],
|
|
4
5
|
"rules": {
|
|
5
6
|
"@typescript-eslint/no-explicit-any": "error",
|
|
6
7
|
"@typescript-eslint/no-non-null-assertion": "error",
|
|
7
8
|
"typescript/consistent-type-assertions": ["error", { "assertionStyle": "never" }],
|
|
8
9
|
"typescript/no-require-imports": "error",
|
|
9
10
|
"typescript/array-type": ["error", { "default": "array-simple" }],
|
|
11
|
+
"typescript/parameter-properties": "error",
|
|
12
|
+
"typescript/explicit-member-accessibility": ["error", { "accessibility": "no-public" }],
|
|
10
13
|
"typescript/ban-ts-comment": [
|
|
11
14
|
"error",
|
|
12
15
|
{
|
|
@@ -50,7 +53,10 @@
|
|
|
50
53
|
"no-underscore-dangle": "warn",
|
|
51
54
|
|
|
52
55
|
"vitest/no-alias-methods": "error",
|
|
53
|
-
"vitest/warn-todo": "off"
|
|
56
|
+
"vitest/warn-todo": "off",
|
|
57
|
+
|
|
58
|
+
"policy/no-mocking": "error",
|
|
59
|
+
"policy/no-keyword-privacy": "error"
|
|
54
60
|
},
|
|
55
61
|
"categories": {
|
|
56
62
|
"correctness": "error",
|
|
@@ -67,6 +73,12 @@
|
|
|
67
73
|
"import/no-default-export": "off"
|
|
68
74
|
}
|
|
69
75
|
},
|
|
76
|
+
{
|
|
77
|
+
"files": ["configs/policy.ts"],
|
|
78
|
+
"rules": {
|
|
79
|
+
"import/no-default-export": "off"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
70
82
|
{
|
|
71
83
|
"files": ["*.vue"],
|
|
72
84
|
"rules": {
|
|
@@ -102,8 +102,9 @@ Exported from `@orkestrel/scaffold`, and reachable from
|
|
|
102
102
|
| `ENGINES_PATTERN` | const | The minimum-Node engine syntax a blueprint declares. |
|
|
103
103
|
| `ENVIRONMENTS` | const | The three `Environment` values, frozen. |
|
|
104
104
|
| `EXECUTABLE_PATHS` | const | The vendored paths a target receives with its executable bit set, frozen. |
|
|
105
|
-
| `EXTRA_NAME_PATTERN` | const | The development extra name syntax: any valid npm package name. |
|
|
106
105
|
| `EXTRA_RANGE_PATTERN` | const | The registry-only semver subset accepted for a development extra's range. |
|
|
106
|
+
| `FLOOR_RANGE_PATTERN` | const | The exact three-component floor accepted for a foreign peer's range. |
|
|
107
|
+
| `FOREIGN_NAME_PATTERN` | const | The package name syntax for a dependency this package does not publish. |
|
|
107
108
|
| `GLOBAL_SETUP_PATH` | const | The shared Vitest global-setup module whose presence makes a workspace `global`. |
|
|
108
109
|
| `GROUPS` | const | The seven `Group` values in plan order, frozen. |
|
|
109
110
|
| `GUIDES_TEST_PATH` | const | The guide-parity proof whose presence selects the planned `guides` project. |
|
|
@@ -465,7 +466,8 @@ the registry, so `new` fails when the registry names no release for a package it
|
|
|
465
466
|
workspace would otherwise declare a dependency that does not resolve.
|
|
466
467
|
|
|
467
468
|
`new --bin` creates the executable entry, its test, and its scoped Vite and TypeScript wrappers. The
|
|
468
|
-
other structural facts do not need creation flags. Add `tests/
|
|
469
|
+
other structural facts do not need creation flags. Add a root `tests/setup*.test.ts` proof for
|
|
470
|
+
`setup`, `tests/guides.test.ts` for `guides`,
|
|
469
471
|
`tests/distribution.test.ts` for `distribution`, `tests/integration.test.ts` for `integration`,
|
|
470
472
|
`tests/conformance.test.ts` for `conformance`, `tests/setupService.ts` for `service`,
|
|
471
473
|
`tests/setupGlobal.ts` for `global`, and `configs/app/vite.showcase.config.ts` for `showcase`;
|
|
@@ -478,8 +480,9 @@ vendor list from edited text.
|
|
|
478
480
|
`audit`, `repair`, `catalog`, and `overwrite` derive the blueprint from the target itself. The name
|
|
479
481
|
and the declared `@orkestrel/*` packages come from `package.json`. The two environment axes come
|
|
480
482
|
from the directories the target actually ships, because a directory is the fact and a declaration
|
|
481
|
-
beside it could disagree.
|
|
482
|
-
`bin`, `tests/
|
|
483
|
+
beside it could disagree. Nine more facts come from exact-case files: `src/bin/main.ts` selects
|
|
484
|
+
`bin`, each root `tests/setup*.test.ts` match selects `setup`, `tests/guides.test.ts` selects
|
|
485
|
+
`guides`, `tests/distribution.test.ts` selects `distribution`,
|
|
483
486
|
`tests/integration.test.ts` selects `integration`, `tests/conformance.test.ts` selects
|
|
484
487
|
`conformance`, `tests/setupService.ts` selects `service`, `tests/setupGlobal.ts` selects `global`,
|
|
485
488
|
and `configs/app/vite.showcase.config.ts` selects `showcase`. A containing directory does not select
|
|
@@ -585,8 +588,14 @@ blueprint.engines // '>=22.12.0'
|
|
|
585
588
|
|
|
586
589
|
`src` selects published library environments and `app` selects private application environments.
|
|
587
590
|
The two axes are independent, so a library-only, an application-only, and a mixed workspace are all
|
|
588
|
-
first class. `dependencies`
|
|
589
|
-
development dependencies and may carry any
|
|
591
|
+
first class. `dependencies` are runtime `@orkestrel/*` packages. A peer in the `@orkestrel` scope is
|
|
592
|
+
a fleet pin; every other peer is a floor. `extras` are development dependencies and may carry any
|
|
593
|
+
valid npm name. A peer reaches the generated workspace through two representations:
|
|
594
|
+
`Blueprint.peers` validates the scope rule and compiles the manifest declarations, while the
|
|
595
|
+
`peers` binding in the generated `vite.config.ts` derives from the target's live
|
|
596
|
+
`peerDependencies`. Each published build face — core, browser, server, and `bin` — externalizes
|
|
597
|
+
every name in that binding, so a peer the workspace declares by hand, such as `vitest`, is left as
|
|
598
|
+
an import in the emitted bundle rather than inlined into it.
|
|
590
599
|
|
|
591
600
|
One published environment owns the package root directly. Several published environments require
|
|
592
601
|
`core`, which owns that root while each other environment keeps its subpath. A multi-environment
|
|
@@ -596,10 +605,14 @@ because the shape is chosen once and read afterwards: `new` refuses the advisory
|
|
|
596
605
|
`repair` need the plan to describe and restore a target that already has that shape. A library
|
|
597
606
|
caller creating a workspace holds the same refusal, and the Compile section below states it.
|
|
598
607
|
|
|
599
|
-
`bin`, `guides`, `distribution`, `integration`, `conformance`, `service`, `vendors`,
|
|
600
|
-
`showcase` are structural facts. Each is set only when the workspace physically ships
|
|
601
|
-
or exact-case file that defines it, never because of the workspace's name and never
|
|
602
|
-
sibling fact is set.
|
|
608
|
+
`bin`, `setup`, `guides`, `distribution`, `integration`, `conformance`, `service`, `vendors`,
|
|
609
|
+
`global`, and `showcase` are structural facts. Each is set only when the workspace physically ships
|
|
610
|
+
the directory or exact-case file that defines it, never because of the workspace's name and never
|
|
611
|
+
because a sibling fact is set.
|
|
612
|
+
|
|
613
|
+
`setup` registers every root `tests/setup*.test.ts` proof in one Node project that loads
|
|
614
|
+
`tests/setup.ts`. A nested or wrong-case match does not set the fact. The generated manifest emits
|
|
615
|
+
`test:setup` and invokes it from `test` only while the fact is set.
|
|
603
616
|
|
|
604
617
|
A structural fact is read when a verb runs, not when the file appears. Writing
|
|
605
618
|
`tests/integration.test.ts` into a workspace sets the fact, but the root configuration on disk was
|
package/dist/host/manifest.json
CHANGED
|
@@ -80,11 +80,6 @@
|
|
|
80
80
|
"destination": ".agents/skills/orkestrel-build-application/agents/openai.yaml",
|
|
81
81
|
"executable": false
|
|
82
82
|
},
|
|
83
|
-
{
|
|
84
|
-
"storage": "agents/skills/orkestrel-build-application/references/application.md",
|
|
85
|
-
"destination": ".agents/skills/orkestrel-build-application/references/application.md",
|
|
86
|
-
"executable": false
|
|
87
|
-
},
|
|
88
83
|
{
|
|
89
84
|
"storage": "agents/skills/orkestrel-debrief/SKILL.md",
|
|
90
85
|
"destination": ".agents/skills/orkestrel-debrief/SKILL.md",
|
|
@@ -315,6 +310,11 @@
|
|
|
315
310
|
"destination": ".claude/rules/workspace.md",
|
|
316
311
|
"executable": false
|
|
317
312
|
},
|
|
313
|
+
{
|
|
314
|
+
"storage": "claude/rules/writing.md",
|
|
315
|
+
"destination": ".claude/rules/writing.md",
|
|
316
|
+
"executable": false
|
|
317
|
+
},
|
|
318
318
|
{
|
|
319
319
|
"storage": "claude/settings.json",
|
|
320
320
|
"destination": ".claude/settings.json",
|
|
@@ -440,6 +440,11 @@
|
|
|
440
440
|
"destination": "configs/helpers.ts",
|
|
441
441
|
"executable": false
|
|
442
442
|
},
|
|
443
|
+
{
|
|
444
|
+
"storage": "configs/policy.ts",
|
|
445
|
+
"destination": "configs/policy.ts",
|
|
446
|
+
"executable": false
|
|
447
|
+
},
|
|
443
448
|
{
|
|
444
449
|
"storage": "cursor/mcp.json",
|
|
445
450
|
"destination": ".cursor/mcp.json",
|
|
@@ -546,7 +551,6 @@
|
|
|
546
551
|
".agents/skills/orkestrel-align-packages/references",
|
|
547
552
|
".agents/skills/orkestrel-build-application",
|
|
548
553
|
".agents/skills/orkestrel-build-application/agents",
|
|
549
|
-
".agents/skills/orkestrel-build-application/references",
|
|
550
554
|
".agents/skills/orkestrel-debrief",
|
|
551
555
|
".agents/skills/orkestrel-debrief/agents",
|
|
552
556
|
".agents/skills/orkestrel-debrief/references",
|
|
@@ -576,5 +580,5 @@
|
|
|
576
580
|
".codex/agents",
|
|
577
581
|
".cursor/rules"
|
|
578
582
|
],
|
|
579
|
-
"digest": "
|
|
583
|
+
"digest": "cdc9d27a693c15833702e2afe0a7ef1da3f4cdec10dccfb3d5f4a6920d57acd8"
|
|
580
584
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|