@sublang/slc 0.11.0 → 0.13.0
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 +2 -2
- package/dist/slc.config.template.yaml +2 -2
- package/dist/verify-coverage.d.ts +2 -1
- package/dist/verify-coverage.d.ts.map +1 -1
- package/dist/verify-coverage.js +59 -2
- package/dist/verify-coverage.js.map +1 -1
- package/dist/verify.d.ts +3 -2
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +19 -8
- package/dist/verify.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -157,11 +157,11 @@ either, per key.
|
|
|
157
157
|
```yaml
|
|
158
158
|
# slc.config.yaml
|
|
159
159
|
agent: claude-code # claude-code | codex | gemini | opencode
|
|
160
|
-
model: claude-opus-
|
|
160
|
+
model: claude-opus-5-5 # optional; omit to use the agent CLI's default
|
|
161
161
|
effort: high # optional adapter-scoped reasoning effort
|
|
162
162
|
fastMode: true # optional adapter-scoped fast mode; false is a literal request
|
|
163
163
|
reviewerAgent: codex # optional; enables reviewed compilation
|
|
164
|
-
reviewerModel: gpt-
|
|
164
|
+
reviewerModel: gpt-6-sol # optional reviewer model
|
|
165
165
|
reviewerEffort: xhigh # optional reviewer reasoning effort
|
|
166
166
|
reviewerFastMode: true # optional reviewer fast mode
|
|
167
167
|
stallTimeout: 2400 # seconds of agent silence before a stalled call fails
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
# SLC_REVIEWER_* variables, plus SLC_STALL_TIMEOUT, override these per key
|
|
4
4
|
# (DR-006, DR-022).
|
|
5
5
|
agent: claude-code
|
|
6
|
-
# model: claude-opus-
|
|
6
|
+
# model: claude-opus-5-5
|
|
7
7
|
# effort: high
|
|
8
8
|
# Fast mode is a literal request (true or false) where the agent CLI supports
|
|
9
9
|
# it; omit it to keep the agent CLI's default.
|
|
10
10
|
# fastMode: true
|
|
11
11
|
# Optional independent review/fix loop; disabled until reviewerAgent is set.
|
|
12
12
|
# reviewerAgent: codex
|
|
13
|
-
# reviewerModel: gpt-
|
|
13
|
+
# reviewerModel: gpt-6-sol
|
|
14
14
|
# reviewerEffort: xhigh
|
|
15
15
|
# reviewerFastMode: true
|
|
16
16
|
# Seconds of agent inactivity before a stalled call fails the run (DR-019);
|
|
@@ -13,9 +13,10 @@ interface MachineLike {
|
|
|
13
13
|
provide(implementations: {
|
|
14
14
|
actors: Record<string, unknown>;
|
|
15
15
|
}): MachineLike;
|
|
16
|
-
/** XState exposes `setup()`-registered guards here. */
|
|
16
|
+
/** XState exposes `setup()`-registered guards and actions here. */
|
|
17
17
|
implementations?: {
|
|
18
18
|
guards?: Record<string, unknown>;
|
|
19
|
+
actions?: Record<string, unknown>;
|
|
19
20
|
};
|
|
20
21
|
/** XState's resolved state nodes expose the actual invocation actor ids. */
|
|
21
22
|
root?: ResolvedStateNodeLike;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-coverage.d.ts","sourceRoot":"","sources":["../src/verify-coverage.ts"],"names":[],"mappings":"AA8BA,OAAO,
|
|
1
|
+
{"version":3,"file":"verify-coverage.d.ts","sourceRoot":"","sources":["../src/verify-coverage.ts"],"names":[],"mappings":"AA8BA,OAAO,EAeL,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AAErB,sEAAsE;AACtE,eAAO,MAAM,aAAa,YAAY,CAAC;AAavC,iFAAiF;AACjF,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,cAGC;CACF;AAyDD,6DAA6D;AAC7D,UAAU,WAAW;IACnB,MAAM,EAAE,iBAAiB,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,OAAO,CAAC,eAAe,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,WAAW,CAAC;IAC3E,mEAAmE;IACnE,eAAe,CAAC,EAAE;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC;IACF,4EAA4E;IAC5E,IAAI,CAAC,EAAE,qBAAqB,CAAC;CAC9B;AAyBD,UAAU,qBAAqB;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjC;AAqJD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,OAAO,GAAG,WAAW,CAwB3D;AAopCD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAU/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,EAC7D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,GAAE,SAAS,OAAO,EAAO,GACnC,OAAO,CAST;AAg6DD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CA+IjE;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,OAAO,EAClB,IAAI,GAAE;IACJ,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GACL,OAAO,CAAC,MAAM,EAAE,CAAC,CAkCnB;AAyvBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CA8BT;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAmBnD"}
|
package/dist/verify-coverage.js
CHANGED
|
@@ -24,7 +24,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
|
24
24
|
import { join } from 'node:path';
|
|
25
25
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
26
26
|
import { createActor, fromPromise } from 'xstate';
|
|
27
|
-
import { AWAIT_BOSS_REPLY_STATE, BOSS_REPLY_EVENT,
|
|
27
|
+
import { AWAIT_BOSS_REPLY_STATE, BOSS_REPLY_EVENT, INTERRUPT_EVENT, NEEDS_BOSS_REPLY, VERIFY_MODULE, controllerDecisionNearMiss, enumerateCaptainStates, enumerateScriptStates, initialStateTarget, isControllerDecisionResult, isControllerMachine, loadFsmModule, normalizeArms, } from './verify.js';
|
|
28
28
|
/** The `gears2fsm`-mandated captain actor name a machine declares. */
|
|
29
29
|
export const CAPTAIN_ACTOR = 'captain';
|
|
30
30
|
// Each check owns its resources, including concurrent checks and async actor
|
|
@@ -539,6 +539,40 @@ function tagsOf(state) {
|
|
|
539
539
|
return [state.tags];
|
|
540
540
|
return Array.isArray(state.tags) ? state.tags : [];
|
|
541
541
|
}
|
|
542
|
+
/** XState's built-in actions that send the machine an event by themselves. */
|
|
543
|
+
const EVENT_RAISING_ACTION_TYPES = new Set([
|
|
544
|
+
'xstate.raise',
|
|
545
|
+
'xstate.sendTo',
|
|
546
|
+
'xstate.enqueueActions',
|
|
547
|
+
]);
|
|
548
|
+
/**
|
|
549
|
+
* Whether an `entry` or `exit` action list can move the machine without an
|
|
550
|
+
* external event: a built-in raise, send, or enqueue, written inline or behind
|
|
551
|
+
* a `setup()`-registered name. An action that only assigns keeps a parked leaf
|
|
552
|
+
* inert (DR-053).
|
|
553
|
+
*/
|
|
554
|
+
function raisesEvent(machine, actions) {
|
|
555
|
+
const typeOf = (action) => {
|
|
556
|
+
if (typeof action === 'string')
|
|
557
|
+
return action;
|
|
558
|
+
if ((typeof action === 'object' && action !== null) ||
|
|
559
|
+
typeof action === 'function') {
|
|
560
|
+
const type = action.type;
|
|
561
|
+
return typeof type === 'string' ? type : undefined;
|
|
562
|
+
}
|
|
563
|
+
return undefined;
|
|
564
|
+
};
|
|
565
|
+
const list = actions === undefined ? [] : Array.isArray(actions) ? actions : [actions];
|
|
566
|
+
return list.some((action) => {
|
|
567
|
+
const type = typeOf(action);
|
|
568
|
+
if (type === undefined)
|
|
569
|
+
return false;
|
|
570
|
+
if (EVENT_RAISING_ACTION_TYPES.has(type))
|
|
571
|
+
return true;
|
|
572
|
+
const named = typeOf(machine.implementations?.actions?.[type]);
|
|
573
|
+
return named !== undefined && EVENT_RAISING_ACTION_TYPES.has(named);
|
|
574
|
+
});
|
|
575
|
+
}
|
|
542
576
|
function stateRefForTarget(refs, target, source) {
|
|
543
577
|
const absolute = target.startsWith('#');
|
|
544
578
|
const normalized = absolute
|
|
@@ -2441,7 +2475,7 @@ async function runFsmCoverage(fsmModule, sourceText) {
|
|
|
2441
2475
|
const detail = nearMiss.missing.length > 0
|
|
2442
2476
|
? `missing ${JSON.stringify(nearMiss.missing[0])}`
|
|
2443
2477
|
: `extra ${JSON.stringify(nearMiss.extra[0])}`;
|
|
2444
|
-
findings.push(`state ${captain.binding.stateId}: controller decision contract near-miss (${detail}); the controller domain requires exactly ${
|
|
2478
|
+
findings.push(`state ${captain.binding.stateId}: controller decision contract near-miss (${detail}); the controller domain requires exactly ${nearMiss.domain.join(', ')}`);
|
|
2445
2479
|
}
|
|
2446
2480
|
for (const ref of parallelRefs) {
|
|
2447
2481
|
await coverageYield();
|
|
@@ -2604,6 +2638,29 @@ async function runFsmCoverage(fsmModule, sourceText) {
|
|
|
2604
2638
|
resolveGuard(machine, rawGuard) === undefined)) {
|
|
2605
2639
|
continue;
|
|
2606
2640
|
}
|
|
2641
|
+
// A controller's final defensive fallback rejects malformed actor
|
|
2642
|
+
// output. It is not a second business action for a valid result,
|
|
2643
|
+
// provided the parked leaf it enters cannot leave by itself.
|
|
2644
|
+
const targetRef = stateRefForTarget(refs, target, captain.ref);
|
|
2645
|
+
if (isControllerDecisionResult(state.result) &&
|
|
2646
|
+
rawGuard === undefined &&
|
|
2647
|
+
index === rawDoneArms.length - 1 &&
|
|
2648
|
+
targetRef !== undefined &&
|
|
2649
|
+
tagsOf(targetRef.state).includes('playbook.parked') &&
|
|
2650
|
+
targetRef.state.invoke === undefined &&
|
|
2651
|
+
targetRef.state.states === undefined &&
|
|
2652
|
+
!Object.hasOwn(targetRef.state, 'always') &&
|
|
2653
|
+
!Object.hasOwn(targetRef.state, 'after') &&
|
|
2654
|
+
!raisesEvent(machine, targetRef.state.entry) &&
|
|
2655
|
+
!raisesEvent(machine, targetRef.state.exit) &&
|
|
2656
|
+
!rawDoneArms
|
|
2657
|
+
.slice(0, index)
|
|
2658
|
+
.some((otherArm) => stateRefForTarget(refs, rawArmTarget(otherArm) ?? '', captain.ref) === targetRef) &&
|
|
2659
|
+
transitionArms(captain.invocation.onError).some((errorArm, errorIndex, errorArms) => errorIndex === errorArms.length - 1 &&
|
|
2660
|
+
armGuard(errorArm) === undefined &&
|
|
2661
|
+
stateRefForTarget(refs, rawArmTarget(errorArm) ?? '', captain.ref) === targetRef)) {
|
|
2662
|
+
continue;
|
|
2663
|
+
}
|
|
2607
2664
|
const guard = orderedArmPredicate(machine, rawDoneArms, index);
|
|
2608
2665
|
if (guard === undefined)
|
|
2609
2666
|
continue;
|