engineering-memory 1.0.0 → 1.2.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "engineering-memory",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Installs the Engineering Memory skill and its local MCP bridge. Sign in after installing; your organization and project are resolved from your account.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -4,6 +4,7 @@ import { assertManagedPath, canonicalPath } from '../utilities/files.js';
|
|
|
4
4
|
import { sha256, stableStringify } from '../utilities/hash.js';
|
|
5
5
|
import { NativeCommandRunner } from '../utilities/process.js';
|
|
6
6
|
export const temporaryScaffoldingMarker = 'ENGINEERING-MEMORY-TEMPORARY';
|
|
7
|
+
export const temporaryScaffoldingPattern = `${temporaryScaffoldingMarker}:`;
|
|
7
8
|
export class GitInspector {
|
|
8
9
|
runner;
|
|
9
10
|
constructor(runner = new NativeCommandRunner()) {
|
|
@@ -47,6 +48,7 @@ export class GitInspector {
|
|
|
47
48
|
repoRoot: root,
|
|
48
49
|
head,
|
|
49
50
|
changedPaths,
|
|
51
|
+
worktreeHash: sha256(`${stableStringify(normalizedManifest)}\n`),
|
|
50
52
|
diffHash: sha256(`${head ?? '<unborn>'}\n${stableStringify(normalizedManifest)}\n`),
|
|
51
53
|
};
|
|
52
54
|
}
|
|
@@ -303,7 +305,7 @@ export class GitInspector {
|
|
|
303
305
|
return [...found.values()].sort((left, right) => left.path === right.path ? left.line - right.line : left.path.localeCompare(right.path));
|
|
304
306
|
}
|
|
305
307
|
async markerMatches(root, scope, origin) {
|
|
306
|
-
const result = await this.runner.run('git', ['grep', '--no-color', '-n', '-I', '-F', ...scope, '-e',
|
|
308
|
+
const result = await this.runner.run('git', ['grep', '--no-color', '-n', '-I', '-F', ...scope, '-e', temporaryScaffoldingPattern], { cwd: root });
|
|
307
309
|
if (result.exitCode !== 0)
|
|
308
310
|
return [];
|
|
309
311
|
return result.stdout
|
|
@@ -81,6 +81,13 @@ export const engineeringMemoryToolNames = [
|
|
|
81
81
|
'auth.signin_browser',
|
|
82
82
|
'auth.logout',
|
|
83
83
|
];
|
|
84
|
+
const discoverableKindNames = [
|
|
85
|
+
'screen_logic',
|
|
86
|
+
'component_mapping',
|
|
87
|
+
'module_logic',
|
|
88
|
+
'data_model',
|
|
89
|
+
'api_endpoint',
|
|
90
|
+
];
|
|
84
91
|
const reconciliationEntry = z.object({
|
|
85
92
|
resourceId: z.string().min(1),
|
|
86
93
|
type: z.enum(['approved_revision', 'no_semantic_memory_change']),
|
|
@@ -193,6 +200,9 @@ export function registerEngineeringMemoryTools(server, service) {
|
|
|
193
200
|
'figma_mapping',
|
|
194
201
|
'figma_reference',
|
|
195
202
|
'flow_logic',
|
|
203
|
+
'module_logic',
|
|
204
|
+
'data_model',
|
|
205
|
+
'api_endpoint',
|
|
196
206
|
'current_deviation',
|
|
197
207
|
'quality_gate',
|
|
198
208
|
'task_history',
|
|
@@ -348,7 +358,7 @@ export function registerEngineeringMemoryTools(server, service) {
|
|
|
348
358
|
newResources: z
|
|
349
359
|
.array(z.object({
|
|
350
360
|
path: z.string().min(1),
|
|
351
|
-
kind: z.enum(
|
|
361
|
+
kind: z.enum(discoverableKindNames),
|
|
352
362
|
resourceKey: z.string().min(2),
|
|
353
363
|
}))
|
|
354
364
|
.optional(),
|
|
@@ -382,13 +392,7 @@ export function registerEngineeringMemoryTools(server, service) {
|
|
|
382
392
|
content: z.string().min(2),
|
|
383
393
|
discoveryUnits: z
|
|
384
394
|
.array(z.object({
|
|
385
|
-
kind: z.enum(
|
|
386
|
-
'screen_logic',
|
|
387
|
-
'component_mapping',
|
|
388
|
-
'module_logic',
|
|
389
|
-
'data_model',
|
|
390
|
-
'api_endpoint',
|
|
391
|
-
]),
|
|
395
|
+
kind: z.enum(discoverableKindNames),
|
|
392
396
|
patterns: z.array(z.string().min(1)).min(1),
|
|
393
397
|
}))
|
|
394
398
|
.min(1)
|
|
@@ -94,7 +94,9 @@ export class BridgeService {
|
|
|
94
94
|
taskKind: persistedBootstrap.taskKind,
|
|
95
95
|
mode: persistedBootstrap.mode ?? 'write',
|
|
96
96
|
repoFingerprint: repository.repoFingerprint,
|
|
97
|
-
...(input.mode === 'read_only'
|
|
97
|
+
...(input.mode === 'read_only'
|
|
98
|
+
? { baselineDiffHash: repository.git.worktreeHash }
|
|
99
|
+
: {}),
|
|
98
100
|
checkpointIdempotencyKey: checkpointId,
|
|
99
101
|
knownRevisions: persistedBootstrap.knownRevisions,
|
|
100
102
|
}),
|
|
@@ -1009,6 +1011,7 @@ export class BridgeService {
|
|
|
1009
1011
|
changedPaths: taskMode === 'read_only' ? [] : taskChangedPaths,
|
|
1010
1012
|
pathChanges: pathChangeManifest,
|
|
1011
1013
|
diffHash: repository.git.diffHash,
|
|
1014
|
+
...(taskMode === 'read_only' ? { worktreeHash: repository.git.worktreeHash } : {}),
|
|
1012
1015
|
validations,
|
|
1013
1016
|
pendingOutboxCount,
|
|
1014
1017
|
newResources: input.newResources,
|
|
@@ -1305,12 +1308,19 @@ export class BridgeService {
|
|
|
1305
1308
|
const authenticated = authentication.authenticated === true;
|
|
1306
1309
|
const state = decision?.state ?? (repository.projectId ? 'bound' : 'none');
|
|
1307
1310
|
const client = await this.clientUpdate(authenticated);
|
|
1311
|
+
const shipped = objectValue(objectValue(client)?.shippedKnowledge);
|
|
1312
|
+
const incomplete = shipped && (shipped.failure !== null || Number(shipped.live) < Number(shipped.expected));
|
|
1308
1313
|
return asJsonValue({
|
|
1309
1314
|
authenticated,
|
|
1310
1315
|
repository: publicRepository(repository),
|
|
1311
1316
|
decision: state,
|
|
1312
1317
|
projectId: repository.projectId ?? decision?.projectId ?? null,
|
|
1313
1318
|
client,
|
|
1319
|
+
...(incomplete
|
|
1320
|
+
? {
|
|
1321
|
+
shippedKnowledgeWarning: 'The backend is not serving all of the knowledge this release ships. Tell the user before relying on the rules: some are missing from the running server, so a review against them is incomplete. The counts and the reason are in client.shippedKnowledge.',
|
|
1322
|
+
}
|
|
1323
|
+
: {}),
|
|
1314
1324
|
nextAction: entryNextAction(authenticated, state),
|
|
1315
1325
|
});
|
|
1316
1326
|
});
|
|
@@ -2393,6 +2403,16 @@ export function newMemoryResourceCandidate(entry, policy) {
|
|
|
2393
2403
|
]).has(extension)) {
|
|
2394
2404
|
return [];
|
|
2395
2405
|
}
|
|
2406
|
+
const name = entry.path.toLowerCase().split('/').slice(-1)[0] ?? '';
|
|
2407
|
+
if (name.endsWith('.entity.ts')) {
|
|
2408
|
+
return [{ path: entry.path, kind: 'data_model' }];
|
|
2409
|
+
}
|
|
2410
|
+
if (name.endsWith('.controller.ts')) {
|
|
2411
|
+
return [{ path: entry.path, kind: 'api_endpoint' }];
|
|
2412
|
+
}
|
|
2413
|
+
if (name.endsWith('.module.ts') || name.endsWith('.service.ts')) {
|
|
2414
|
+
return [{ path: entry.path, kind: 'module_logic' }];
|
|
2415
|
+
}
|
|
2396
2416
|
const segments = entry.path.toLowerCase().split('/').slice(0, -1);
|
|
2397
2417
|
const screenIndex = segments.findIndex((segment) => ['screen', 'screens', 'view', 'views'].includes(segment));
|
|
2398
2418
|
const componentIndex = segments.findIndex((segment) => ['widget', 'widgets', 'component', 'components'].includes(segment));
|
|
@@ -66,7 +66,7 @@ Send calls that do not feed each other in one batch rather than one at a time: r
|
|
|
66
66
|
|
|
67
67
|
Checkpoints, recorded corrections and reconciliations return before the backend has them, reporting `deliveryStatus: 'pending'` with the task version they will occupy. That is a completed call, not a pending one: the journal is already durable, delivery is already under way, and `task.verify` refuses while anything remains undelivered. Do not wait for it, poll it, or send it again. Wait only for what the next step uses — a proposal's identifiers, an approval's revision, a prepared lease, and verification itself.
|
|
68
68
|
|
|
69
|
-
Temporary code written to reach or force a path — a pinned state, a fixed service response, a jump straight to the screen — is allowed and expected, carries the marker `ENGINEERING-MEMORY-TEMPORARY`
|
|
69
|
+
Temporary code written to reach or force a path — a pinned state, a fixed service response, a jump straight to the screen — is allowed and expected, carries the marker `ENGINEERING-MEMORY-TEMPORARY` immediately followed by a colon and its reason, and is removed before verification. `task.verify` refuses while any marker is in the tree and names every line, and the commit gate refuses while one is staged.
|
|
70
70
|
|
|
71
71
|
Do not write task Markdown files directly. The bridge owns event IDs, expected task versions, atomic projections, outbox state, and synchronization.
|
|
72
72
|
|