@devflow-tools/sdk 0.17.2 → 0.17.4

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.
Files changed (52) hide show
  1. package/dist/action-lease.d.ts +65 -0
  2. package/dist/action-lease.d.ts.map +1 -0
  3. package/dist/action-lease.js +153 -0
  4. package/dist/action-lease.js.map +1 -0
  5. package/dist/action-lease.test.d.ts +2 -0
  6. package/dist/action-lease.test.d.ts.map +1 -0
  7. package/dist/action-lease.test.js +67 -0
  8. package/dist/action-lease.test.js.map +1 -0
  9. package/dist/canonical-action-binding.d.ts.map +1 -1
  10. package/dist/canonical-action-binding.js +29 -1
  11. package/dist/canonical-action-binding.js.map +1 -1
  12. package/dist/canonical-action-binding.test.d.ts +2 -0
  13. package/dist/canonical-action-binding.test.d.ts.map +1 -0
  14. package/dist/canonical-action-binding.test.js +42 -0
  15. package/dist/canonical-action-binding.test.js.map +1 -0
  16. package/dist/capability-rollout.d.ts +56 -0
  17. package/dist/capability-rollout.d.ts.map +1 -1
  18. package/dist/capability-rollout.js +178 -1
  19. package/dist/capability-rollout.js.map +1 -1
  20. package/dist/index.d.ts +5 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +5 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/semantic-resolution.d.ts +104 -0
  25. package/dist/semantic-resolution.d.ts.map +1 -0
  26. package/dist/semantic-resolution.js +178 -0
  27. package/dist/semantic-resolution.js.map +1 -0
  28. package/dist/semantic-resolution.test.d.ts +2 -0
  29. package/dist/semantic-resolution.test.d.ts.map +1 -0
  30. package/dist/semantic-resolution.test.js +106 -0
  31. package/dist/semantic-resolution.test.js.map +1 -0
  32. package/dist/task-runtime-reducer.d.ts +3 -0
  33. package/dist/task-runtime-reducer.d.ts.map +1 -0
  34. package/dist/task-runtime-reducer.js +219 -0
  35. package/dist/task-runtime-reducer.js.map +1 -0
  36. package/dist/task-runtime-store.d.ts +34 -0
  37. package/dist/task-runtime-store.d.ts.map +1 -0
  38. package/dist/task-runtime-store.js +126 -0
  39. package/dist/task-runtime-store.js.map +1 -0
  40. package/dist/task-runtime.d.ts +114 -0
  41. package/dist/task-runtime.d.ts.map +1 -0
  42. package/dist/task-runtime.js +157 -0
  43. package/dist/task-runtime.js.map +1 -0
  44. package/dist/task-runtime.test.d.ts +2 -0
  45. package/dist/task-runtime.test.d.ts.map +1 -0
  46. package/dist/task-runtime.test.js +60 -0
  47. package/dist/task-runtime.test.js.map +1 -0
  48. package/dist/types/task-context-envelope.d.ts +8 -0
  49. package/dist/types/task-context-envelope.d.ts.map +1 -1
  50. package/dist/types/task-semantic-control.d.ts +6 -2
  51. package/dist/types/task-semantic-control.d.ts.map +1 -1
  52. package/package.json +3 -3
@@ -0,0 +1,65 @@
1
+ import type { CanonicalAction } from './types/task-context-envelope.js';
2
+ export type ToolFieldClass = 'locked' | 'constrained' | 'advisory' | 'transport';
3
+ export interface ToolFieldPolicyV1 {
4
+ class: ToolFieldClass;
5
+ type?: 'string' | 'number' | 'boolean' | 'array' | 'object';
6
+ enum?: Array<string | number | boolean>;
7
+ minimum?: number;
8
+ maximum?: number;
9
+ pattern?: string;
10
+ }
11
+ export interface ToolFieldManifestV1 {
12
+ schemaVersion: 'tool-field-manifest.v1';
13
+ tool: string;
14
+ version: string;
15
+ fields: Record<string, ToolFieldPolicyV1>;
16
+ }
17
+ export interface ActionLeaseV1 {
18
+ schemaVersion: 'action-lease.v1';
19
+ leaseId: string;
20
+ taskSpecHash: string;
21
+ manifestVersion: string;
22
+ tool: string;
23
+ projectRealpathHash: string;
24
+ operationMode: string;
25
+ lockedInputHash: string;
26
+ targets: Array<{
27
+ identityId: string;
28
+ path: string;
29
+ expectedState: 'existing' | 'missing' | 'unknown';
30
+ contentHash?: string;
31
+ }>;
32
+ verificationPlanHash: string;
33
+ issuedAt: number;
34
+ expiresAt: number;
35
+ leaseHash: string;
36
+ }
37
+ export declare function canonicalToolFieldManifest(action: CanonicalAction): ToolFieldManifestV1;
38
+ export declare function issueActionLease(input: {
39
+ taskSpecHash: string;
40
+ action: CanonicalAction;
41
+ manifest: ToolFieldManifestV1;
42
+ projectRoot: string;
43
+ targets: ActionLeaseV1['targets'];
44
+ issuedAt?: number;
45
+ ttlMs?: number;
46
+ }): ActionLeaseV1;
47
+ export declare function validateActionLease(input: {
48
+ lease: ActionLeaseV1;
49
+ manifest: ToolFieldManifestV1;
50
+ authenticated: boolean;
51
+ activeTaskSpecHash: string;
52
+ projectRoot: string;
53
+ toolName: string;
54
+ operationMode: string;
55
+ args: Record<string, unknown>;
56
+ currentTargets: ActionLeaseV1['targets'];
57
+ now?: number;
58
+ }): {
59
+ valid: true;
60
+ } | {
61
+ valid: false;
62
+ reason: string;
63
+ };
64
+ export declare function projectRealpathHash(projectRoot: string): string;
65
+ //# sourceMappingURL=action-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-lease.d.ts","sourceRoot":"","sources":["../src/action-lease.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGxE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,CAAC;AAEjF,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5D,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,wBAAwB,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,iBAAiB,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;QAClD,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,eAAe,GAAG,mBAAmB,CASvF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,aAAa,CAkBhB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,cAAc,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAyBrD;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAI/D"}
@@ -0,0 +1,153 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, realpathSync } from 'node:fs';
3
+ import { dirname, isAbsolute, relative, resolve } from 'node:path';
4
+ import { stableRuntimeHash } from './task-runtime.js';
5
+ export function canonicalToolFieldManifest(action) {
6
+ const fields = Object.fromEntries(Object.keys(action.input).map(field => [field, { class: 'locked' }]));
7
+ for (const [field, policy] of Object.entries(action.binding.safeInputVariations ?? {})) {
8
+ fields[field] = { class: 'constrained', ...policy };
9
+ }
10
+ fields.evidenceRefs = { class: 'advisory', type: 'array' };
11
+ return { schemaVersion: 'tool-field-manifest.v1', tool: action.tool, version: '1.0.0', fields };
12
+ }
13
+ export function issueActionLease(input) {
14
+ if (input.manifest.tool !== input.action.tool)
15
+ throw new Error('ACTION_LEASE_MANIFEST_TOOL_MISMATCH');
16
+ const issuedAt = input.issuedAt ?? Date.now();
17
+ const body = {
18
+ schemaVersion: 'action-lease.v1',
19
+ leaseId: `lease:${stableRuntimeHash({ taskSpecHash: input.taskSpecHash, tool: input.action.tool, issuedAt }).slice(0, 32)}`,
20
+ taskSpecHash: input.taskSpecHash,
21
+ manifestVersion: input.manifest.version,
22
+ tool: input.action.tool,
23
+ projectRealpathHash: projectRealpathHash(input.projectRoot),
24
+ operationMode: input.action.binding.operationMode ?? 'unknown',
25
+ lockedInputHash: stableRuntimeHash(lockedInput(input.action.input, input.manifest)),
26
+ targets: input.targets.map(target => ({ ...target })),
27
+ verificationPlanHash: stableRuntimeHash(input.action.verificationPlan),
28
+ issuedAt,
29
+ expiresAt: issuedAt + (input.ttlMs ?? 10 * 60_000),
30
+ };
31
+ return { ...body, leaseHash: stableRuntimeHash(body) };
32
+ }
33
+ export function validateActionLease(input) {
34
+ if (!input.authenticated)
35
+ return invalid('action_lease_unauthenticated');
36
+ if (input.lease.schemaVersion !== 'action-lease.v1')
37
+ return invalid('action_lease_schema_unsupported');
38
+ const { leaseHash: _hash, ...body } = input.lease;
39
+ if (stableRuntimeHash(body) !== input.lease.leaseHash)
40
+ return invalid('action_lease_hash_mismatch');
41
+ if ((input.now ?? Date.now()) > input.lease.expiresAt)
42
+ return invalid('action_lease_expired');
43
+ if (input.lease.taskSpecHash !== input.activeTaskSpecHash)
44
+ return invalid('action_lease_task_mismatch');
45
+ if (input.manifest.tool !== input.lease.tool || input.manifest.version !== input.lease.manifestVersion) {
46
+ return invalid('action_lease_manifest_mismatch');
47
+ }
48
+ if (projectRealpathHash(input.projectRoot) !== input.lease.projectRealpathHash)
49
+ return invalid('action_lease_project_mismatch');
50
+ if (!pathsContained(input.projectRoot, input.args))
51
+ return invalid('action_lease_path_escape');
52
+ if (input.toolName !== input.lease.tool)
53
+ return invalid('action_lease_tool_mismatch');
54
+ if (input.operationMode !== input.lease.operationMode)
55
+ return invalid('action_lease_mode_mismatch');
56
+ if (!targetsEqual(input.lease.targets, input.currentTargets))
57
+ return invalid('action_lease_target_stale');
58
+ if (stableRuntimeHash(lockedInput(input.args, input.manifest)) !== input.lease.lockedInputHash) {
59
+ return invalid('action_lease_locked_field_mismatch');
60
+ }
61
+ for (const [field, value] of Object.entries(input.args)) {
62
+ if (field.startsWith('_devflow_'))
63
+ continue;
64
+ const policy = input.manifest.fields[field];
65
+ if (!policy)
66
+ return invalid(`action_lease_unknown_field:${field}`);
67
+ if (policy.class === 'constrained' && !matches(value, policy))
68
+ return invalid(`action_lease_constraint:${field}`);
69
+ }
70
+ return { valid: true };
71
+ }
72
+ export function projectRealpathHash(projectRoot) {
73
+ let path = resolve(projectRoot);
74
+ try {
75
+ path = realpathSync(path);
76
+ }
77
+ catch { /* Creation targets may not exist yet. */ }
78
+ return createHash('sha256').update(path).digest('hex');
79
+ }
80
+ function lockedInput(args, manifest) {
81
+ return Object.fromEntries(Object.entries(args)
82
+ .filter(([field]) => manifest.fields[field]?.class === 'locked')
83
+ .sort(([a], [b]) => a.localeCompare(b)));
84
+ }
85
+ function pathsContained(projectRoot, args) {
86
+ let root = resolve(projectRoot);
87
+ try {
88
+ root = realpathSync(root);
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ for (const field of ['filePath', 'targetPath', 'path']) {
94
+ const value = args[field];
95
+ if (typeof value !== 'string')
96
+ continue;
97
+ let target = isAbsolute(value) ? resolve(value) : resolve(root, value);
98
+ try {
99
+ target = realpathSync(target);
100
+ }
101
+ catch {
102
+ const parent = dirname(target);
103
+ if (existsSync(parent))
104
+ target = resolve(realpathSync(parent), target.split('/').at(-1));
105
+ }
106
+ const rel = relative(root, target);
107
+ if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`) || isAbsolute(rel))
108
+ return false;
109
+ }
110
+ return true;
111
+ }
112
+ function targetsEqual(left, right) {
113
+ if (left.length !== right.length)
114
+ return false;
115
+ const current = new Map(right.map(target => [target.identityId, normalizeTarget(target)]));
116
+ return left.every(rawExpected => {
117
+ const expected = normalizeTarget(rawExpected);
118
+ const actual = current.get(expected.identityId);
119
+ if (!actual || actual.path !== expected.path)
120
+ return false;
121
+ if (expected.expectedState !== 'unknown' && actual.expectedState !== expected.expectedState)
122
+ return false;
123
+ return expected.contentHash === undefined || expected.contentHash === actual.contentHash;
124
+ });
125
+ }
126
+ function normalizeTarget(target) {
127
+ return { ...target, path: target.path.normalize('NFKC').replaceAll('\\', '/') };
128
+ }
129
+ function matches(value, policy) {
130
+ if (policy.type && runtimeType(value) !== policy.type)
131
+ return false;
132
+ if (policy.enum && !policy.enum.includes(value))
133
+ return false;
134
+ if (typeof value === 'number' && (!Number.isFinite(value)
135
+ || policy.minimum !== undefined && value < policy.minimum
136
+ || policy.maximum !== undefined && value > policy.maximum))
137
+ return false;
138
+ if (typeof value === 'string' && policy.pattern && !new RegExp(policy.pattern, 'u').test(value))
139
+ return false;
140
+ return true;
141
+ }
142
+ function runtimeType(value) {
143
+ if (Array.isArray(value))
144
+ return 'array';
145
+ if (value && typeof value === 'object')
146
+ return 'object';
147
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
148
+ return typeof value;
149
+ }
150
+ return 'other';
151
+ }
152
+ function invalid(reason) { return { valid: false, reason }; }
153
+ //# sourceMappingURL=action-lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-lease.js","sourceRoot":"","sources":["../src/action-lease.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=action-lease.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-lease.test.d.ts","sourceRoot":"","sources":["../src/action-lease.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,67 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { canonicalToolFieldManifest, issueActionLease, validateActionLease } from './action-lease.js';
6
+ const roots = [];
7
+ afterEach(() => { for (const root of roots.splice(0))
8
+ rmSync(root, { recursive: true, force: true }); });
9
+ function fixture() {
10
+ const root = mkdtempSync(join(tmpdir(), 'devflow-action-lease-'));
11
+ roots.push(root);
12
+ mkdirSync(join(root, 'src'));
13
+ writeFileSync(join(root, 'src', 'FlightMonitorPage.tsx'), 'export const FlightMonitorPage = 1;');
14
+ const action = {
15
+ tool: 'react_audit_performance', status: 'required', required: true,
16
+ input: { projectRoot: root, filePath: 'src/FlightMonitorPage.tsx', scope: 'related' },
17
+ binding: {
18
+ projectRoot: root, sessionId: 'session', requestId: 'request', targetAnchors: [],
19
+ requiredContextReceipt: 'context', requiredPolicyFacets: [], operationMode: 'analyze',
20
+ safeInputVariations: {
21
+ componentName: { type: 'string', enum: ['FlightMonitorPage'] },
22
+ maxFindings: { type: 'number', minimum: 1, maximum: 50 },
23
+ },
24
+ },
25
+ verificationPlan: [],
26
+ };
27
+ const manifest = canonicalToolFieldManifest(action);
28
+ const targets = [{
29
+ identityId: 'artifact:flight', path: 'src/FlightMonitorPage.tsx',
30
+ expectedState: 'existing', contentHash: 'content:1',
31
+ }];
32
+ const lease = issueActionLease({
33
+ taskSpecHash: 'spec:1', action, manifest, projectRoot: root, targets, issuedAt: 100, ttlMs: 100,
34
+ });
35
+ return { root, action, manifest, targets, lease };
36
+ }
37
+ describe('ActionLease.v1', () => {
38
+ it('allows bounded safe refinements and rejects unknown or changed semantic fields', () => {
39
+ const x = fixture();
40
+ const base = {
41
+ lease: x.lease, manifest: x.manifest, authenticated: true, activeTaskSpecHash: 'spec:1',
42
+ projectRoot: x.root, toolName: x.action.tool, operationMode: 'analyze', currentTargets: x.targets, now: 150,
43
+ };
44
+ expect(validateActionLease({ ...base, args: { ...x.action.input, componentName: 'FlightMonitorPage', maxFindings: 8 } })).toEqual({ valid: true });
45
+ expect(validateActionLease({ ...base, args: { ...x.action.input, componentName: 'OtherPage' } })).toMatchObject({ valid: false });
46
+ expect(validateActionLease({ ...base, args: { ...x.action.input, surprise: true } })).toMatchObject({ valid: false });
47
+ });
48
+ it('fails closed for expiry, cross-project, stale content, mode drift, and symlink escape', () => {
49
+ const x = fixture();
50
+ const base = {
51
+ lease: x.lease, manifest: x.manifest, authenticated: true, activeTaskSpecHash: 'spec:1',
52
+ projectRoot: x.root, toolName: x.action.tool, operationMode: 'analyze',
53
+ args: x.action.input, currentTargets: x.targets, now: 150,
54
+ };
55
+ expect(validateActionLease({ ...base, now: 201 })).toMatchObject({ reason: 'action_lease_expired' });
56
+ expect(validateActionLease({ ...base, projectRoot: mkdtempSync(join(tmpdir(), 'other-project-')) })).toMatchObject({ reason: 'action_lease_project_mismatch' });
57
+ expect(validateActionLease({ ...base, currentTargets: [{ ...x.targets[0], contentHash: 'changed' }] })).toMatchObject({ reason: 'action_lease_target_stale' });
58
+ expect(validateActionLease({ ...base, operationMode: 'modify' })).toMatchObject({ reason: 'action_lease_mode_mismatch' });
59
+ const outside = mkdtempSync(join(tmpdir(), 'outside-target-'));
60
+ roots.push(outside);
61
+ writeFileSync(join(outside, 'escape.tsx'), 'escape');
62
+ symlinkSync(join(outside, 'escape.tsx'), join(x.root, 'src', 'escape.tsx'));
63
+ expect(validateActionLease({ ...base, args: { ...x.action.input, filePath: 'src/escape.tsx' } }))
64
+ .toMatchObject({ reason: 'action_lease_path_escape' });
65
+ });
66
+ });
67
+ //# sourceMappingURL=action-lease.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-lease.test.js","sourceRoot":"","sources":["../src/action-lease.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-action-binding.d.ts","sourceRoot":"","sources":["../src/canonical-action-binding.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAexE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAE/E;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBxG"}
1
+ {"version":3,"file":"canonical-action-binding.d.ts","sourceRoot":"","sources":["../src/canonical-action-binding.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAgBxE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAE/E;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CA2BxG"}
@@ -11,6 +11,7 @@ const TRANSPORT_FIELDS = new Set([
11
11
  '_devflow_worker_id',
12
12
  '_devflow_worker_context_receipt',
13
13
  ]);
14
+ const STRUCTURAL_EVIDENCE_FIELDS = new Set(['evidenceRefs']);
14
15
  export function canonicalActionInputHash(input) {
15
16
  return createHash('sha256').update(stableJson(normalizeActionInput(input))).digest('hex');
16
17
  }
@@ -21,7 +22,17 @@ export function validateCanonicalActionBinding(input) {
21
22
  const expectedHash = input.action.binding.normalizedInputHash
22
23
  ?? canonicalActionInputHash(input.action.input);
23
24
  const actualInputHash = canonicalActionInputHash(input.args);
24
- if (expectedHash !== actualInputHash) {
25
+ const safeVariations = input.action.binding.safeInputVariations ?? {};
26
+ const variedFields = Object.keys(safeVariations)
27
+ .filter(field => input.action.input[field] === undefined && input.args[field] !== undefined);
28
+ for (const field of variedFields) {
29
+ if (!matchesSafeVariation(input.args[field], safeVariations[field])) {
30
+ return { valid: false, reason: `canonical_safe_input_invalid:${field}`, actualInputHash };
31
+ }
32
+ }
33
+ const lockedActualInput = Object.fromEntries(Object.entries(input.args)
34
+ .filter(([field]) => !variedFields.includes(field) && !STRUCTURAL_EVIDENCE_FIELDS.has(field)));
35
+ if (expectedHash !== canonicalActionInputHash(lockedActualInput)) {
25
36
  return { valid: false, reason: 'canonical_input_hash_mismatch', actualInputHash };
26
37
  }
27
38
  for (const target of input.action.binding.operationTargets ?? []) {
@@ -32,6 +43,23 @@ export function validateCanonicalActionBinding(input) {
32
43
  }
33
44
  return { valid: true, actualInputHash };
34
45
  }
46
+ function matchesSafeVariation(value, policy) {
47
+ if (typeof value !== policy.type)
48
+ return false;
49
+ if (policy.enum && !policy.enum.some(candidate => candidate === value))
50
+ return false;
51
+ if (typeof value === 'number') {
52
+ if (!Number.isFinite(value))
53
+ return false;
54
+ if (policy.minimum !== undefined && value < policy.minimum)
55
+ return false;
56
+ if (policy.maximum !== undefined && value > policy.maximum)
57
+ return false;
58
+ }
59
+ if (typeof value === 'string' && policy.pattern && !new RegExp(policy.pattern, 'u').test(value))
60
+ return false;
61
+ return true;
62
+ }
35
63
  function normalizeActionInput(input) {
36
64
  return Object.fromEntries(Object.entries(input)
37
65
  .filter(([key, value]) => !TRANSPORT_FIELDS.has(key) && !key.startsWith('_devflow_') && value !== undefined)
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-action-binding.js","sourceRoot":"","sources":["../src/canonical-action-binding.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical-action-binding.js","sourceRoot":"","sources":["../src/canonical-action-binding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=canonical-action-binding.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-action-binding.test.d.ts","sourceRoot":"","sources":["../src/canonical-action-binding.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { canonicalActionInputHash, validateCanonicalActionBinding } from './canonical-action-binding.js';
3
+ function action() {
4
+ const input = { projectRoot: '/project', filePath: 'src/FlightMonitorPage.tsx', scope: 'related' };
5
+ return {
6
+ tool: 'react_audit_performance', input, status: 'recommended', required: false,
7
+ binding: {
8
+ projectRoot: '/project', sessionId: 'session', requestId: 'request',
9
+ targetAnchors: ['src/FlightMonitorPage.tsx'], requiredContextReceipt: 'context',
10
+ requiredPolicyFacets: [], normalizedInputHash: canonicalActionInputHash(input),
11
+ operationTargets: [{ path: 'src/FlightMonitorPage.tsx', expectedState: 'existing' }],
12
+ safeInputVariations: {
13
+ componentName: { type: 'string', enum: ['FlightMonitorPage'] },
14
+ maxFindings: { type: 'number', minimum: 1, maximum: 50 },
15
+ },
16
+ },
17
+ verificationPlan: [],
18
+ };
19
+ }
20
+ describe('canonical action safe input variations', () => {
21
+ it('allows declared bounded read-only refinements', () => {
22
+ expect(validateCanonicalActionBinding({
23
+ action: action(), toolName: 'react_audit_performance',
24
+ args: {
25
+ projectRoot: '/project', filePath: 'src/FlightMonitorPage.tsx', scope: 'related',
26
+ componentName: 'FlightMonitorPage', maxFindings: 8,
27
+ },
28
+ }).valid).toBe(true);
29
+ });
30
+ it('rejects unknown, out-of-range, and target-changing input', () => {
31
+ for (const args of [
32
+ { projectRoot: '/project', filePath: 'src/FlightMonitorPage.tsx', scope: 'related', maxFindings: 500 },
33
+ { projectRoot: '/project', filePath: 'src/FlightMonitorPage.tsx', scope: 'related', componentName: 'OtherPage' },
34
+ { projectRoot: '/project', filePath: 'src/Other.tsx', scope: 'related', maxFindings: 8 },
35
+ { projectRoot: '/project', filePath: 'src/FlightMonitorPage.tsx', scope: 'related', surprise: true },
36
+ ]) {
37
+ expect(validateCanonicalActionBinding({ action: action(), toolName: 'react_audit_performance', args }).valid)
38
+ .toBe(false);
39
+ }
40
+ });
41
+ });
42
+ //# sourceMappingURL=canonical-action-binding.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-action-binding.test.js","sourceRoot":"","sources":["../src/canonical-action-binding.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAEzG,SAAS,MAAM;IACb,MAAM,KAAK,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,2BAA2B,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACnG,OAAO;QACL,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK;QAC9E,OAAO,EAAE;YACP,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;YACnE,aAAa,EAAE,CAAC,2BAA2B,CAAC,EAAE,sBAAsB,EAAE,SAAS;YAC/E,oBAAoB,EAAE,EAAE,EAAE,mBAAmB,EAAE,wBAAwB,CAAC,KAAK,CAAC;YAC9E,gBAAgB,EAAE,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;YACpF,mBAAmB,EAAE;gBACnB,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,mBAAmB,CAAC,EAAE;gBAC9D,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;aACzD;SACF;QACD,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,8BAA8B,CAAC;YACpC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,yBAAyB;YACrD,IAAI,EAAE;gBACJ,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,2BAA2B,EAAE,KAAK,EAAE,SAAS;gBAChF,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAC;aACnD;SACF,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,KAAK,MAAM,IAAI,IAAI;YACjB,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,2BAA2B,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE;YACtG,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,2BAA2B,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE;YAChH,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE;YACxF,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,2BAA2B,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;SACrG,EAAE,CAAC;YACF,MAAM,CAAC,8BAA8B,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,yBAAyB,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC;iBAC1G,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -27,4 +27,60 @@ export interface CapabilityRolloutResolution {
27
27
  }
28
28
  export declare const DEFAULT_CAPABILITY_ROLLOUT: Readonly<CapabilityRolloutConfig>;
29
29
  export declare function resolveCapabilityRollout(projectRoot: string, env?: NodeJS.ProcessEnv): CapabilityRolloutResolution;
30
+ export type EvidenceRuntimeRolloutStage = 'off' | 'shadow' | 'project' | 'percentage';
31
+ export type EvidenceRuntimeRolloutSetting = {
32
+ stage: 'off' | 'shadow';
33
+ } | {
34
+ stage: 'project';
35
+ projects: string[];
36
+ } | {
37
+ stage: 'percentage';
38
+ percentage: number;
39
+ salt: string;
40
+ };
41
+ export interface EvidenceRuntimeRolloutConfig {
42
+ artifactIdentity: EvidenceRuntimeRolloutSetting;
43
+ channelOutcomes: EvidenceRuntimeRolloutSetting;
44
+ actionLease: EvidenceRuntimeRolloutSetting;
45
+ onlineTerminalProjection: EvidenceRuntimeRolloutSetting;
46
+ memoryAutoSkip: EvidenceRuntimeRolloutSetting;
47
+ knowledgePublish: EvidenceRuntimeRolloutSetting;
48
+ }
49
+ export type EvidenceRuntimeRolloutKey = keyof EvidenceRuntimeRolloutConfig;
50
+ export interface EvidenceRuntimeRolloutDiagnostic {
51
+ code: 'invalid_evidence_rollout' | 'unknown_evidence_rollout_key';
52
+ source: 'project' | 'environment';
53
+ message: string;
54
+ key?: EvidenceRuntimeRolloutKey;
55
+ value?: unknown;
56
+ environmentVariable?: string;
57
+ }
58
+ export interface EvidenceRuntimeRolloutResolution {
59
+ config: EvidenceRuntimeRolloutConfig;
60
+ projectId: string;
61
+ diagnostics: EvidenceRuntimeRolloutDiagnostic[];
62
+ }
63
+ export interface EvidenceRuntimeRolloutDecision {
64
+ stage: EvidenceRuntimeRolloutStage;
65
+ writeEvents: boolean;
66
+ shadowCompare: boolean;
67
+ readCandidate: boolean;
68
+ projectTerminalOutcome: boolean;
69
+ preserveEvents: true;
70
+ rewriteOutcomes: false;
71
+ }
72
+ export declare const DEFAULT_EVIDENCE_RUNTIME_ROLLOUT: Readonly<EvidenceRuntimeRolloutConfig>;
73
+ /** Resolve the independently reversible evidence-runtime rollout controls. */
74
+ export declare function resolveEvidenceRuntimeRollout(projectRoot: string, env?: NodeJS.ProcessEnv): EvidenceRuntimeRolloutResolution;
75
+ export declare function decideEvidenceRuntimeRollout(input: {
76
+ setting: EvidenceRuntimeRolloutSetting;
77
+ projectId: string;
78
+ bucketKey: string;
79
+ }): EvidenceRuntimeRolloutDecision;
80
+ /**
81
+ * Rollback retains append-only evidence by returning every active capability to
82
+ * shadow, while disabling all candidate reads and terminal projections.
83
+ */
84
+ export declare function rollbackEvidenceRuntimeRollout(config: EvidenceRuntimeRolloutConfig): EvidenceRuntimeRolloutConfig;
85
+ export declare function evidenceRuntimeProjectId(projectRoot: string): string;
30
86
  //# sourceMappingURL=capability-rollout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capability-rollout.d.ts","sourceRoot":"","sources":["../src/capability-rollout.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC;AAElD,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,EAAE,WAAW,CAAC;IAC9B,cAAc,EAAE,WAAW,CAAC;IAC5B,iBAAiB,EAAE,WAAW,CAAC;IAC/B,kBAAkB,EAAE,WAAW,CAAC;IAChC,kBAAkB,EAAE,WAAW,CAAC;IAChC,mBAAmB,EAAE,WAAW,CAAC;IACjC,gBAAgB,EAAE,WAAW,CAAC;IAC9B,kBAAkB,EAAE,WAAW,CAAC;IAChC,eAAe,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,uBAAuB,CAAC;AAEjE,MAAM,MAAM,+BAA+B,GACvC,mBAAmB,GACnB,kBAAkB,GAClB,wBAAwB,GACxB,uBAAuB,GACvB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,+BAA+B,CAAC;IACtC,MAAM,EAAE,SAAS,GAAG,aAAa,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,oBAAoB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,uBAAuB,CAAC;IAChC,WAAW,EAAE,2BAA2B,EAAE,CAAC;CAC5C;AAED,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,uBAAuB,CAUvE,CAAC;AAwBH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,2BAA2B,CAwD7B"}
1
+ {"version":3,"file":"capability-rollout.d.ts","sourceRoot":"","sources":["../src/capability-rollout.ts"],"names":[],"mappings":"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"}