@orkestrel/scaffold 0.0.101 → 0.0.102
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/brief.js +6 -14
- package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +41 -28
- package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +5 -12
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +25 -13
- package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +18 -25
- package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +11 -9
- package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +233 -232
- package/dist/agents/skills/orkestrel-publish/scripts/compare.js +95 -89
- package/dist/agents/skills/orkestrel-publish/scripts/pins.js +5 -7
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +1273 -0
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +99 -89
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +54 -52
- package/dist/agents/skills/orkestrel-scout/scripts/map.js +160 -161
- package/dist/bin/main.js +483 -444
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +1 -0
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +8 -11
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +58 -28
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +5 -10
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +31 -12
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +28 -23
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +12 -10
- package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +318 -237
- package/dist/host/agents/skills/orkestrel-journey/references/statechart.md +2 -5
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +7 -6
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +12 -10
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +12 -5
- package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +124 -82
- package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +5 -7
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1655 -0
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +128 -97
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +70 -55
- package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +215 -155
- package/dist/host/claude/rules/architecture.md +2 -2
- package/dist/host/claude/rules/tests.md +8 -2
- package/dist/host/claude/rules/typescript.md +130 -0
- package/dist/host/claude/rules/workspace.md +30 -12
- package/dist/host/configs/helpers.ts +206 -133
- package/dist/host/configs/policy.ts +110 -105
- package/dist/host/guides/scaffold.md +244 -170
- package/dist/host/manifest.json +35 -29
- package/dist/host/tests/config.test.ts +1220 -633
- package/dist/host/tests/policy.test.ts +19 -0
- package/dist/host/tests/setupPolicy.ts +1669 -985
- package/dist/src/core/index.cjs +1595 -1686
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +202 -18
- package/dist/src/core/index.d.ts +202 -18
- package/dist/src/core/index.js +1590 -1687
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +448 -392
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +1182 -1052
- package/dist/src/server/index.d.ts +1182 -1052
- package/dist/src/server/index.js +447 -395
- package/dist/src/server/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -536,31 +536,29 @@ export function isPolicyDeclaredFunction(node: PolicyExpression): boolean {
|
|
|
536
536
|
|
|
537
537
|
/** Returns a policy function's position through parentheses, object values, and array elements. */
|
|
538
538
|
export function functionToPolicyPosition(node: PolicyExpression): PolicyExpression {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
)
|
|
554
|
-
position = parent.parent
|
|
555
|
-
continue
|
|
556
|
-
}
|
|
557
|
-
if (parent.type === 'ArrayExpression' && parent.elements?.includes(position) === true) {
|
|
558
|
-
position = parent
|
|
559
|
-
continue
|
|
560
|
-
}
|
|
561
|
-
break
|
|
539
|
+
const parent = node.parent
|
|
540
|
+
if (parent === undefined || parent === null) return node
|
|
541
|
+
if (parent.type === 'ParenthesizedExpression') return functionToPolicyPosition(parent)
|
|
542
|
+
if (
|
|
543
|
+
parent.type === 'Property' &&
|
|
544
|
+
parent.kind === 'init' &&
|
|
545
|
+
parent.method === false &&
|
|
546
|
+
parent.computed !== true &&
|
|
547
|
+
parent.value === node &&
|
|
548
|
+
parent.parent?.type === 'ObjectExpression'
|
|
549
|
+
) {
|
|
550
|
+
return functionToPolicyPosition(parent.parent)
|
|
551
|
+
}
|
|
552
|
+
if (parent.type === 'ArrayExpression' && parent.elements?.includes(node) === true) {
|
|
553
|
+
return functionToPolicyPosition(parent)
|
|
562
554
|
}
|
|
563
|
-
return
|
|
555
|
+
return node
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Returns a policy node's position through its enclosing parentheses alone. */
|
|
559
|
+
export function nodeToPolicyOuter(node: PolicyExpression): PolicyExpression {
|
|
560
|
+
const parent = node.parent
|
|
561
|
+
return parent?.type === 'ParenthesizedExpression' ? nodeToPolicyOuter(parent) : node
|
|
564
562
|
}
|
|
565
563
|
|
|
566
564
|
/** Reports whether a literal position is admitted as an argument, return, or arrow body. */
|
|
@@ -611,20 +609,22 @@ export function isPolicyMethod(node: PolicyExpression): boolean {
|
|
|
611
609
|
/**
|
|
612
610
|
* Reports whether a policy function sits inside another function before any class-expression
|
|
613
611
|
* boundary.
|
|
612
|
+
*
|
|
613
|
+
* @param node - The function node whose ancestors are read.
|
|
614
|
+
* @param method - If `true`, a method body was already crossed on the way up; if `false`, none was.
|
|
615
|
+
* Default: `false`.
|
|
616
|
+
* @returns True if a non-method function, or a method inside a class declaration, encloses the node
|
|
617
|
+
* before a class expression does; false otherwise.
|
|
614
618
|
*/
|
|
615
|
-
export function hasPolicyFunctionAncestor(node: PolicyExpression): boolean {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
if (!isPolicyMethod(parent)) return true
|
|
623
|
-
method = true
|
|
624
|
-
}
|
|
625
|
-
parent = parent.parent
|
|
619
|
+
export function hasPolicyFunctionAncestor(node: PolicyExpression, method = false): boolean {
|
|
620
|
+
const parent = node.parent
|
|
621
|
+
if (parent === undefined || parent === null) return method
|
|
622
|
+
if (parent.type === 'ClassExpression') return false
|
|
623
|
+
if (parent.type === 'ClassDeclaration' && method) return true
|
|
624
|
+
if (isPolicyFunction(parent)) {
|
|
625
|
+
return !isPolicyMethod(parent) || hasPolicyFunctionAncestor(parent, true)
|
|
626
626
|
}
|
|
627
|
-
return method
|
|
627
|
+
return hasPolicyFunctionAncestor(parent, method)
|
|
628
628
|
}
|
|
629
629
|
|
|
630
630
|
/**
|
|
@@ -634,15 +634,11 @@ export function hasPolicyFunctionAncestor(node: PolicyExpression): boolean {
|
|
|
634
634
|
* reads module regions rather than class members.
|
|
635
635
|
*/
|
|
636
636
|
export function functionToPolicyRegion(node: PolicyExpression): PolicyExpression | undefined {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
current = parent
|
|
643
|
-
parent = parent.parent
|
|
644
|
-
}
|
|
645
|
-
return undefined
|
|
637
|
+
const parent = node.parent
|
|
638
|
+
if (parent === undefined || parent === null) return undefined
|
|
639
|
+
if (parent.type === 'ClassDeclaration' || parent.type === 'ClassExpression') return undefined
|
|
640
|
+
if (parent.type === 'Program') return statementToPolicyDeclaration(node)
|
|
641
|
+
return functionToPolicyRegion(parent)
|
|
646
642
|
}
|
|
647
643
|
|
|
648
644
|
/** Lists every module function a top-level statement declares, paired with its declared name. */
|
|
@@ -651,15 +647,16 @@ export function statementToPolicyBindings(node: PolicyExpression): readonly Poli
|
|
|
651
647
|
return [{ node, name: identifierToPolicyName(node.id) }]
|
|
652
648
|
}
|
|
653
649
|
if (node.type !== 'VariableDeclaration') return []
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
650
|
+
// The iterator consumes one declarator at a time and reads a hole as an `undefined` declarator,
|
|
651
|
+
// as a `for…of` over the list would.
|
|
652
|
+
return Iterator.from(node.declarations ?? [])
|
|
653
|
+
.flatMap((declarator) => {
|
|
654
|
+
const init = declarator.init
|
|
655
|
+
if (init === undefined || init === null || !isPolicyFunction(init)) return []
|
|
656
|
+
const name = identifierToPolicyName(declarator.id)
|
|
657
|
+
return name === undefined ? [] : [{ node: declarator, name }]
|
|
658
|
+
})
|
|
659
|
+
.toArray()
|
|
663
660
|
}
|
|
664
661
|
|
|
665
662
|
/** Reports whether a call trims a whole payload before splitting it on a line feed. */
|
|
@@ -735,11 +732,9 @@ export function stripPolicyCode(text: string): string {
|
|
|
735
732
|
* @returns One hit per match, each naming its row and the offset the match starts at.
|
|
736
733
|
*/
|
|
737
734
|
export function textToPolicyHits(text: string): readonly PolicyHit[] {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}
|
|
742
|
-
return hits.sort((left, right) => left.index - right.index)
|
|
735
|
+
return POLICY_BANNED_TERMS.flatMap((term) =>
|
|
736
|
+
[...text.matchAll(term.pattern)].map((match) => ({ term, index: match.index })),
|
|
737
|
+
).sort((left, right) => left.index - right.index)
|
|
743
738
|
}
|
|
744
739
|
|
|
745
740
|
/**
|
|
@@ -749,13 +744,15 @@ export function textToPolicyHits(text: string): readonly PolicyHit[] {
|
|
|
749
744
|
* @returns The description with continuation markers removed and whitespace collapsed.
|
|
750
745
|
*/
|
|
751
746
|
export function commentToPolicyParagraph(comment: PolicyComment): string {
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
747
|
+
const lines = comment.value
|
|
748
|
+
.split(POLICY_BREAK_PATTERN)
|
|
749
|
+
.map((line) => line.replace(POLICY_MARKER_PATTERN, ''))
|
|
750
|
+
const end = lines.findIndex((text) => text.trimStart().startsWith('@'))
|
|
751
|
+
return lines
|
|
752
|
+
.slice(0, end === -1 ? lines.length : end)
|
|
753
|
+
.join(' ')
|
|
754
|
+
.replace(/\s+/gu, ' ')
|
|
755
|
+
.trim()
|
|
759
756
|
}
|
|
760
757
|
|
|
761
758
|
/**
|
|
@@ -795,27 +792,32 @@ export function programToPolicyDocs(
|
|
|
795
792
|
node: PolicyExpression,
|
|
796
793
|
sourceCode: PolicySourceCode,
|
|
797
794
|
): readonly PolicyDoc[] {
|
|
795
|
+
// The iterator consumes one entry at a time and reads a hole as an `undefined` entry, as a
|
|
796
|
+
// `for…of` over the list would. The comments are read only for an export statement, once per
|
|
797
|
+
// statement, and every comment is read where a `findLast` would stop at the nearest one.
|
|
798
798
|
const comments = sourceCode.getAllComments()
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
799
|
+
return Iterator.from(programToPolicyStatements(node))
|
|
800
|
+
.flatMap((statement) => {
|
|
801
|
+
if (!statement.type.startsWith('Export')) return []
|
|
802
|
+
const start = statement.range[0]
|
|
803
|
+
const previous = Iterator.from(comments)
|
|
804
|
+
.flatMap((comment) => (comment.range[1] <= start ? [comment] : []))
|
|
805
|
+
.toArray()
|
|
806
|
+
.at(-1)
|
|
807
|
+
if (previous === undefined || previous.type !== 'Block') return []
|
|
808
|
+
if (!previous.value.startsWith('*')) return []
|
|
809
|
+
if (sourceCode.text.slice(previous.range[1], start).trim() !== '') return []
|
|
810
|
+
const declaration = statement.declaration
|
|
811
|
+
return [
|
|
812
|
+
{
|
|
813
|
+
comment: previous,
|
|
814
|
+
name:
|
|
815
|
+
identifierToPolicyName(declaration?.id) ??
|
|
816
|
+
identifierToPolicyName(declaration?.declarations?.[0]?.id),
|
|
817
|
+
},
|
|
818
|
+
]
|
|
816
819
|
})
|
|
817
|
-
|
|
818
|
-
return docs
|
|
820
|
+
.toArray()
|
|
819
821
|
}
|
|
820
822
|
|
|
821
823
|
/** Reports a doc block whose first sentence is not a third-person summary of its own symbol. */
|
|
@@ -981,8 +983,7 @@ export function reportFunction(context: PolicyContext, node: PolicyExpression):
|
|
|
981
983
|
return
|
|
982
984
|
}
|
|
983
985
|
if (region.type !== 'VariableDeclaration') return
|
|
984
|
-
|
|
985
|
-
while (position.parent?.type === 'ParenthesizedExpression') position = position.parent
|
|
986
|
+
const position = nodeToPolicyOuter(node)
|
|
986
987
|
// Module placement admits direct callbacks; a literal member still belongs in a function file.
|
|
987
988
|
if (
|
|
988
989
|
(node.type === 'ArrowFunctionExpression' || node.id === null) &&
|
|
@@ -1062,24 +1063,28 @@ export function reportDomain(context: PolicyContext, node: PolicyExpression): vo
|
|
|
1062
1063
|
}
|
|
1063
1064
|
if (!isPolicyDomain(context.filename, context.cwd)) return
|
|
1064
1065
|
const expected = fileToPolicyStem(file)
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1066
|
+
// The iterator consumes one statement at a time and reads a hole as an `undefined` statement, as
|
|
1067
|
+
// a `for…of` over the body would. Each statement is judged whole before the next is read.
|
|
1068
|
+
const members = Iterator.from(programToPolicyStatements(node))
|
|
1069
|
+
.flatMap((statement) => {
|
|
1070
|
+
if (statement.type === 'ImportDeclaration') return []
|
|
1071
|
+
const declaration = statementToPolicyDeclaration(statement)
|
|
1072
|
+
if (declaration === undefined || !isPolicyDeclaredFunction(declaration)) {
|
|
1073
|
+
return [{ implementation: false, malformed: true }]
|
|
1074
|
+
}
|
|
1075
|
+
return [
|
|
1076
|
+
{
|
|
1077
|
+
implementation: declaration.type === 'FunctionDeclaration',
|
|
1078
|
+
malformed:
|
|
1079
|
+
statement.type !== 'ExportNamedDeclaration' ||
|
|
1080
|
+
identifierToPolicyName(declaration.id) !== expected,
|
|
1081
|
+
},
|
|
1082
|
+
]
|
|
1083
|
+
})
|
|
1084
|
+
.toArray()
|
|
1085
|
+
const implementations = members.filter(({ implementation }) => implementation).length
|
|
1086
|
+
const malformed = members.some((member) => member.malformed)
|
|
1087
|
+
if (implementations !== 1 || malformed) context.report({ node, messageId: 'module' })
|
|
1083
1088
|
}
|
|
1084
1089
|
|
|
1085
1090
|
/** Reports source that reads the host line ending or splits arrived text before trimming it. */
|