@theronap/agnoclast-mcp 0.9.178 → 0.9.180
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/lib/arrivals_notice.mjs +5 -1
- package/lib/capture.mjs +40 -0
- package/lib/server.mjs +6 -1
- package/package.json +1 -1
package/lib/arrivals_notice.mjs
CHANGED
|
@@ -83,7 +83,11 @@ export function formatNotice(signals) {
|
|
|
83
83
|
const group = offers.filter((o) => o.via_reason === key)
|
|
84
84
|
if (!group.length) continue
|
|
85
85
|
lines.push(` ${why} (${group.length}):`)
|
|
86
|
-
|
|
86
|
+
// The title is what makes a row judgeable; an id names a unit without saying what it is.
|
|
87
|
+
for (const o of group) {
|
|
88
|
+
const name = o.title ? ` ${o.title}` : ''
|
|
89
|
+
lines.push(` ${o.intakeItemId}${name} · ${o.source} · ${o.hoursAgo}h`)
|
|
90
|
+
}
|
|
87
91
|
}
|
|
88
92
|
// Only when the pile genuinely exceeds the server's scan window; `total` is counted before it.
|
|
89
93
|
if (total > offers.length) lines.push(` … and ${total - offers.length} beyond the scan window`)
|
package/lib/capture.mjs
CHANGED
|
@@ -80,6 +80,46 @@ export function repoFullNameFrom(cwd) {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* The FILES this session is working on, for ADR-0066 §7 session identifiers.
|
|
85
|
+
*
|
|
86
|
+
* 🔴 WHY: the session used to hold only `repo:<owner/name>`, while every record arrives carrying the
|
|
87
|
+
* exact paths it touched. Everything in a repo matches the repo, so on a live session 211 of 217
|
|
88
|
+
* arrivals came back "matched" — a pile with no bounded action in it, which an agent then claims
|
|
89
|
+
* none of. Git already knows the answer precisely, so nothing new has to be plumbed or remembered.
|
|
90
|
+
*
|
|
91
|
+
* Two questions, unioned:
|
|
92
|
+
* working tree vs HEAD — what is being edited right now
|
|
93
|
+
* base..HEAD — what this branch has already committed
|
|
94
|
+
*
|
|
95
|
+
* The second is why this survives a commit: the moment work is committed the working tree goes
|
|
96
|
+
* clean, and a session that had just built something would stop being a candidate for the very
|
|
97
|
+
* records that build produces (its own PR, its own release mail).
|
|
98
|
+
*
|
|
99
|
+
* ⚠ SCOPED TO THIS BRANCH ON PURPOSE. The base is merge-base(HEAD, origin), so a session sitting on
|
|
100
|
+
* an unmodified main reports NOTHING rather than the whole repo's recent history — which would be
|
|
101
|
+
* other people's work, claimed as attention this session never paid.
|
|
102
|
+
*
|
|
103
|
+
* Best-effort and bounded like every other git read here: a non-repo cwd, a detached head or a
|
|
104
|
+
* missing origin yields [], and the caller simply omits the field.
|
|
105
|
+
*/
|
|
106
|
+
export function workingFilesFrom(cwd, max = 40) {
|
|
107
|
+
if (!cwd) return []
|
|
108
|
+
const run = (args) => {
|
|
109
|
+
try {
|
|
110
|
+
return execFileSync('git', ['-C', String(cwd), ...args], {
|
|
111
|
+
encoding: 'utf8', timeout: 2000, stdio: ['ignore', 'pipe', 'ignore'],
|
|
112
|
+
}).split('\n').map((l) => l.trim()).filter(Boolean)
|
|
113
|
+
} catch {
|
|
114
|
+
return []
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const files = new Set(run(['diff', '--name-only', 'HEAD']))
|
|
118
|
+
const base = run(['merge-base', 'HEAD', 'origin/HEAD'])[0] || run(['merge-base', 'HEAD', 'origin/main'])[0]
|
|
119
|
+
if (base) for (const f of run(['diff', '--name-only', base, 'HEAD'])) files.add(f)
|
|
120
|
+
return [...files].slice(0, max)
|
|
121
|
+
}
|
|
122
|
+
|
|
83
123
|
// ── SHR-01/T9 — stamp the repos the session WORKED IN, not the one it was launched from ─────────
|
|
84
124
|
//
|
|
85
125
|
// WHY THIS EXISTS. `repoFullNameFrom(cwd)` above reads the session's LAUNCH directory. Measured
|
package/lib/server.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { buildProposal, renderProposal, withAskNotice } from './propose_obligati
|
|
|
15
15
|
import { renderCaptureStatus } from './capture_status.mjs'
|
|
16
16
|
import { renderTriage } from './red_link_triage.mjs'
|
|
17
17
|
import { runCodeGraphQuery } from './code_graph_cli.mjs'
|
|
18
|
-
import { repoFullNameFrom } from './capture.mjs'
|
|
18
|
+
import { repoFullNameFrom, workingFilesFrom } from './capture.mjs'
|
|
19
19
|
import { spawnObligationWorker } from './obligations_worker.mjs'
|
|
20
20
|
import { renderObligations } from './obligations_render.mjs'
|
|
21
21
|
|
|
@@ -203,6 +203,11 @@ export async function runServer(version) {
|
|
|
203
203
|
cwd: process.cwd(),
|
|
204
204
|
mcpVersion: version,
|
|
205
205
|
repo: repoFullNameFrom(process.cwd()) ?? undefined,
|
|
206
|
+
// files (ADR-0066 §7, 2026-09-25): the exact paths this session is working on, so it can
|
|
207
|
+
// be told apart from every other session in the same repo. Holding only `repo:` made 211
|
|
208
|
+
// of 217 arrivals "matched" on a live session — a pile with no bounded action in it.
|
|
209
|
+
// Best-effort and bounded in workingFilesFrom; a non-repo cwd yields [] and is omitted.
|
|
210
|
+
files: workingFilesFrom(process.cwd()).slice(0, 40),
|
|
206
211
|
}),
|
|
207
212
|
})
|
|
208
213
|
} catch { /* best-effort heartbeat — never disrupt the session */ }
|
package/package.json
CHANGED