feat: per-change-block hunk actions (#50), codex lanes without a pipeline, macOS LaunchAgent
- git (#50): stage-hunk/discard-hunk take an optional `block` — one run of consecutive +/- lines inside an @@ hunk. `onlyBlock` (server/lib/git-diff.js) cuts git's fresh hunk down to it, folding the other blocks into the side being checked; LaneDiffView hangs one review bar per block (unified + split) and its arrows walk blocks. - git exclude: entries AgentHub writes for a lane go to the COMMON git dir with the lane's path prefix (server/lib/git-exclude.js, used by router-apply and lane-mcp) — a linked worktree's own info/exclude is never read by git, and a subdir lane has no .git. MCP sync no longer fails with ENOTDIR on a worktree lane or creates a stray .git in a non-repo lane. - codex lanes carry no pipeline: codex-ingest mirrors only idle/running, codex-nudge is removed, agents install writes nothing for codex, the Workspace hides stage/pipeline/feature pickers/PipelineMap for them, and every server start clears leftover codex stage data and the old AGENTS.md stage block. - Changes panel: a whole file opens for reading and enters the editor on a click on its text (caret at the clicked line), not automatically. - macOS: LaunchAgent start-at-login (scripts/launchd-service.js, picked by scripts/service-manager.js). - Adds the AgentHub introduction slides and their image-embedding script.
This commit is contained in:
+31
-11
@@ -410,13 +410,7 @@ function reservedPorts(excludeLaneId = null) {
|
||||
* of where the agent now says it is has not been passed for this pass; it has
|
||||
* to be re-earned. Records under a key matching no node in the pipeline are
|
||||
* left untouched — their position is unknown, so they cannot be proven ahead.
|
||||
*
|
||||
* `keepDetection` is the ONE exception to that clearing, and exists for exactly
|
||||
* one caller: codex-ingest.js, which advances a codex lane's stage FROM its own
|
||||
* detection. There the detection is not stale evidence of something the
|
||||
* declaration superseded — it is the reason for the declaration, and the card
|
||||
* has to keep saying so, or an inferred stage becomes indistinguishable from
|
||||
* one the agent actually claimed.
|
||||
|
||||
*/
|
||||
/**
|
||||
* Append one row to the stage log — the history `lanes.stages` cannot keep,
|
||||
@@ -472,7 +466,7 @@ function appendStageEvent(lane, nodeId, { source, result, evidence } = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
function setStage(id, { stage, status, evidence, note, result, keepDetection } = {}) {
|
||||
function setStage(id, { stage, status, evidence, note, result } = {}) {
|
||||
const lane = getLane(id);
|
||||
if (!lane) throw Object.assign(new Error(`no lane ${id}`), { code: "ENOLANE" });
|
||||
const next = stage || lane.stage;
|
||||
@@ -495,9 +489,7 @@ function setStage(id, { stage, status, evidence, note, result, keepDetection } =
|
||||
};
|
||||
db.prepare(
|
||||
`UPDATE lanes SET stage = ?, stage_since = ?, status = ?, stages = ?, notes = ?, updated_at = ?${
|
||||
changed && !keepDetection
|
||||
? ", detected_stage = NULL, detected_signal = NULL, detected_at = NULL"
|
||||
: ""
|
||||
changed ? ", detected_stage = NULL, detected_signal = NULL, detected_at = NULL" : ""
|
||||
}
|
||||
WHERE id = ?`
|
||||
).run(
|
||||
@@ -864,6 +856,33 @@ function purgeLaneSessions(laneId) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codex lanes carry no pipeline, but older builds inferred and advanced one for
|
||||
* them. Wipe what those builds left — the stage columns, the stage log and any
|
||||
* feature records — so nothing stale survives into the Workflows statistics or
|
||||
* resurfaces if a view ever reads it. Idempotent; run at every server start.
|
||||
*
|
||||
* @returns {number} how many codex lanes still carried pipeline data
|
||||
*/
|
||||
function clearCodexPipelines() {
|
||||
const CODEX = "SELECT id FROM lanes WHERE tool = 'codex'";
|
||||
let changed = 0;
|
||||
db.transaction(() => {
|
||||
changed = db
|
||||
.prepare(
|
||||
`UPDATE lanes SET stage = 'idle', stage_since = NULL, stages = '{}',
|
||||
detected_stage = NULL, detected_signal = NULL, detected_at = NULL
|
||||
WHERE tool = 'codex' AND (stage <> 'idle' OR stages <> '{}' OR detected_stage IS NOT NULL
|
||||
OR id IN (SELECT lane_id FROM lane_stage_events)
|
||||
OR id IN (SELECT lane_id FROM lane_features))`
|
||||
)
|
||||
.run().changes;
|
||||
db.prepare(`DELETE FROM lane_stage_events WHERE lane_id IN (${CODEX})`).run();
|
||||
db.prepare(`DELETE FROM lane_features WHERE lane_id IN (${CODEX})`).run();
|
||||
})();
|
||||
return changed;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEAD_SEC,
|
||||
VALID_TOOLS,
|
||||
@@ -875,6 +894,7 @@ module.exports = {
|
||||
updateLane,
|
||||
deleteLane,
|
||||
setStage,
|
||||
clearCodexPipelines,
|
||||
setRouterProfile,
|
||||
lanesByRouter,
|
||||
recordDetection,
|
||||
|
||||
Reference in New Issue
Block a user