@entrorove/skill 0.1.32 → 0.1.34
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/CAPABILITY-MAP.md +20 -0
- package/CHANGELOG.md +10 -0
- package/SKILL.md +31 -5
- package/automatic-feedback-client.mjs +43 -0
- package/cli.mjs +20 -1
- package/cloud-event-stream.mjs +27 -0
- package/cloud-task-client.mjs +34 -15
- package/cloud-watch-client.mjs +58 -0
- package/ide-presentation.mjs +58 -0
- package/local-cli.mjs +12 -1
- package/local-contract-types.mjs +9 -3
- package/local-contracts.mjs +31 -2
- package/local-error.mjs +19 -1
- package/local-execution.mjs +23 -1
- package/local-scope-config-imports.mjs +192 -0
- package/local-scope-repository.mjs +45 -9
- package/manifest.json +1 -1
- package/package.json +7 -1
- package/release-state.json +21 -15
- package/release.mjs +16 -6
- package/releases.json +12 -0
- package/remote-client.mjs +37 -9
- package/scope-runner-client.mjs +125 -0
package/local-contracts.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import { array, binding, change, confirmation, enumeration, evidence, evidenceAr
|
|
|
14
14
|
const schemas = {};
|
|
15
15
|
const base = { repositoryRoot: text, home: text };
|
|
16
16
|
const flow = { ...base, flowId: identifier };
|
|
17
|
+
const fixedRoundingPolicy = object({ decimalPlaces: { const: 2 }, mode: { const: 'half-away-from-zero' } }, ['decimalPlaces', 'mode']);
|
|
17
18
|
const step = { ...flow, stepId: identifier };
|
|
18
19
|
function add(names, properties, required = [], alternatives) {
|
|
19
20
|
const schema = object(properties, required);
|
|
@@ -54,8 +55,8 @@ add('rollback', { ...step, snapshotId: identifier }, ['repositoryRoot', 'flowId'
|
|
|
54
55
|
const check = { anyOf: [{ type: 'boolean' }, { type: 'object', properties: { status: text }, required: ['status'] }] };
|
|
55
56
|
add('final-gate', { ...base, ...binding, audit: check, test: check, operations: check, evidence: array(evidence), preflight: record }, ['audit', 'test', 'operations', 'evidence']);
|
|
56
57
|
schemas['final-gate'] = { oneOf: [schemas['final-gate'], FINAL_GATE16_INPUT_SCHEMA, FINAL_GATE16_READ_INPUT_SCHEMA] };
|
|
57
|
-
add('formula-evaluate', { formula, values: decimalValues }, ['formula']);
|
|
58
|
-
add('formula-graph', { formulas: array(formulaEntry), inputs: decimalValues }, ['formulas']);
|
|
58
|
+
add('formula-evaluate', { formula, values: decimalValues, roundingPolicy: fixedRoundingPolicy }, ['formula']);
|
|
59
|
+
add('formula-graph', { formulas: array(formulaEntry), inputs: decimalValues, roundingPolicy: fixedRoundingPolicy }, ['formulas']);
|
|
59
60
|
add('formula-final-gate', { engine: record, flowId: identifier, stepId: identifier }, ['engine']);
|
|
60
61
|
add('calculation-final-gate', { ...step, enginePath: relativePath }, ['repositoryRoot', 'enginePath']);
|
|
61
62
|
add('run-approved-plan', { repositoryRoot: text, planPath: relativePath, approvalPath: text, signerConfigPath: nullable(text) }, ['repositoryRoot', 'planPath', 'approvalPath', 'signerConfigPath']);
|
|
@@ -114,9 +115,37 @@ Object.assign(schemas, ARCHGUARD_LOCAL_OPERATION_SCHEMAS, CALCTOOL_LOCAL_OPERATI
|
|
|
114
115
|
export const LOCAL_OPERATION_SCHEMAS = Object.freeze(schemas);
|
|
115
116
|
const ajv = new Ajv({ strict: true, strictRequired: false, allErrors: true });
|
|
116
117
|
const validators = new Map(Object.entries(schemas).map(([operation, schema]) => [operation, ajv.compile(schema)]));
|
|
118
|
+
const FORMULA_ARITY = { add: [1, Infinity], mul: [1, Infinity], sub: [2, 2], div: [2, 2], safeDivide: [2, 2], percentOf: [2, 2], round: [1, 1], if: [3, 3] };
|
|
119
|
+
function formulaArityError(node, path) {
|
|
120
|
+
if (!node || typeof node !== 'object' || Array.isArray(node) || typeof node.op !== 'string') return undefined;
|
|
121
|
+
const bounds = FORMULA_ARITY[node.op];
|
|
122
|
+
if (!bounds) return undefined;
|
|
123
|
+
const count = Array.isArray(node.args) ? node.args.length : -1;
|
|
124
|
+
if (count < bounds[0] || count > bounds[1]) {
|
|
125
|
+
const expected = bounds[0] === bounds[1] ? `exactly ${bounds[0]}` : `at least ${bounds[0]}`;
|
|
126
|
+
return `${path}.args: operator "${node.op}" requires ${expected} arguments; received ${count < 0 ? 'non-array args' : count}`;
|
|
127
|
+
}
|
|
128
|
+
for (const [index, child] of node.args.entries()) {
|
|
129
|
+
const failure = formulaArityError(child, `${path}.args[${index}]`);
|
|
130
|
+
if (failure) return failure;
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
function formulaInputHint(operation, input) {
|
|
135
|
+
if (operation === 'formula-evaluate') return formulaArityError(input?.formula, 'formula');
|
|
136
|
+
if (operation === 'formula-graph' && Array.isArray(input?.formulas)) {
|
|
137
|
+
for (const [index, entry] of input.formulas.entries()) {
|
|
138
|
+
const failure = formulaArityError(entry?.expression, `formulas[${index}].expression`);
|
|
139
|
+
if (failure) return failure;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
117
144
|
export function validateLocalInput(operation, input) {
|
|
118
145
|
const validate = validators.get(operation);
|
|
119
146
|
if (!validate) throw Object.assign(new Error(`Unsupported local operation: ${operation}`), { code: 'ENTROROVE_OPERATION_UNKNOWN' });
|
|
147
|
+
const hint = formulaInputHint(operation, input);
|
|
148
|
+
if (hint) throw Object.assign(new Error(`Invalid ${operation} input: ${hint}`), { code: 'ENTROROVE_INPUT_INVALID' });
|
|
120
149
|
if (!validate(input)) {
|
|
121
150
|
const details = validate.errors.map(error => `${error.instancePath || '/'} ${error.message}`).join('; ');
|
|
122
151
|
throw Object.assign(new Error(`Invalid ${operation} input: ${details}`), { code: 'ENTROROVE_INPUT_INVALID' });
|
package/local-error.mjs
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
export const LOCAL_ERROR_SCHEMA = 'entrorove.local-error/1.0';
|
|
2
|
+
export const LOCAL_ERROR_CODE_CATALOG = Object.freeze({
|
|
3
|
+
ENTROROVE_INPUT_INVALID: Object.freeze({ disposition: 'terminal', stability: 'stable' }),
|
|
4
|
+
ENTROROVE_OPERATION_UNKNOWN: Object.freeze({ disposition: 'terminal', stability: 'stable' }),
|
|
5
|
+
ENTROROVE_LOCAL_FAILURE: Object.freeze({ disposition: 'terminal', stability: 'stable' }),
|
|
6
|
+
DIV_ZERO: Object.freeze({ disposition: 'terminal', stability: 'stable' }),
|
|
7
|
+
ENTROROVE_MUTATE_NOT_ACCEPTED: Object.freeze({ disposition: 'needs-human', stability: 'stable' }),
|
|
8
|
+
ENTROROVE_MUTATION_AUTHORITY_REQUIRED: Object.freeze({ disposition: 'needs-human', stability: 'stable' }),
|
|
9
|
+
ENTROROVE_BUDGET_LEASE_EXPIRED: Object.freeze({ disposition: 'retriable', stability: 'stable' }),
|
|
10
|
+
ENTROROVE_GIT_READER_UNSUPPORTED: Object.freeze({ disposition: 'terminal', stability: 'stable' }),
|
|
11
|
+
});
|
|
2
12
|
|
|
3
13
|
const BLOCKED_CODES = new Set([
|
|
4
14
|
'ENTROROVE_MUTATE_NOT_ACCEPTED', 'ENTROROVE_MUTATION_AUTHORITY_REQUIRED',
|
|
@@ -16,8 +26,16 @@ export function localErrorStatus(error) {
|
|
|
16
26
|
? 'blocked' : 'failed';
|
|
17
27
|
}
|
|
18
28
|
|
|
29
|
+
export function localErrorDisposition(code) {
|
|
30
|
+
const catalogued = LOCAL_ERROR_CODE_CATALOG[code];
|
|
31
|
+
if (catalogued) return catalogued.disposition;
|
|
32
|
+
if (/_LEASE_EXPIRED$|_BUSY$|_RECONNECT/.test(code)) return 'retriable';
|
|
33
|
+
if (BLOCKED_CODES.has(code) || /(?:AUTHORITY_REQUIRED|NOT_ACCEPTED|REVOKED)$/.test(code)) return 'needs-human';
|
|
34
|
+
return 'terminal';
|
|
35
|
+
}
|
|
36
|
+
|
|
19
37
|
export function localErrorEnvelope(error, fallbackCode = 'ENTROROVE_LOCAL_FAILURE') {
|
|
20
38
|
const code = typeof error?.code === 'string' && error.code ? error.code : fallbackCode;
|
|
21
39
|
const message = typeof error?.message === 'string' && error.message ? error.message : 'Local operation failed';
|
|
22
|
-
return { schemaVersion: LOCAL_ERROR_SCHEMA, status: localErrorStatus({ ...error, code }), code, message };
|
|
40
|
+
return { schemaVersion: LOCAL_ERROR_SCHEMA, status: localErrorStatus({ ...error, code }), code, disposition: localErrorDisposition(code), message };
|
|
23
41
|
}
|
package/local-execution.mjs
CHANGED
|
@@ -275,7 +275,29 @@ export async function finalGate(input) {
|
|
|
275
275
|
guarantee: 'Original engine, frozen role plans and actual three-party checks are required' };
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
const LOCAL_OPERATION_GROUPS = Object.freeze(['core', 'budget', 'scope', 'merge', 'chain', 'handoff', 'archguard', 'calctool', 'swarm', 'validator', 'formula', 'evidence']);
|
|
279
|
+
const PASS_REQUIRED_OPERATIONS = new Set(['mutation-snapshot-attest', 'mutate-gate', 'gate-issue', 'gate-verify', 'guarded-write',
|
|
280
|
+
'merge-verified', 'rollback', 'archguard-contract-create', 'archguard-contract-update', 'archguard-checkpoint', 'archguard-scope-request',
|
|
281
|
+
'budget-handoff', 'budget-transition', 'spawn-bind', 'peer-complete', 'complete']);
|
|
282
|
+
function operationGroup(operation) {
|
|
283
|
+
if (operation.startsWith('archguard-')) return 'archguard';
|
|
284
|
+
if (operation.startsWith('calctool-')) return 'calctool';
|
|
285
|
+
if (operation.includes('handoff')) return 'handoff';
|
|
286
|
+
if (operation.startsWith('budget-')) return 'budget';
|
|
287
|
+
if (operation.startsWith('chain-')) return 'chain';
|
|
288
|
+
if (operation.startsWith('formula-')) return 'formula';
|
|
289
|
+
if (operation.startsWith('merge-') || ['branch-create', 'branch-create-virtual', 'branch-list', 'branch-switch', 'diff-report', 'preflight', 'ledger-query'].includes(operation)) return 'merge';
|
|
290
|
+
if (operation.startsWith('peer-') || ['coordinate', 'spawn-bind', 'complete', 'lease-verify'].includes(operation)) return 'swarm';
|
|
291
|
+
if (operation.startsWith('evidence-')) return 'evidence';
|
|
292
|
+
if (operation.startsWith('probe') || operation === 'reassess' || operation.startsWith('snapshot') || operation.includes('scope')) return 'scope';
|
|
293
|
+
if (operation === 'final-gate' || operation.includes('verify') || operation.includes('validate')) return 'validator';
|
|
294
|
+
return 'core';
|
|
295
|
+
}
|
|
296
|
+
const LOCAL_OPERATION_METADATA = Object.freeze(Object.fromEntries(Object.keys(LOCAL_OPERATION_SCHEMAS).map(operation => [operation, Object.freeze({
|
|
297
|
+
group: operationGroup(operation), requiresPass: PASS_REQUIRED_OPERATIONS.has(operation),
|
|
298
|
+
})])));
|
|
299
|
+
export const LOCAL_CAPABILITIES = Object.freeze({ schemaVersion: LOCAL_SCHEMA, operations: Object.freeze(Object.keys(LOCAL_OPERATION_SCHEMAS)), operationSchemas: LOCAL_OPERATION_SCHEMAS,
|
|
300
|
+
operationMetadata: LOCAL_OPERATION_METADATA, groups: LOCAL_OPERATION_GROUPS, stateDirectory: '~/.entrorove', forbidGitBranch: true, forbidWorktree: true, evidenceSchema: EVIDENCE_SCHEMA, budgets: READ_BUDGETS, validatorRunner: RUNNER_CAPABILITIES, workflowRunner: WORKFLOW_LOCAL_CAPABILITIES });
|
|
279
301
|
export function capabilities() { return LOCAL_CAPABILITIES; }
|
|
280
302
|
export const guardedWriteFile = guardedWrite;
|
|
281
303
|
export const verifyMutationPassFile = verifyMutationPass;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
const missing = (error) => ['ENOENT', 'ENOTDIR'].includes(error?.code ?? '');
|
|
5
|
+
function literal(value, field) {
|
|
6
|
+
if (typeof value !== 'string' || !value || value !== value.trim() || value !== value.normalize('NFC')
|
|
7
|
+
|| /[\\:\u0000-\u001f\u007f]/.test(value) || value.startsWith('/') || value.startsWith('~')) {
|
|
8
|
+
throw new Error(`Scope tsconfig ${field} requires a supported repository-relative literal path`);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
function within(directory, value, allowRoot = false) {
|
|
13
|
+
const resolved = path.posix.normalize(path.posix.join(directory, literal(value, 'path'))).replace(/\/+$/, '');
|
|
14
|
+
if (resolved === '..' || resolved.startsWith('../') || resolved.startsWith('/')
|
|
15
|
+
|| resolved.split('/').some(part => ['node_modules', '.git', '.entrorove', '.aimlock', '.archguard'].includes(part))) {
|
|
16
|
+
throw new Error('Scope tsconfig path escapes the authorized repository');
|
|
17
|
+
}
|
|
18
|
+
if (resolved === '.') {
|
|
19
|
+
if (!allowRoot)
|
|
20
|
+
throw new Error('Scope tsconfig mapping requires a literal candidate within the repository');
|
|
21
|
+
return '';
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
function pathsOption(value) {
|
|
26
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
27
|
+
throw new Error('Scope tsconfig paths requires an object of literal mappings');
|
|
28
|
+
const result = Object.create(null);
|
|
29
|
+
const entries = Object.entries(value);
|
|
30
|
+
if (entries.length > 512)
|
|
31
|
+
throw new Error('Scope tsconfig paths exceeds 512 mappings');
|
|
32
|
+
for (const [key, targets] of entries) {
|
|
33
|
+
if (!key || key !== key.trim() || key !== key.normalize('NFC') || /[\\:\u0000-\u001f\u007f]/.test(key)
|
|
34
|
+
|| key.startsWith('/') || key.split('/').some(part => part === '.' || part === '..') || key.split('*').length > 2) {
|
|
35
|
+
throw new Error('Scope tsconfig paths supports only exact or single-wildcard mappings');
|
|
36
|
+
}
|
|
37
|
+
if (!Array.isArray(targets) || !targets.length || targets.length > 128 || targets.some(target => typeof target !== 'string')) {
|
|
38
|
+
throw new Error('Scope tsconfig paths targets must be a nonempty bounded string array');
|
|
39
|
+
}
|
|
40
|
+
result[key] = targets.map(target => {
|
|
41
|
+
literal(target, 'mapping');
|
|
42
|
+
if (target.split('*').length > 2 || (target.includes('*') && !key.includes('*'))) {
|
|
43
|
+
throw new Error('Scope tsconfig paths target has an unsupported wildcard mapping');
|
|
44
|
+
}
|
|
45
|
+
return target;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
function parsedConfig(relative, source) {
|
|
51
|
+
const parsed = ts.parseConfigFileTextToJson(relative, source);
|
|
52
|
+
if (parsed.error)
|
|
53
|
+
throw new Error(`Scope tsconfig JSONC syntax is invalid (diagnostic ${parsed.error.code})`);
|
|
54
|
+
if (!parsed.config || typeof parsed.config !== 'object' || Array.isArray(parsed.config))
|
|
55
|
+
throw new Error('Scope tsconfig must contain a configuration object');
|
|
56
|
+
return parsed.config;
|
|
57
|
+
}
|
|
58
|
+
function pathMatch(paths, specifier) {
|
|
59
|
+
if (!paths)
|
|
60
|
+
return null;
|
|
61
|
+
if (Object.hasOwn(paths, specifier))
|
|
62
|
+
return { targets: paths[specifier], wildcard: '' };
|
|
63
|
+
let selected = null;
|
|
64
|
+
let prefixLength = -1;
|
|
65
|
+
for (const [key, targets] of Object.entries(paths)) {
|
|
66
|
+
const star = key.indexOf('*');
|
|
67
|
+
if (star < 0)
|
|
68
|
+
continue;
|
|
69
|
+
const prefix = key.slice(0, star);
|
|
70
|
+
const suffix = key.slice(star + 1);
|
|
71
|
+
if (prefix.length > prefixLength && specifier.startsWith(prefix) && specifier.endsWith(suffix)
|
|
72
|
+
&& specifier.length >= prefix.length + suffix.length) {
|
|
73
|
+
selected = { targets, wildcard: specifier.slice(prefix.length, specifier.length - suffix.length) };
|
|
74
|
+
prefixLength = prefix.length;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return selected;
|
|
78
|
+
}
|
|
79
|
+
function importCandidates(resolution, specifier) {
|
|
80
|
+
if (typeof specifier !== 'string' || !specifier)
|
|
81
|
+
throw new Error('Scope tsconfig import specifier must be nonempty');
|
|
82
|
+
if (specifier.startsWith('node:') || specifier.startsWith('./') || specifier.startsWith('../'))
|
|
83
|
+
return [];
|
|
84
|
+
if (specifier !== specifier.trim() || /[\\:\u0000-\u001f\u007f*]/.test(specifier)
|
|
85
|
+
|| specifier.startsWith('/') || specifier.split('/').some(part => part === '.' || part === '..')) {
|
|
86
|
+
throw new Error('Scope tsconfig import alias or candidate uses an unsupported path');
|
|
87
|
+
}
|
|
88
|
+
const match = pathMatch(resolution?.paths, specifier);
|
|
89
|
+
if (match) {
|
|
90
|
+
const base = resolution.baseUrl ?? resolution.pathsOrigin;
|
|
91
|
+
return [...new Set(match.targets.map(target => within(base, target.replace('*', match.wildcard))))];
|
|
92
|
+
}
|
|
93
|
+
if (specifier.startsWith('@/') || specifier.startsWith('#') || specifier.startsWith('~/')) {
|
|
94
|
+
throw new Error('Scope local import alias requires an actual tsconfig or package-import mapping');
|
|
95
|
+
}
|
|
96
|
+
return resolution?.baseUrl !== undefined ? [within(resolution.baseUrl, specifier)] : [];
|
|
97
|
+
}
|
|
98
|
+
export async function scopeTsconfigImports(read, fromFile, configPath) {
|
|
99
|
+
const canonical = within('', fromFile);
|
|
100
|
+
if (canonical !== fromFile)
|
|
101
|
+
throw new Error('Scope tsconfig source path must be canonical within the repository');
|
|
102
|
+
const observed = new Map();
|
|
103
|
+
const absent = new Set();
|
|
104
|
+
let bytes = 0;
|
|
105
|
+
const metadata = async (relative) => {
|
|
106
|
+
if (absent.has(relative))
|
|
107
|
+
return null;
|
|
108
|
+
if (observed.has(relative))
|
|
109
|
+
return Buffer.from(observed.get(relative).contentBase64, 'base64').toString('utf8');
|
|
110
|
+
let item;
|
|
111
|
+
try {
|
|
112
|
+
item = await read(relative);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (missing(error)) {
|
|
116
|
+
absent.add(relative);
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
;
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
const data = Buffer.from(item.contentBase64, 'base64');
|
|
123
|
+
if (item.path !== relative || data.toString('base64') !== item.contentBase64
|
|
124
|
+
|| createHash('sha256').update(data).digest('hex') !== item.sha256 || !Buffer.from(data.toString('utf8')).equals(data)) {
|
|
125
|
+
throw new Error('Scope tsconfig metadata lost its actual path, UTF-8 content or hash');
|
|
126
|
+
}
|
|
127
|
+
bytes += data.length;
|
|
128
|
+
if (data.length > 1024 * 1024 || bytes > 16 * 1024 * 1024)
|
|
129
|
+
throw new Error('Scope tsconfig metadata exceeds its bounded read size');
|
|
130
|
+
observed.set(relative, item);
|
|
131
|
+
return data.toString('utf8');
|
|
132
|
+
};
|
|
133
|
+
const load = async (relative, ancestors, depth = 0) => {
|
|
134
|
+
if (depth >= 10)
|
|
135
|
+
throw new Error('Scope tsconfig extends exceeds the 10-configuration depth bound');
|
|
136
|
+
let source = await metadata(relative);
|
|
137
|
+
if (source === null && !relative.endsWith('.json')) {
|
|
138
|
+
relative += '.json';
|
|
139
|
+
source = await metadata(relative);
|
|
140
|
+
}
|
|
141
|
+
if (source === null)
|
|
142
|
+
throw new Error('Scope tsconfig extends references a missing actual configuration');
|
|
143
|
+
if (ancestors.has(relative))
|
|
144
|
+
throw new Error('Scope tsconfig extends contains a configuration cycle');
|
|
145
|
+
const config = parsedConfig(relative, source);
|
|
146
|
+
const directory = path.posix.dirname(relative) === '.' ? '' : path.posix.dirname(relative);
|
|
147
|
+
let inherited = { pathsOrigin: directory };
|
|
148
|
+
if (config.extends !== undefined) {
|
|
149
|
+
const extended = literal(config.extends, 'extends');
|
|
150
|
+
if (!extended.startsWith('./') && !extended.startsWith('../'))
|
|
151
|
+
throw new Error('Scope tsconfig npm extends is unsupported; use an actual repository-relative extends');
|
|
152
|
+
inherited = await load(within(directory, extended), new Set([...ancestors, relative]), depth + 1);
|
|
153
|
+
}
|
|
154
|
+
const options = config.compilerOptions === undefined ? {} : config.compilerOptions;
|
|
155
|
+
if (!options || typeof options !== 'object' || Array.isArray(options))
|
|
156
|
+
throw new Error('Scope tsconfig compilerOptions must be an object');
|
|
157
|
+
const own = options;
|
|
158
|
+
return { ...inherited,
|
|
159
|
+
...(own.baseUrl === undefined ? {} : { baseUrl: within(directory, literal(own.baseUrl, 'baseUrl'), true) }),
|
|
160
|
+
...(own.paths === undefined ? {} : { paths: pathsOption(own.paths), pathsOrigin: directory }) };
|
|
161
|
+
};
|
|
162
|
+
let directory = path.posix.dirname(canonical);
|
|
163
|
+
let resolution = null;
|
|
164
|
+
if (configPath !== undefined) {
|
|
165
|
+
if (within('', configPath) !== configPath || !/(?:^|\/)(?:ts|js)config(?:\.[^/]+)?\.json$/.test(configPath))
|
|
166
|
+
throw new Error('Scope import context requires an actual repository-relative tsconfig or jsconfig');
|
|
167
|
+
resolution = await load(configPath, new Set());
|
|
168
|
+
}
|
|
169
|
+
while (configPath === undefined) {
|
|
170
|
+
const prefix = directory === '.' ? '' : `${directory}/`;
|
|
171
|
+
const relative = await metadata(`${prefix}tsconfig.json`) !== null ? `${prefix}tsconfig.json`
|
|
172
|
+
: await metadata(`${prefix}jsconfig.json`) !== null ? `${prefix}jsconfig.json` : null;
|
|
173
|
+
if (relative !== null) {
|
|
174
|
+
resolution = await load(relative, new Set());
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
if (directory === '.')
|
|
178
|
+
break;
|
|
179
|
+
directory = path.posix.dirname(directory);
|
|
180
|
+
}
|
|
181
|
+
if (resolution?.paths)
|
|
182
|
+
for (const targets of Object.values(resolution.paths))
|
|
183
|
+
for (const target of targets) {
|
|
184
|
+
within(resolution.baseUrl ?? resolution.pathsOrigin, target.replace('*', '__scope_wildcard__'));
|
|
185
|
+
}
|
|
186
|
+
return { candidates: specifier => importCandidates(resolution, specifier), mapped: specifier => {
|
|
187
|
+
if (typeof specifier !== 'string' || !specifier)
|
|
188
|
+
throw new Error('Scope tsconfig mapping lookup requires a nonempty specifier');
|
|
189
|
+
return pathMatch(resolution?.paths, specifier) !== null;
|
|
190
|
+
}, observations: [...observed.keys()].sort()
|
|
191
|
+
.map(relative => ({ path: relative, sha256: observed.get(relative).sha256 })) };
|
|
192
|
+
}
|
|
@@ -11,6 +11,7 @@ import { workspaceImport, workspaceIndex } from './local-scope-workspaces.mjs';
|
|
|
11
11
|
import { assertBudgetRunnerAllowed } from './local-budget-reads.mjs';
|
|
12
12
|
import { observeBudgetScopeGit, scopeGitBudgetEnforced } from './local-scope-git.mjs';
|
|
13
13
|
import { scopeGitMetadata } from './local-scope-git-reads.mjs';
|
|
14
|
+
import { scopeTsconfigImports } from './local-scope-config-imports.mjs';
|
|
14
15
|
|
|
15
16
|
const execute = promisify(execFile);
|
|
16
17
|
async function git(root, args, allowed = [], input = { repositoryRoot: root }) {
|
|
@@ -179,48 +180,83 @@ function importSpecifiers(content, filename) {
|
|
|
179
180
|
}
|
|
180
181
|
}
|
|
181
182
|
const sourceExtension = /\.(?:[cm]?[jt]sx?|vue)$/i;
|
|
182
|
-
|
|
183
|
+
function declarationModules(content, from) {
|
|
184
|
+
if (!/\.d\.[cm]?ts$/i.test(from)) return new Set();
|
|
185
|
+
const parsed = ts.createSourceFile(from, content.toString('utf8'), ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
186
|
+
return new Set(parsed.statements.filter(node => ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name)
|
|
187
|
+
&& node.modifiers?.some(modifier => modifier.kind === ts.SyntaxKind.DeclareKeyword)).map(node => node.name.text));
|
|
188
|
+
}
|
|
189
|
+
async function resolveImport(root, from, specifier, workspace, input, aliases, configPath, declarations) {
|
|
183
190
|
if (/^(?:https?:|file:|data:)/i.test(specifier)) scopeFail('ENTROROVE_IMPORT_UNSUPPORTED', 'remote source imports cannot be inspected as local facts');
|
|
191
|
+
if (declarations.has(specifier)) return null;
|
|
192
|
+
const label = /^[A-Za-z0-9@._/~+-]{1,256}$/.test(specifier) ? specifier : '[unsupported specifier]';
|
|
193
|
+
let candidates;
|
|
194
|
+
try { candidates = aliases.candidates(specifier); }
|
|
195
|
+
catch (error) { scopeFail('ENTROROVE_IMPORT_UNRESOLVED', `${from}: ${error.message}; specify its actual build config with importContexts`); }
|
|
196
|
+
for (const candidate of candidates) {
|
|
197
|
+
const resolved = await resolveLocalImport(root, candidate, false);
|
|
198
|
+
if (resolved) return resolved;
|
|
199
|
+
}
|
|
200
|
+
if (aliases.mapped(specifier)) scopeFail('ENTROROVE_IMPORT_UNRESOLVED', `${from}: ${label} has no actual resolvable source file in its build config`);
|
|
184
201
|
const localPackage = !specifier.startsWith('.') ? workspaceImport(workspace, specifier) : null;
|
|
185
202
|
if (!specifier.startsWith('.') && !localPackage) {
|
|
186
203
|
if (builtinModules.includes(specifier) || (specifier.startsWith('node:') && builtinModules.includes(specifier.slice(5)))) return null;
|
|
187
|
-
const boundary = await packageBoundary(root, from, input);
|
|
204
|
+
const boundary = await packageBoundary(root, configPath ?? from, input);
|
|
188
205
|
if (boundary.manifestPath) {
|
|
189
206
|
const manifest = JSON.parse((await scopeRead(root, boundary.manifestPath, input)).content.toString('utf8'));
|
|
190
207
|
const name = specifier.startsWith('@') ? specifier.split('/').slice(0, 2).join('/') : specifier.split('/')[0];
|
|
191
208
|
if (['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'].some(field => Object.hasOwn(manifest[field] ?? {}, name))) return null;
|
|
192
209
|
}
|
|
193
|
-
scopeFail('ENTROROVE_IMPORT_UNRESOLVED',
|
|
210
|
+
scopeFail('ENTROROVE_IMPORT_UNRESOLVED', `${from}: ${label} requires a builtin, declared dependency, or actual workspace export`);
|
|
194
211
|
}
|
|
195
212
|
const relative = localPackage ?? path.posix.normalize(path.posix.join(path.posix.dirname(from), specifier));
|
|
213
|
+
return resolveLocalImport(root, relative);
|
|
214
|
+
}
|
|
215
|
+
async function resolveLocalImport(root, relative, required = true) {
|
|
196
216
|
if (relative.startsWith('../') || relative === '..') scopeFail('ENTROROVE_PATH_UNSAFE', 'local import escapes the repository');
|
|
197
217
|
const replacements = /\.js$/.test(relative) ? [relative.replace(/\.js$/, '.ts'), relative.replace(/\.js$/, '.tsx')] : [];
|
|
198
|
-
for (const candidate of [relative, ...replacements, ...['.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx', '/index.js', '/index.ts'].map(ext => relative + ext)]) {
|
|
218
|
+
for (const candidate of [relative, ...replacements, ...['.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx', '.vue', '.json', '.d.ts', '.d.mts', '.d.cts', '/index.js', '/index.ts', '/index.d.ts'].map(ext => relative + ext)]) {
|
|
199
219
|
const item = await scopeTarget(root, candidate, true);
|
|
200
220
|
if (item.exists && item.stat.isFile()) return candidate;
|
|
201
221
|
}
|
|
202
|
-
scopeFail('ENTROROVE_IMPORT_UNRESOLVED', 'a local import has no resolvable source file');
|
|
222
|
+
if (required) scopeFail('ENTROROVE_IMPORT_UNRESOLVED', 'a local import has no resolvable source file');
|
|
223
|
+
return null;
|
|
203
224
|
}
|
|
204
225
|
export async function importGraph(root, originals, input = { repositoryRoot: root }) {
|
|
205
226
|
const pending = originals.filter(file => file.exists !== false).map(file => file.path); const visited = new Map(); const edges = []; let dynamic = false;
|
|
227
|
+
const dynamicSources = [];
|
|
206
228
|
const workspace = await workspaceIndex(root, input);
|
|
229
|
+
const metadata = new Map(workspace.metadata.map(item => [item.path, item]));
|
|
207
230
|
while (pending.length) {
|
|
208
231
|
const relative = pending.shift(); if (visited.has(relative)) continue;
|
|
209
232
|
if (visited.size >= 1000) scopeFail('ENTROROVE_SCOPE_LIMIT', 'import graph exceeds the 1000-file inspection bound');
|
|
210
233
|
const read = await scopeRead(root, relative, input); const boundary = await packageBoundary(root, relative, input);
|
|
211
234
|
visited.set(relative, { path: relative, sha256: read.sha256, module: boundary.path, boundary });
|
|
212
235
|
if (!sourceExtension.test(relative)) continue;
|
|
236
|
+
const contexts = (input.importContexts ?? []).filter(context => relative === context.sourcePrefix || relative.startsWith(`${context.sourcePrefix}/`))
|
|
237
|
+
.sort((a, b) => b.sourcePrefix.length - a.sourcePrefix.length);
|
|
238
|
+
const configPath = contexts[0]?.configPath;
|
|
239
|
+
const aliases = await scopeTsconfigImports(async target => {
|
|
240
|
+
const item = await scopeRead(root, target, input);
|
|
241
|
+
return { path: target, sha256: item.sha256, contentBase64: item.content.toString('base64') };
|
|
242
|
+
}, relative, configPath);
|
|
243
|
+
for (const observed of aliases.observations) metadata.set(observed.path, observed);
|
|
244
|
+
const declarations = declarationModules(read.content, relative);
|
|
213
245
|
const imports = importSpecifiers(read.content, relative); dynamic ||= imports.dynamic;
|
|
246
|
+
if (imports.dynamic) dynamicSources.push({ path: relative, sha256: read.sha256 });
|
|
214
247
|
for (const specifier of imports.specifiers.sort()) {
|
|
215
|
-
const target = await resolveImport(root, relative, specifier, workspace, input);
|
|
216
|
-
edges.push({ from: relative, to: target, external: target === null, specifier
|
|
248
|
+
const target = await resolveImport(root, relative, specifier, workspace, input, aliases, configPath, declarations);
|
|
249
|
+
edges.push({ from: relative, to: target, external: target === null, specifier,
|
|
250
|
+
...(declarations.has(specifier) ? { declarationOnly: true, declarationPath: relative } : {}) });
|
|
217
251
|
if (target !== null && !visited.has(target)) pending.push(target);
|
|
218
252
|
}
|
|
219
253
|
}
|
|
220
254
|
const nodes = [...visited.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
221
255
|
await stableScope(root, nodes, input);
|
|
222
|
-
|
|
223
|
-
|
|
256
|
+
const workspaceMetadata = [...metadata.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
257
|
+
await stableScope(root, workspaceMetadata, input);
|
|
258
|
+
return { nodes, edges: edges.sort((a, b) => `${a.from}:${a.specifier}`.localeCompare(`${b.from}:${b.specifier}`)),
|
|
259
|
+
dynamic, complete: !dynamic, dynamicSources: dynamicSources.sort((a, b) => a.path.localeCompare(b.path)), workspaceMetadata };
|
|
224
260
|
}
|
|
225
261
|
export async function collectScopeFacts(root, requested, baselineRef, knownFiles = [], input = { repositoryRoot: root }) {
|
|
226
262
|
const selected = await scopeFiles(root, requested, knownFiles); const files = [];
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@entrorove/skill",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"entrorove": "cli.mjs"
|
|
@@ -76,7 +76,12 @@
|
|
|
76
76
|
"local-task-handoff-write-archive.mjs",
|
|
77
77
|
"local-task-handoff-write-receipts.mjs",
|
|
78
78
|
"remote-client.mjs",
|
|
79
|
+
"scope-runner-client.mjs",
|
|
79
80
|
"cloud-task-client.mjs",
|
|
81
|
+
"cloud-watch-client.mjs",
|
|
82
|
+
"cloud-event-stream.mjs",
|
|
83
|
+
"ide-presentation.mjs",
|
|
84
|
+
"automatic-feedback-client.mjs",
|
|
80
85
|
"remote-transport.mjs",
|
|
81
86
|
"local-credential.mjs",
|
|
82
87
|
"local-invocations.mjs",
|
|
@@ -122,6 +127,7 @@
|
|
|
122
127
|
"local-scope-files.mjs",
|
|
123
128
|
"local-scope-repository.mjs",
|
|
124
129
|
"local-scope-signature.mjs",
|
|
130
|
+
"local-scope-config-imports.mjs",
|
|
125
131
|
"local-scope-snapshot.mjs",
|
|
126
132
|
"local-scope-state.mjs",
|
|
127
133
|
"local-scope-workspaces.mjs",
|
package/release-state.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "entrorove.release-state/1.0",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"digest": "
|
|
3
|
+
"version": "0.1.34",
|
|
4
|
+
"digest": "88b67ef8c4be3ddf86777218a7324b095e37b2e6df30a002ac267a48548e2a31",
|
|
5
5
|
"files": {
|
|
6
6
|
"local-final-gate16.mjs": "b30caab08441449ad556a6e9a3cefbf91190f0b3f7370f46d2a21156375aa8e3",
|
|
7
7
|
"local-final-gate16-checks.mjs": "1dd30e9666d458d8b12ca6e4975f6f0ac8450c3ea9cbecc7401ae037f66b589a",
|
|
@@ -44,23 +44,23 @@
|
|
|
44
44
|
"local-autocoord17-waits.mjs": "2b0a713987822548a94e1ed3a9a891532db45383797dfc5d5bc8d1e35593cf25",
|
|
45
45
|
"local-validator-isolation17.mjs": "48e94604e28b8fddd567dfb35ff60b73fd094a5803bd49f076388b7f310f92aa",
|
|
46
46
|
"local-calctool-composition17.mjs": "ac89fcb41ab0d0d9b47c1b5696945281b0894eb064820775e36a011c76314e6a",
|
|
47
|
-
"cli.mjs": "
|
|
47
|
+
"cli.mjs": "b890c2173195edc9ccbaa1f9d1b45a845cad0f1838c300d90a77b1f776c8f178",
|
|
48
48
|
"review-client.mjs": "3491eef68ed533174b31db3c53febb6519b8f088f71a9964644714a9a4c03c77",
|
|
49
49
|
"version.mjs": "1f392147d72c40af4b03b307ea607075fb815af5174fa07e254b95fe12dbf3e7",
|
|
50
|
-
"SKILL.md": "
|
|
51
|
-
"CAPABILITY-MAP.md": "
|
|
50
|
+
"SKILL.md": "11469bd5f51e008c26492d2e01401959451c259e04699dd4b8c833701c27d0b2",
|
|
51
|
+
"CAPABILITY-MAP.md": "f1dd06d99f191daa27f7b1520a3d6d26b1ceba139d30cd287d2b9bfd79459923",
|
|
52
52
|
"AGREEMENT.md": "f93a68e92c457200dd024610e65f74e478b8f60860f951da818b70561f1b9bf8",
|
|
53
|
-
"package.json": "
|
|
53
|
+
"package.json": "559c14f546a781839ed5e741602d26f888a9c98399a397b788c0fc17da1c4083",
|
|
54
54
|
"manifest.json": "ab06e307795bc9da5add926752b6c4dbdaf18625090261a035aa356a679c504f",
|
|
55
|
-
"release.mjs": "
|
|
56
|
-
"local-cli.mjs": "
|
|
55
|
+
"release.mjs": "1b1925df27dd26164874d291c2dbac9a13010fca7892a9d5b529a3e6e99c0139",
|
|
56
|
+
"local-cli.mjs": "a79037d7383a29822b465e6db1c862a43d47cc344f05b6651c849633c49d19f7",
|
|
57
57
|
"local-state-lock.mjs": "1dbf64264642a0851faf043e07ee9f66d2ad0508e9f799b0626246e42fae893e",
|
|
58
|
-
"local-execution.mjs": "
|
|
58
|
+
"local-execution.mjs": "cdada6df6dc8831cebb58a629b56c4b3f8e1bf9aae4e3fdc121521ba20839383",
|
|
59
59
|
"local-integrity.mjs": "4f325376e536999c3b00245f66aac9ef1ae762c33012b363c231622008f72805",
|
|
60
60
|
"local-evidence-verification.mjs": "9b7dea31777505272f63616fd62af7603338f703bb1285fc565d6451715c7ce0",
|
|
61
61
|
"local-formula.mjs": "706d5ec0cb2caf95a547531a81ca746fe246d4c53d902e03595a3b360e8c85af",
|
|
62
62
|
"local-ledger.mjs": "2009fb68aadcd7292b72f1d0d99f378d03644be1c5b4b4150d9f6a0b3f7c15ce",
|
|
63
|
-
"local-error.mjs": "
|
|
63
|
+
"local-error.mjs": "9dc42763ca7013cde607543308e029796d68f3b020a5a3b4ad9e68815e38d0f5",
|
|
64
64
|
"blueprint-criterion-wire.mjs": "fb6b7dcce0b97a699e3e8968372767a3fddd83fedc750998573f789177243072",
|
|
65
65
|
"blueprint-criterion-runner.mjs": "761c0e670b4b20c6bed53e5ca5d0178759505c3977ea2ed1b7223383c534bc4c",
|
|
66
66
|
"local-chain-bindings.mjs": "b8eff999ccd17b53c614a3c9f5376da78fcaa8632bb3e07bc1adcceda2e75f6c",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"local-scope-candidate.mjs": "8f0bd9606e70d4a0ebacdd3cd600ec3afed85e2bb3e1760aa1144cf55d4e028a",
|
|
90
90
|
"local-scope-context.mjs": "79753abfc6c76089d17f003a1be537dfaea10d6731c542f7fc53f2a9996ed164",
|
|
91
91
|
"local-scope-files.mjs": "0671ac4baef610a55ea6c1db6ebca7a4b6cfda45edb8aeaa828019e2a26f5a76",
|
|
92
|
-
"local-scope-repository.mjs": "
|
|
92
|
+
"local-scope-repository.mjs": "af7fe24408509dcebe39bdfc6fcef6adcf66f6ad09473149f920d5e921a48d1a",
|
|
93
93
|
"local-scope-git.mjs": "53bbbb6c4795db711b5bc164591a6ad79a561427da046d6bbe997dae6eb82829",
|
|
94
94
|
"local-scope-git-reads.mjs": "d18d4441664aa59ad8360ee16a69fc0282e7530705d5ae7950944a8158448bb4",
|
|
95
95
|
"local-scope-git-comparison.mjs": "d86e559843087ae851795c9fb16b844dc46cc461fb5da37dbca0f6ba0d06450b",
|
|
@@ -113,12 +113,18 @@
|
|
|
113
113
|
"runtime/git-native-linux-v1.mjs": "cf5cb91426a105e62c0f07a8a230dec592dba46f85a3f708b4c4e8cfcd1126c6",
|
|
114
114
|
"runtime/git-native-darwin-v1.mjs": "f88aab72dc86f94eb1115784872957cb8ed0f74205ae70e1ecd1939e7790e310",
|
|
115
115
|
"local-scope-signature.mjs": "bd05e8cf9e23f9511a16844974362297b9e9d11930ff7b8ad2a490e8d7660fe9",
|
|
116
|
+
"local-scope-config-imports.mjs": "16053142410dd647f13360f29fb3680c3e3a3ebc38019e43af6db05896d92a33",
|
|
116
117
|
"local-scope-snapshot.mjs": "c0f851470b98863a1d187825ed61ee6072d1c057b178fdc85ae29af02a3b250f",
|
|
117
118
|
"local-scope-state.mjs": "8b600a91fc0068d7a8c0bb752ddba7ed30ada93daafb118d6cba2368fd94cb27",
|
|
118
119
|
"local-scope-workspaces.mjs": "a44c34537e5ed2dcaf193a985e5bc05957989fbb160a650f9e37ba7d66eb2de8",
|
|
119
120
|
"local-task-routing.mjs": "e26d6f1ba134ffe1da2a49b4fb6bb6dfa5617671f774a08e719d04f202cf5eca",
|
|
120
|
-
"remote-client.mjs": "
|
|
121
|
-
"cloud-task-client.mjs": "
|
|
121
|
+
"remote-client.mjs": "3c95a81bcad3e53f63071a87929dae4b7c71e6a45034263269c731d9d494d529",
|
|
122
|
+
"cloud-task-client.mjs": "ecb6124ea5e6249f31fb95cb68d13d821d2daea8768fe47ddf6dcf82fc3392cc",
|
|
123
|
+
"scope-runner-client.mjs": "940c841e2c56e92793e5bf65e713bf4087151f721d0ecb659e0a75d6fdefeab9",
|
|
124
|
+
"cloud-watch-client.mjs": "bfbe636c10af467855776f9d29008d9ce13420b66bcc91b5bf8f6ef79fb2aefe",
|
|
125
|
+
"cloud-event-stream.mjs": "e0eec9fc3e0613094523929634f25030df5ca5c5b5fe2c1e1a4586ab10574808",
|
|
126
|
+
"ide-presentation.mjs": "026bf425d06276300ca748a8e22f66596ee52ff268fe0e6ffeff230885533d9a",
|
|
127
|
+
"automatic-feedback-client.mjs": "817e76b7ca4b5a282b9408ac9cf3daf7e09085db5aacbb49d74d8b6bcc4bb611",
|
|
122
128
|
"remote-transport.mjs": "5e5a8c0b490371f7f5a052cffbeee6202d4cf713dff1c43b6d910fe944f8429c",
|
|
123
129
|
"local-credential.mjs": "2a302a7f67b5ea8dc73453fc96ab33db349b59ca11fa9456e48ca1d9669d877c",
|
|
124
130
|
"local-invocations.mjs": "f6ac4c41c1a5ec34de358c4cca210ca8e403b3a913150a43bb55ec9be55d9998",
|
|
@@ -139,8 +145,8 @@
|
|
|
139
145
|
"workflow-local-request.mjs": "4e24c543ce386292a87dc9cd41f90d23375f12079cacffc515c8cd01fd571780",
|
|
140
146
|
"task-message-entry.mjs": "31d10056cb905237cd5649e8eb067009ff1612ec5dc1061e0373209fbc0b646a",
|
|
141
147
|
"task-message-cli.mjs": "3ca65e96c28129b3bd5cac962d106e0859a1f17df1f6a66ee543c6efc22f918d",
|
|
142
|
-
"local-contracts.mjs": "
|
|
143
|
-
"local-contract-types.mjs": "
|
|
148
|
+
"local-contracts.mjs": "e6c6b9b8b8b89e991c5689d935e26ccd92d398405ebced298817d673095bca1e",
|
|
149
|
+
"local-contract-types.mjs": "85e71fa4dd67e351a4b67573c740bcdb1661cede53f097189f11837771e75e91",
|
|
144
150
|
"local-archguard-ast.mjs": "cefd835312a623e83bf48e4d8e1f76ac6a8adc56c35843705c16967d16bec4e6",
|
|
145
151
|
"local-archguard-checkpoint.mjs": "37896902520cc995720c96288e4a5ed3585952b55c9c35be281f91fa754c71ec",
|
|
146
152
|
"local-archguard-components.mjs": "a8fb3d0fd787f9160905013fd333cc0b9e8cf624cce797461f36f4ab31d170ad",
|
package/release.mjs
CHANGED
|
@@ -86,10 +86,13 @@ const sourceFiles = [
|
|
|
86
86
|
'runtime/git-native-linux-v1.mjs',
|
|
87
87
|
'runtime/git-native-darwin-v1.mjs',
|
|
88
88
|
'local-scope-signature.mjs',
|
|
89
|
+
'local-scope-config-imports.mjs',
|
|
89
90
|
'local-scope-snapshot.mjs',
|
|
90
91
|
'local-scope-state.mjs',
|
|
91
92
|
'local-scope-workspaces.mjs',
|
|
92
93
|
'local-task-routing.mjs', 'remote-client.mjs', 'cloud-task-client.mjs',
|
|
94
|
+
'scope-runner-client.mjs',
|
|
95
|
+
'cloud-watch-client.mjs', 'cloud-event-stream.mjs', 'ide-presentation.mjs', 'automatic-feedback-client.mjs',
|
|
93
96
|
'remote-transport.mjs', 'local-credential.mjs', 'local-invocations.mjs',
|
|
94
97
|
'local-task-handoff-fence.mjs',
|
|
95
98
|
'local-task-handoff-storage.mjs', 'local-task-handoff-overlay-wire.mjs', 'local-task-handoff-completion-wire.mjs',
|
|
@@ -257,7 +260,15 @@ function releaseNote(changed) {
|
|
|
257
260
|
if (suppliedZh && suppliedEn) return {
|
|
258
261
|
zh: suppliedZh.replaceAll(/\s+/g, ' '), en: suppliedEn.replaceAll(/\s+/g, ' '),
|
|
259
262
|
}
|
|
260
|
-
|
|
263
|
+
if (changed.includes('scope-runner-client.mjs')) return {
|
|
264
|
+
zh: '补齐账号与任务隔离的本地签名器和真实快照接入,解析实际别名及类型声明;动态依赖仅进入受限规划,保留独立写入核验。',
|
|
265
|
+
en: 'Connected account-bound scope signers and real snapshots, resolved actual aliases and declarations, and retained restricted planning for unresolved dynamic imports with separate mutation verification.',
|
|
266
|
+
}
|
|
267
|
+
const distinct = distinctReleaseLabels(changed, releaseLabels())
|
|
268
|
+
return { zh: `更新了${distinct.map(label => label.zh).join('、')}。`, en: `Updated ${distinct.map(label => label.en).join(', ')}.` }
|
|
269
|
+
}
|
|
270
|
+
function releaseLabels() {
|
|
271
|
+
return withFinalGate16ReleaseLabels({ ...calctoolReleaseLabels, ...mutationReleaseLabels, ...swarmReleaseLabels, ...coordination17ReleaseLabels, ...nativeReadReleaseLabels, ...feedbackReleaseLabels, ...invocationReleaseLabels, ...chainReleaseLabels,
|
|
261
272
|
'blueprint-criterion-wire.mjs': { zh: '蓝图验收标准执行授权', en: 'Blueprint criterion execution authority' },
|
|
262
273
|
'blueprint-criterion-runner.mjs': { zh: '蓝图验收标准实际执行器', en: 'Blueprint criterion process runner' },
|
|
263
274
|
'local-archguard-ast.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
@@ -344,12 +355,11 @@ function releaseNote(changed) {
|
|
|
344
355
|
'task-message-entry.mjs': { zh: '任务消息实际投递入口', en: 'task message host delivery entry' },
|
|
345
356
|
'task-message-cli.mjs': { zh: '任务消息命令与适配器', en: 'task message command and adapter' },
|
|
346
357
|
'cloud-task-client.mjs': { zh: '云端沙箱任务路由与逐任务选择', en: 'cloud sandbox task routing and per-task choice' },
|
|
358
|
+
'cloud-watch-client.mjs': { zh: 'IDE 实时云端进度与推广展示', en: 'live IDE cloud progress and promotion display' },
|
|
359
|
+
'cloud-event-stream.mjs': { zh: 'IDE 实时云端进度与推广展示', en: 'live IDE cloud progress and promotion display' },
|
|
360
|
+
'ide-presentation.mjs': { zh: 'IDE 实时云端进度与推广展示', en: 'live IDE cloud progress and promotion display' },
|
|
361
|
+
'automatic-feedback-client.mjs': { zh: '原调用自动评价回执核验', en: 'original invocation automatic evaluation receipt verification' },
|
|
347
362
|
})
|
|
348
|
-
const distinct = distinctReleaseLabels(changed, labels)
|
|
349
|
-
return {
|
|
350
|
-
zh: `更新了${distinct.map(label => label.zh).join('、')}。`,
|
|
351
|
-
en: `Updated ${distinct.map(label => label.en).join(', ')}.`,
|
|
352
|
-
}
|
|
353
363
|
}
|
|
354
364
|
|
|
355
365
|
async function writeAll(changes) {
|
package/releases.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.1.34",
|
|
4
|
+
"date": "2026-10-12",
|
|
5
|
+
"zh": "补回旧版八技能的 IDE 可见云端选择、真实事件进度与独立推广提示;服务端自动评价绑定原调用并返回可验证回执,支持只读恢复;修复旧式 UUID 调用漏计用量,保持账号隔离及沙箱/调用计数分离。",
|
|
6
|
+
"en": "Restore visible IDE cloud choice, authoritative live progress and separate promotion notices from the original eight-skill workflow. Persist account-bound automatic invocation evaluations with verifiable receipts and read-only recovery; meter legacy UUID calls without mixing skill and sandbox counters."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.1.33",
|
|
10
|
+
"date": "2026-10-12",
|
|
11
|
+
"zh": "补齐账号与任务隔离的本地签名器和真实快照接入,解析实际别名及类型声明;动态依赖仅进入受限规划,保留独立写入核验。",
|
|
12
|
+
"en": "Connected account-bound scope signers and real snapshots, resolved actual aliases and declarations, and retained restricted planning for unresolved dynamic imports with separate mutation verification."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.1.32",
|
|
4
16
|
"date": "2026-10-11",
|