@staix/agent-hub 0.16.0 → 0.18.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/CHANGELOG.md +34 -0
- package/README.md +2 -2
- package/docs/agent-notes/README.md +5 -0
- package/docs/agent-notes/adapters.md +20 -5
- package/docs/agent-notes/benchmarks.md +1 -0
- package/docs/agent-notes/daemon.md +5 -3
- package/docs/agent-notes/local-worker.md +1 -0
- package/docs/agent-notes/tasks.md +9 -3
- package/docs/agent-notes/tests.md +6 -3
- package/docs/dogfood.md +21 -4
- package/docs/memory.md +1 -1
- package/docs/operations.md +150 -34
- package/docs/profiles.md +36 -0
- package/docs/quickstart.md +14 -4
- package/docs/roles.md +1 -0
- package/docs/sdlc.md +39 -13
- package/docs/security.md +41 -9
- package/docs/smoke.md +51 -3
- package/docs/specs/2026-09-19-agent-hub-design.md +56 -10
- package/docs/specs/2026-09-20-upgrade-recovery-design.md +3 -1
- package/docs/verification/2026-10-25-0.17.0.md +74 -0
- package/docs/verification/2026-10-25-0.18.0.md +76 -0
- package/docs/verification/2026-10-25-codex-0164-reviewer-tool-call.md +52 -0
- package/docs/verification/2026-10-25-codex-review-live-verdict.md +35 -0
- package/docs/verification/2026-10-25-kimi-231-reviewer-compat.md +48 -0
- package/docs/verification/2026-10-25-kimi-usage-ac11.md +48 -0
- package/docs/verification/2026-10-25-qwen-dual-output-hub-e2e.md +23 -0
- package/docs/verification/2026-10-25-qwen-dual-output-t0.md +20 -0
- package/docs/verification/2026-10-25-remote-docker-transport.md +46 -0
- package/docs/verification/2026-10-25-reviewer-no-verdict-diagnostics.md +35 -0
- package/docs/verification/profiles/YYYY-MM-DD-general.md +46 -0
- package/docs/verification/profiles/YYYY-MM-DD-research.md +61 -0
- package/docs/verification/profiles/YYYY-MM-DD-writing.md +46 -0
- package/docs/verified.json +28 -19
- package/package.json +2 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +1115 -192
- package/src/adapters/codex-review-isolation.ts +10 -1
- package/src/adapters/compat.ts +7 -2
- package/src/adapters/conformance/enrollment.ts +18 -4
- package/src/adapters/conformance/factories.ts +4 -1
- package/src/adapters/conformance/kit.ts +11 -0
- package/src/adapters/definitions/builtin-metadata.ts +1 -1
- package/src/adapters/definitions/native-cli-entry-qwen.ts +32 -4
- package/src/adapters/definitions/native-cli-preview-qwen.ts +9 -1
- package/src/adapters/definitions/native-factories.ts +8 -0
- package/src/adapters/definitions/native-recovery.ts +8 -0
- package/src/adapters/definitions/qwen.ts +7 -4
- package/src/adapters/local-worker.ts +5 -3
- package/src/adapters/qwen-dual.ts +578 -0
- package/src/adapters/registry-types.ts +5 -1
- package/src/adapters/registry.ts +9 -1
- package/src/adapters/reviewer-mcp.ts +12 -6
- package/src/adapters/reviewer-print.ts +100 -17
- package/src/cli/console-state.ts +9 -2
- package/src/cli/help.ts +29 -28
- package/src/cli/identity.ts +87 -6
- package/src/cli/main.ts +190 -69
- package/src/cli/output.ts +7 -2
- package/src/cli/sdlc-output.ts +242 -0
- package/src/cli/task-output.ts +212 -0
- package/src/cli/upgrade-output.ts +57 -0
- package/src/cli/upgrade.ts +4 -3
- package/src/hub/board.ts +17 -0
- package/src/hub/check-runner.ts +252 -22
- package/src/hub/conductor.ts +5 -0
- package/src/hub/config-apply.ts +16 -7
- package/src/hub/config-edit-host.ts +1 -1
- package/src/hub/config-tier.ts +1 -1
- package/src/hub/daemon.ts +487 -94
- package/src/hub/dogfood-profile.ts +248 -0
- package/src/hub/dogfood-read.ts +77 -14
- package/src/hub/dogfood.ts +5 -1
- package/src/hub/events.ts +1 -1
- package/src/hub/host-executable.ts +2 -1
- package/src/hub/hub-tools.ts +2 -2
- package/src/hub/memory-plan-guard.ts +8 -33
- package/src/hub/operational-authority.ts +60 -0
- package/src/hub/operational-view.ts +141 -0
- package/src/hub/orphan-process.ts +69 -0
- package/src/hub/permission-mode.ts +1 -1
- package/src/hub/read-only-shell-proof.ts +80 -0
- package/src/hub/read-only-shell.ts +162 -0
- package/src/hub/reviewer-pool-config.ts +3 -2
- package/src/hub/reviewer-pool.ts +3 -0
- package/src/hub/routing.ts +23 -6
- package/src/hub/sdlc-merge.ts +299 -0
- package/src/hub/sdlc-mirror.ts +129 -0
- package/src/hub/sdlc.ts +58 -12
- package/src/hub/settings.ts +11 -5
- package/src/hub/snapshots.ts +60 -0
- package/src/hub/task-repository.ts +31 -5
- package/src/hub/tasks.ts +266 -28
- package/src/local/tools.ts +17 -4
- package/src/memory/brief.ts +45 -5
- package/src/ui/index.html +2 -1
package/src/memory/brief.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildIntentBrief, type IntentBriefOptions, type IntentBriefSource } from "@staix/agent-mem";
|
|
1
2
|
import type { PeerId } from "../hub/envelope.ts";
|
|
2
3
|
import type { MemoryClient } from "./client.ts";
|
|
3
4
|
|
|
@@ -30,17 +31,20 @@ export async function related(client: MemoryClient, project: string, query: stri
|
|
|
30
31
|
/** A native memory line for a brief (#258): `mem:<id8> <kind> <tier>: <title or text>`, fails first. */
|
|
31
32
|
export interface NativeItem { id: string; line: string; kind?: string; about?: readonly string[]; tier?: string; peer?: string; machine?: string; at?: string }
|
|
32
33
|
export type NativeBrief = (task: BriefTask) => NativeItem[] | Promise<NativeItem[]>;
|
|
34
|
+
export interface IntentBriefContext { source: IntentBriefSource; options: IntentBriefOptions }
|
|
35
|
+
/** Host-owned policy and store binding; the library owns relevance, ordering and text. */
|
|
36
|
+
export type IntentBriefHost = (task: BriefTask) => IntentBriefContext | Promise<IntentBriefContext>;
|
|
33
37
|
export interface BriefTask { id?: number; created?: number; title: string; refs: { paths?: string[] }; plan?: { paths?: string[]; symbols?: string[] } }
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* the
|
|
40
|
-
* twice in one hub run, except a directly matching plan fail that must accompany a new task.
|
|
40
|
+
* Production task briefs use the library's intent retrieval and rendering with host policy and bindings.
|
|
41
|
+
* The hub applies its per-peer delivery dedupe and item cap to complete library rows, reserving the front
|
|
42
|
+
* for host-screened plan fails even when the library's byte cap omitted them. Injected clients without
|
|
43
|
+
* the library port retain the legacy index/timeline bridge; intent mode retires its related/readNotice path.
|
|
41
44
|
*/
|
|
42
45
|
export class Briefs {
|
|
43
46
|
private readonly seen = new Map<PeerId, Set<string>>();
|
|
47
|
+
private readonly libraryRuns = new Map<PeerId, Promise<unknown>>();
|
|
44
48
|
|
|
45
49
|
constructor(
|
|
46
50
|
private readonly client: MemoryClient | undefined,
|
|
@@ -50,11 +54,47 @@ export class Briefs {
|
|
|
50
54
|
/** Counts of what a brief carried, for the research records (#258 AC11); never its text. */
|
|
51
55
|
private readonly observe?: (peer: PeerId, task: number, counts: { native: number; fails: number; claudeMem: number }) => void,
|
|
52
56
|
private readonly displayNative?: (items: readonly NativeItem[]) => string[],
|
|
57
|
+
private readonly intent?: IntentBriefHost,
|
|
53
58
|
) {}
|
|
54
59
|
|
|
55
60
|
async forTask(peer: PeerId, task: BriefTask, priority: readonly NativeItem[] = []): Promise<string | undefined> {
|
|
56
61
|
// A brief snapshots its configured cap once, before either optional source is selected.
|
|
57
62
|
const maximum = typeof this.maxItems === "function" ? this.maxItems() : this.maxItems;
|
|
63
|
+
if (this.intent) {
|
|
64
|
+
// Serialize only this peer's library reads, so awaited policy cannot duplicate a delivered note.
|
|
65
|
+
const previous = this.libraryRuns.get(peer);
|
|
66
|
+
const run = (async () => {
|
|
67
|
+
await previous?.catch(() => undefined);
|
|
68
|
+
if (maximum < 1) return undefined;
|
|
69
|
+
try {
|
|
70
|
+
const context = await this.intent!(task);
|
|
71
|
+
const seen = this.seen.get(peer) ?? new Set<string>();
|
|
72
|
+
this.seen.set(peer, seen);
|
|
73
|
+
const revision = context.options.policyVersion();
|
|
74
|
+
const result = await buildIntentBrief(context.source, context.options);
|
|
75
|
+
if (result.state === "unknown" || context.options.allowed?.() === false || context.options.policyVersion() !== revision) return undefined;
|
|
76
|
+
context.options.assertCurrent?.();
|
|
77
|
+
const lines = result.text.split("\n");
|
|
78
|
+
const rendered = new Map(result.items.map((item, index) => [`mem:${item.id}`, lines[index + 1]!]));
|
|
79
|
+
const selected: NativeItem[] = [];
|
|
80
|
+
// Priority is already screened and sanitized by the host's plan guard. Its advice must survive
|
|
81
|
+
// the standalone library's byte cap or narrower retrieval policy, and recur with the next task.
|
|
82
|
+
for (const item of priority) if (selected.length < maximum && !selected.some(row => row.id === item.id)) selected.push({ ...item, line: rendered.get(item.id) ?? item.line });
|
|
83
|
+
for (const item of result.items) {
|
|
84
|
+
const id = `mem:${item.id}`;
|
|
85
|
+
if (selected.length < maximum && !seen.has(id) && !selected.some(row => row.id === id)) selected.push({ id, line: rendered.get(id)!, kind: item.kind });
|
|
86
|
+
}
|
|
87
|
+
if (!selected.length) return undefined;
|
|
88
|
+
// Preserve complete library rows (including graph neighbours after a seen direct bridge).
|
|
89
|
+
const text = [lines[0] || "Live fail notes for this plan (advice, not a block):", ...selected.map(item => item.line)].join("\n");
|
|
90
|
+
for (const item of selected) seen.add(item.id);
|
|
91
|
+
if (task.id !== undefined) try { this.observe?.(peer, task.id, { native: selected.length, fails: selected.filter(item => item.kind === "fail").length, claudeMem: 0 }); } catch { /* telemetry never fails a brief */ }
|
|
92
|
+
return text;
|
|
93
|
+
} catch { return undefined; }
|
|
94
|
+
})();
|
|
95
|
+
this.libraryRuns.set(peer, run);
|
|
96
|
+
try { return await run; } finally { if (this.libraryRuns.get(peer) === run) this.libraryRuns.delete(peer); }
|
|
97
|
+
}
|
|
58
98
|
const seen = this.seen.get(peer) ?? new Set<string>();
|
|
59
99
|
this.seen.set(peer, seen);
|
|
60
100
|
let native: NativeItem[] = [];
|
package/src/ui/index.html
CHANGED
|
@@ -1399,7 +1399,8 @@ function renderBoard(snapshot, peers, ids) {
|
|
|
1399
1399
|
const data=(snapshot.boardLegend || []).find(item=>item.peer===id), row=el('div',undefined,'agent-slot');
|
|
1400
1400
|
row.append(peerMark(id),el('p',String(peers[id].state || 'unknown'),'meta'));
|
|
1401
1401
|
const wip=data && Number.isSafeInteger(data.wip) && data.wip>=0 ? data.wip : 'unknown';
|
|
1402
|
-
|
|
1402
|
+
const split=data?.wipBreakdown,splitText=split && [split.active,split.reviewWait,split.reserved].every(Number.isSafeInteger) ? ' (active '+split.active+', review-wait '+split.reviewWait+', reserved '+split.reserved+')' : '';
|
|
1403
|
+
row.append(el('p','WIP '+wip+(Number.isSafeInteger(data?.wipLimit) ? '/'+data.wipLimit : '')+splitText+' / permission '+(data?.permissionMode || 'unknown'),'meta'));
|
|
1403
1404
|
if (Array.isArray(data?.activeTasks) && data.activeTasks.length) row.append(el('p','Active tasks: '+data.activeTasks.map(id=>'#'+id).join(', '),'meta'));
|
|
1404
1405
|
const filter=el('button','View '+id);filter.type='button';filter.addEventListener('click',()=>{if(!boardViewState)return;peerFilter.value=id;renderBoard(boardViewState.snapshot,boardViewState.peers,boardViewState.ids)});row.append(filter);
|
|
1405
1406
|
if (eligible.includes(id)) dropTarget(row,card=>card.assignable,{action:'assign',peer:id});
|