@hmharness/agent 0.19.1 → 0.19.3

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @hmharness/agent - cognitive query tool (blueprint §18/UX-004 seed)
3
+ *
4
+ * Gives the LIVE model read access to its own accumulated world model:
5
+ * which tool types historically succeed, how calibrated its predictions
6
+ * are, and what the diagnosis layer thinks is worth learning. Read-only by
7
+ * design — the model cannot write beliefs; those update only from real
8
+ * trajectories (no self-grading channel).
9
+ */
10
+ import type { Tool } from '@hmharness/kernel';
11
+ export declare const cognitiveQueryTool: Tool;
@@ -0,0 +1,53 @@
1
+ export const cognitiveQueryTool = {
2
+ name: 'cognitive_query',
3
+ description: 'Query the cognitive layer\'s accumulated knowledge about past runs: which action/tool types historically succeed (belief table with confidence and evidence counts), prediction calibration, planner-trusted action types, learning opportunities, and memory contradictions. Read-only. Args: focus=beliefs|calibration|diagnosis|memory (optional; omit for a summary).',
4
+ parameters: {
5
+ type: 'object',
6
+ properties: {
7
+ focus: { type: 'string', description: 'beliefs | calibration | diagnosis | memory (optional)' },
8
+ },
9
+ },
10
+ async execute(args, ctx) {
11
+ const focus = String(args.focus ?? 'summary');
12
+ try {
13
+ const { analyzeWorldModel, diagnoseOpportunities, CognitiveMemory } = await import('@hmharness/cognitive');
14
+ const lines = [];
15
+ if (focus === 'summary' || focus === 'beliefs') {
16
+ const wm = await analyzeWorldModel(ctx.home);
17
+ lines.push(`world model (${wm.trajectoriesReplayed} trajectories, ${wm.stepsReplayed} steps replayed):`);
18
+ if (wm.beliefs.length === 0)
19
+ lines.push(' (no beliefs yet — run a few tasks first)');
20
+ for (const b of wm.beliefs.slice(0, 12)) {
21
+ lines.push(` ${b.actionType.padEnd(24)} conf=${b.confidence.toFixed(2)} n=${b.evidenceCount}`);
22
+ }
23
+ if (focus === 'beliefs') {
24
+ lines.push(`planner gate: trusted=[${wm.plannerGate.trusted.join(',')}] untrusted=[${wm.plannerGate.untrusted.join(',')}] unknown=[${wm.plannerGate.unknown.join(',')}]`);
25
+ }
26
+ }
27
+ if (focus === 'summary' || focus === 'calibration') {
28
+ const wm = await analyzeWorldModel(ctx.home);
29
+ const cal = wm.calibration;
30
+ lines.push(`calibration: ${cal.resolved} resolved predictions${cal.meanError !== undefined ? `, mean |error|=${cal.meanError}` : ' (no predictions recorded yet — steps carry no confidence)'}`);
31
+ }
32
+ if (focus === 'summary' || focus === 'diagnosis') {
33
+ const d = await diagnoseOpportunities(ctx.home);
34
+ lines.push(`diagnosis (${d.trajectories} trajectories):`);
35
+ if (d.opportunities.length === 0)
36
+ lines.push(' (no learning opportunity meets the evidence threshold yet)');
37
+ for (const o of d.opportunities.slice(0, 6)) {
38
+ lines.push(` [${o.suggestedTargets.join('/')}] ${o.signal}`);
39
+ }
40
+ }
41
+ if (focus === 'summary' || focus === 'memory') {
42
+ const mem = new CognitiveMemory(ctx.home);
43
+ await mem.load();
44
+ const stats = mem.stats();
45
+ lines.push(`memory: working:${stats.working} episodic:${stats.episodic} semantic:${stats.semantic} procedural:${stats.procedural} world:${stats.world}, contradictions pending: ${mem.detectContradictions().length}`);
46
+ }
47
+ return { output: lines.join('\n') };
48
+ }
49
+ catch (err) {
50
+ return { output: 'cognitive_query failed: ' + String(err).slice(0, 200), isError: true };
51
+ }
52
+ },
53
+ };
package/dist/prompt.d.ts CHANGED
@@ -4,6 +4,9 @@ export declare function buildSystemPrompt(opts: {
4
4
  memory: string;
5
5
  skills: string;
6
6
  insights: string;
7
+ /** world-model digest (trusted/flaky tools from run history; empty until
8
+ * enough evidence exists — blueprint M3 planner consumption) */
9
+ cognitive?: string;
7
10
  model: string;
8
11
  locale?: string;
9
12
  agentsMd?: string;
package/dist/prompt.js CHANGED
@@ -44,6 +44,12 @@ export function buildSystemPrompt(opts) {
44
44
  if (opts.insights.trim()) {
45
45
  parts.push('', '## Recent session outcomes (what worked / what failed)', opts.insights.trim());
46
46
  }
47
+ // ---- Cognitive OS: world-model digest (blueprint M3) ----
48
+ // Statistical tool reliability from run history. Treat as evidence, not
49
+ // commands: a flaky tool deserves extra verification, not avoidance.
50
+ if (opts.cognitive?.trim()) {
51
+ parts.push('', '## Tool reliability (from run history)', opts.cognitive.trim());
52
+ }
47
53
  // ---- Identity anchor (LAST — recency wins over 15K chars of instructions above;
48
54
  // flash-class models have strong built-in identities that override a single
49
55
  // "You are hmh" at the top. Repeating + anchoring at the end fixes it.) ----
package/dist/runner.d.ts CHANGED
@@ -41,6 +41,7 @@ export declare function contextPack(task: string, sessionId?: string, opts?: {
41
41
  memory: string;
42
42
  skills: string;
43
43
  insights: string;
44
+ cognitive: string;
44
45
  skillsInjected: string[];
45
46
  }>;
46
47
  /**
package/dist/runner.js CHANGED
@@ -126,9 +126,9 @@ export async function contextPack(task, sessionId, opts = {}) {
126
126
  // injection entirely — the model doesn't need them for "你好" and they add
127
127
  // ~4K tokens of noise that dilutes the identity anchor
128
128
  if (isTrivialTask(task)) {
129
- return { memory: '', skills: '', insights: '', skillsInjected: [] };
129
+ return { memory: '', skills: '', insights: '', cognitive: '', skillsInjected: [] };
130
130
  }
131
- const [memory, skills, insights] = await Promise.all([
131
+ const [memory, skills, insights, cognitive] = await Promise.all([
132
132
  retrieveMemory(home, task, { workspace: opts.workspace ?? undefined, embedding: opts.embedding }),
133
133
  listSkills(home),
134
134
  // 2026-09-27 plan A: experience retrieval - the K most RELEVANT past
@@ -138,6 +138,10 @@ export async function contextPack(task, sessionId, opts = {}) {
138
138
  // Plan C: cross-project lessons stay retrievable but carry their
139
139
  // origin stamp ([来自项目:X]) so the model can weigh them.
140
140
  retrieveInsights(home, task, { workspace: opts.workspace ?? undefined }),
141
+ // blueprint M3: the world model feeds the planner — which tools history
142
+ // trusts/distrusts lands in the system prompt (empty until ≥3 steps of
143
+ // evidence exist, so cold starts see nothing)
144
+ import('@hmharness/cognitive').then((m) => m.buildContextDigest(home)).catch(() => ''),
141
145
  ]);
142
146
  let canaryBlock = '';
143
147
  let canaryNames = [];
@@ -148,7 +152,7 @@ export async function contextPack(task, sessionId, opts = {}) {
148
152
  canaryBlock = canaryWatermark(canaryNames) + '\n' + skillsToPrompt(canary);
149
153
  }
150
154
  }
151
- return { memory, skills: skillsToPrompt(skills) + (canaryBlock ? '\n' + canaryBlock : ''), insights, skillsInjected: [...skills.map((s) => s.name), ...canaryNames] };
155
+ return { memory, skills: skillsToPrompt(skills) + (canaryBlock ? '\n' + canaryBlock : ''), insights, cognitive, skillsInjected: [...skills.map((s) => s.name), ...canaryNames] };
152
156
  }
153
157
  export function loadApprovedRules(home) {
154
158
  try {
@@ -302,6 +306,7 @@ export async function runAgentTask(opts) {
302
306
  memory: pack.memory,
303
307
  skills: pack.skills,
304
308
  insights: pack.insights,
309
+ ...(pack.cognitive ? { cognitive: pack.cognitive } : {}),
305
310
  model: cfg.provider.model,
306
311
  locale: cfg.locale,
307
312
  agentsMd: agentsMd ?? undefined,
@@ -319,6 +324,7 @@ export async function runAgentTask(opts) {
319
324
  memoryChars: pack.memory.length,
320
325
  skills: pack.skills.length,
321
326
  insights: pack.insights.length,
327
+ cognitiveChars: pack.cognitive.length,
322
328
  });
323
329
  await session.user(opts.task);
324
330
  // YOLO fix: when yes=true the caller's approvalAsk (TUI dialog, web remote
package/dist/tools.js CHANGED
@@ -9,6 +9,7 @@ import { copyFile, readFile, readdir, writeFile } from 'node:fs/promises';
9
9
  import { isAbsolute, join, resolve } from 'node:path';
10
10
  import { promisify } from 'node:util';
11
11
  import { chatVision, homeDir, isBareProbe, isVisionRefusal, loadConfig, visionProviderChain } from '@hmharness/kernel';
12
+ import { cognitiveQueryTool } from "./cognitive-tools.js";
12
13
  const execCb = promisify(exec);
13
14
  const DENY_PATTERNS = [
14
15
  // recursive deletes aimed at ROOT/HOME/SYSTEM targets only - relative
@@ -662,4 +663,5 @@ export const seeImageTool = {
662
663
  export const baseTools = [
663
664
  readFileTool, editFileTool, writeFileTool, listDirTool, runCommandTool, rememberTool, seeImageTool,
664
665
  webSearchTool, webFetchTool, browserOpenTool, desktopScreenshotTool, desktopClickTool, desktopTypeTool, sshRunTool,
666
+ cognitiveQueryTool,
665
667
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hmharness/agent",
3
- "version": "0.19.1",
3
+ "version": "0.19.3",
4
4
  "description": "hmharness agent execution layer: base tools, system prompt, sub-agent spawn, and the shared task runner that frontends (cli, web) drive.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,13 +15,13 @@
15
15
  "build": "tsc -p tsconfig.build.json"
16
16
  },
17
17
  "dependencies": {
18
- "@hmharness/cognitive": "0.19.1",
19
- "@hmharness/domain-harmony": "0.19.1",
20
- "@hmharness/domain-ops": "0.19.1",
21
- "@hmharness/evolution": "0.19.1",
22
- "@hmharness/kernel": "0.19.1",
23
- "@hmharness/observability": "0.19.1",
24
- "@hmharness/sandbox": "0.19.1"
18
+ "@hmharness/cognitive": "0.19.3",
19
+ "@hmharness/domain-harmony": "0.19.3",
20
+ "@hmharness/domain-ops": "0.19.3",
21
+ "@hmharness/evolution": "0.19.3",
22
+ "@hmharness/kernel": "0.19.3",
23
+ "@hmharness/observability": "0.19.3",
24
+ "@hmharness/sandbox": "0.19.3"
25
25
  },
26
26
  "files": [
27
27
  "dist"