mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-31 21:05:20 +00:00
Integrates #3697 on current main. Prefer the observer project ID, retain a sole legacy ID until the new observer folder exists, and release the ending session lease across same-root aliases. Replace the unsafe live merge hint with read-only project inspection, and validate alias IDs before path use. #3711 independently identified the computed-ID selection gap; its early switch without observer data and unchanged SessionEnd path were not adopted.
74 lines
2.2 KiB
JavaScript
Executable File
74 lines
2.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
/**
|
|
* Session end marker hook - performs lightweight observer cleanup and
|
|
* outputs stdin to stdout unchanged. Exports run() for in-process execution.
|
|
*/
|
|
|
|
const {
|
|
resolveProjectContext,
|
|
getAliasContexts,
|
|
removeSessionLease,
|
|
listSessionLeases,
|
|
stopObserverForContext,
|
|
resolveSessionId
|
|
} = require('../lib/observer-sessions');
|
|
const { resolveHookSessionId } = require('../lib/hook-session');
|
|
|
|
function log(message) {
|
|
process.stderr.write(`[SessionEnd] ${message}\n`);
|
|
}
|
|
|
|
function run(rawInput) {
|
|
const output = rawInput || '';
|
|
const sessionId = resolveSessionId(resolveHookSessionId(output));
|
|
|
|
if (!sessionId) {
|
|
log('No session ID available; skipping observer cleanup');
|
|
return output;
|
|
}
|
|
|
|
try {
|
|
const observerContext = resolveProjectContext();
|
|
// Leases from sessions that started before a remote was added sit under the root's older ids.
|
|
const contexts = [observerContext, ...getAliasContexts(observerContext)];
|
|
for (const context of contexts) removeSessionLease(context, sessionId);
|
|
const remainingLeases = contexts.reduce((count, context) => count + listSessionLeases(context).length, 0);
|
|
|
|
if (remainingLeases === 0) {
|
|
for (const context of contexts) {
|
|
if (stopObserverForContext(context)) {
|
|
log(`Stopped observer for project ${context.projectId} after final session lease ended`);
|
|
} else if (context === observerContext) {
|
|
log(`No running observer to stop for project ${context.projectId}`);
|
|
}
|
|
}
|
|
} else {
|
|
log(`Retained observer for project ${observerContext.projectId}; ${remainingLeases} session lease(s) remain`);
|
|
}
|
|
} catch (err) {
|
|
log(`Observer cleanup skipped: ${err.message}`);
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
// Legacy CLI execution (when run directly)
|
|
if (require.main === module) {
|
|
const MAX_STDIN = 1024 * 1024;
|
|
let raw = '';
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', chunk => {
|
|
if (raw.length < MAX_STDIN) {
|
|
const remaining = MAX_STDIN - raw.length;
|
|
raw += chunk.substring(0, remaining);
|
|
}
|
|
});
|
|
process.stdin.on('end', () => {
|
|
process.stdout.write(run(raw));
|
|
});
|
|
}
|
|
|
|
module.exports = { run };
|