ADR-1244 Phase 4 (D5 trust + D6 upgrade/compat). capability-trust.cjs (disclosure/consent, strict_known_registries, engines+compatVersions, reserved namespace) + capability-lifecycle.cjs (install/upgrade/remove/reconcile; ledger-as-commit-point _pending intent; atomic stage-then-swap; surgical marker-isolated shared-edit strip; owner-token lock) + capability-source promote/skipEnginesGate seams + loader pending-skip + config keys. No sandbox re-derived (consent+integrity+reversibility). 6 Codex adversarial rounds + /security-review (no HIGH) + /code-review; gsd-test green both platforms; CI green. Phase 5 (#1434) wires the CLI dispatch. Closes #1433. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,40 @@ describe('loadRegistry — accepting valid overlays', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadRegistry — uncommitted (_pending) overlay is not activated (ADR-1244 Phase 4)', () => {
|
||||
test('a capability dir whose ledger entry has a _pending intent is skipped with a warning', (t) => {
|
||||
const home = makeOverlayHome([featureCap('pendingcap', { skills: ['pending-skill'] })]);
|
||||
t.after(() => cleanup(home));
|
||||
// Co-located ledger marks the cap as an in-flight (uncommitted) install.
|
||||
fs.writeFileSync(
|
||||
path.join(home, '.gsd-capabilities.json'),
|
||||
JSON.stringify({
|
||||
version: '1', updatedAt: '2026-01-01T00:00:00Z',
|
||||
entries: { pendingcap: { id: 'pendingcap', version: '1.0.0', source: 's', integrity: '', files: [], sharedEdits: [], _pending: { kind: 'install', backupName: null, sharedFiles: [] } } },
|
||||
}),
|
||||
'utf8',
|
||||
);
|
||||
const reg = load(home);
|
||||
assert.ok(!reg.capabilities['pendingcap'], 'uncommitted cap not activated');
|
||||
assert.ok(reg._overlay.warnings.some((w) => w.id === 'pendingcap' && /in progress/.test(w.reason)), 'skip warning recorded');
|
||||
});
|
||||
|
||||
test('once the ledger entry is committed (no _pending) the same dir activates normally', (t) => {
|
||||
const home = makeOverlayHome([featureCap('committedcap', { skills: ['committed-skill'] })]);
|
||||
t.after(() => cleanup(home));
|
||||
fs.writeFileSync(
|
||||
path.join(home, '.gsd-capabilities.json'),
|
||||
JSON.stringify({
|
||||
version: '1', updatedAt: '2026-01-01T00:00:00Z',
|
||||
entries: { committedcap: { id: 'committedcap', version: '1.0.0', source: 's', integrity: '', files: [], sharedEdits: [] } },
|
||||
}),
|
||||
'utf8',
|
||||
);
|
||||
const reg = load(home);
|
||||
assert.ok(reg.capabilities['committedcap'], 'committed cap activates');
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadRegistry — first-party always wins', () => {
|
||||
test('overlay whose id collides with a first-party id is rejected; first-party preserved', (t) => {
|
||||
const home = makeOverlayHome([featureCap('ui', { skills: ['hijacked'] })]);
|
||||
|
||||
Reference in New Issue
Block a user