engineering-memory 1.3.0 → 1.4.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.0",
3
+ "version": "1.4.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",
@@ -363,6 +363,11 @@ export function registerEngineeringMemoryTools(server, service) {
363
363
  resourceKey: z.string().min(2),
364
364
  }))
365
365
  .optional(),
366
+ introducedStructures: z
367
+ .array(z.string().min(2).max(80))
368
+ .max(20)
369
+ .optional()
370
+ .describe('Architectural structures this task adds that the project did not have: a cache, a broker, a read replica, a second deployable, a projection, an event store. Verification refuses any the project profile has not recorded under architecture.adopted with the pressure it relieves.'),
366
371
  }),
367
372
  }, async (input) => toolResult(await service.taskVerify(input)));
368
373
  server.registerTool('task.close', {
@@ -957,6 +957,7 @@ export class BridgeService {
957
957
  }
958
958
  let taskChangedPaths = [];
959
959
  let taskChanges = [];
960
+ let foreignChangedPaths = [];
960
961
  const snapshotResponse = await this.dependencies.client.request(endpoints.sessionResume, {
961
962
  method: 'POST',
962
963
  body: {
@@ -994,7 +995,13 @@ export class BridgeService {
994
995
  if (!baseline || activeLease?.baselineDiffHash !== baseline.diffHash) {
995
996
  throw new Error('Write task verification requires its locally pinned change baseline');
996
997
  }
997
- taskChanges = manifestDelta(baseline.changedPaths, repository.git.changedPaths);
998
+ const wholeTreeDelta = manifestDelta(baseline.changedPaths, repository.git.changedPaths);
999
+ const leased = new Set(normalizeChangedPaths([...baseline.leasePaths, ...leaseChangedPaths]));
1000
+ taskChanges = wholeTreeDelta.filter((entry) => leased.has(normalizeChangedPaths([entry.path])[0]));
1001
+ foreignChangedPaths = wholeTreeDelta
1002
+ .filter((entry) => !leased.has(normalizeChangedPaths([entry.path])[0]))
1003
+ .map((entry) => entry.path)
1004
+ .sort();
998
1005
  taskChangedPaths = taskChanges.map((entry) => entry.path).sort();
999
1006
  if (input.changedPaths &&
1000
1007
  stableStringify(normalizeChangedPaths(input.changedPaths)) !==
@@ -1033,6 +1040,7 @@ export class BridgeService {
1033
1040
  validations,
1034
1041
  pendingOutboxCount,
1035
1042
  newResources: input.newResources,
1043
+ introducedStructures: input.introducedStructures,
1036
1044
  });
1037
1045
  await this.dependencies.activeContexts.setVerificationIntent(repository.repoFingerprint, {
1038
1046
  mode: taskMode,
@@ -1072,6 +1080,9 @@ export class BridgeService {
1072
1080
  return asJsonValue({
1073
1081
  ...objectOrEmpty(response.data),
1074
1082
  mode: taskMode,
1083
+ ...(foreignChangedPaths.length > 0
1084
+ ? { changedPathsOutsideThisTask: foreignChangedPaths }
1085
+ : {}),
1075
1086
  repository: publicRepository(repository),
1076
1087
  });
1077
1088
  });
@@ -128,6 +128,8 @@ For each changed screen or component, call `task.reconcile` with an approved pro
128
128
 
129
129
  Record `handoff_before`, then call `task.verify`. For a write task, verify the exact changed paths, current diff hash, validations, session, and lease. For a read-only task, send no changed paths, lease, or write baseline; the bridge supplies the current Git diff hash and the backend compares it with the baseline captured at bootstrap while also verifying bootstrap, discovery, validation-before, validation-after, handoff, pinned read receipts, and synchronized outbox evidence. If verification fails, resolve the reported gap and verify again. Do not state that the task is complete while verification is failing, and do not carry on writing code with the failure unaddressed — a task that never verifies never closes, and everything that depends on closing, including the commit gate, silently never happens.
130
130
 
131
+ When a task adds a structure the system did not have — a cache, a broker, a read replica, a second deployable, a projection, an event store — name it in `introducedStructures` at verification. The backend refuses any the project profile has not recorded under `architecture.adopted`, with the pressure it relieves, and refuses with the stated reason any the project recorded as deliberately declined. Recording it is a project profile revision like any other: propose, have the user approve, reconcile. Do not reach for the structure first and record it afterwards — the point of the record is that somebody decided.
132
+
131
133
  A new screen or component fails verification until its memory exists, which takes four steps in order: `memory.propose_revision` for each new path, the user's explicit approval, `memory.review_proposal`, then `task.reconcile`. The error names the paths. Walk the chain rather than retrying the same verification.
132
134
 
133
135
  Call `task.close` only after verification and only when the current diff still matches. The Git hook performs a fresh authenticated commit-gate check against the closed task, current membership, repository fingerprint, diff hash, and knowledge revisions. A local receipt alone never authorizes commit. Closing a task does not authorize commit, push, publish, deploy, tag, or merge.