hivemind-context-governance 1.3.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 +95 -0
- package/LICENSE +21 -0
- package/README.md +218 -0
- package/dist/cli/init.d.ts +23 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +175 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +162 -0
- package/dist/cli.js.map +1 -0
- package/dist/dashboard/i18n/en.d.ts +43 -0
- package/dist/dashboard/i18n/en.d.ts.map +1 -0
- package/dist/dashboard/i18n/en.js +43 -0
- package/dist/dashboard/i18n/en.js.map +1 -0
- package/dist/dashboard/i18n/index.d.ts +10 -0
- package/dist/dashboard/i18n/index.d.ts.map +1 -0
- package/dist/dashboard/i18n/index.js +14 -0
- package/dist/dashboard/i18n/index.js.map +1 -0
- package/dist/dashboard/i18n/vi.d.ts +43 -0
- package/dist/dashboard/i18n/vi.d.ts.map +1 -0
- package/dist/dashboard/i18n/vi.js +43 -0
- package/dist/dashboard/i18n/vi.js.map +1 -0
- package/dist/dashboard/server.d.ts +23 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +282 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/hooks/compaction.d.ts +21 -0
- package/dist/hooks/compaction.d.ts.map +1 -0
- package/dist/hooks/compaction.js +79 -0
- package/dist/hooks/compaction.js.map +1 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/session-lifecycle.d.ts +28 -0
- package/dist/hooks/session-lifecycle.d.ts.map +1 -0
- package/dist/hooks/session-lifecycle.js +94 -0
- package/dist/hooks/session-lifecycle.js.map +1 -0
- package/dist/hooks/tool-gate.d.ts +28 -0
- package/dist/hooks/tool-gate.d.ts.map +1 -0
- package/dist/hooks/tool-gate.js +152 -0
- package/dist/hooks/tool-gate.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +159 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/complexity.d.ts +41 -0
- package/dist/lib/complexity.d.ts.map +1 -0
- package/dist/lib/complexity.js +67 -0
- package/dist/lib/complexity.js.map +1 -0
- package/dist/lib/context-refresh.d.ts +46 -0
- package/dist/lib/context-refresh.d.ts.map +1 -0
- package/dist/lib/context-refresh.js +77 -0
- package/dist/lib/context-refresh.js.map +1 -0
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +10 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/logging.d.ts +13 -0
- package/dist/lib/logging.d.ts.map +1 -0
- package/dist/lib/logging.js +40 -0
- package/dist/lib/logging.js.map +1 -0
- package/dist/lib/persistence.d.ts +15 -0
- package/dist/lib/persistence.d.ts.map +1 -0
- package/dist/lib/persistence.js +62 -0
- package/dist/lib/persistence.js.map +1 -0
- package/dist/lib/planning-fs.d.ts +34 -0
- package/dist/lib/planning-fs.d.ts.map +1 -0
- package/dist/lib/planning-fs.js +134 -0
- package/dist/lib/planning-fs.js.map +1 -0
- package/dist/lib/sentiment.d.ts +31 -0
- package/dist/lib/sentiment.d.ts.map +1 -0
- package/dist/lib/sentiment.js +158 -0
- package/dist/lib/sentiment.js.map +1 -0
- package/dist/schemas/brain-state.d.ts +60 -0
- package/dist/schemas/brain-state.d.ts.map +1 -0
- package/dist/schemas/brain-state.js +176 -0
- package/dist/schemas/brain-state.js.map +1 -0
- package/dist/schemas/config.d.ts +51 -0
- package/dist/schemas/config.d.ts.map +1 -0
- package/dist/schemas/config.js +128 -0
- package/dist/schemas/config.js.map +1 -0
- package/dist/schemas/hierarchy.d.ts +22 -0
- package/dist/schemas/hierarchy.d.ts.map +1 -0
- package/dist/schemas/hierarchy.js +27 -0
- package/dist/schemas/hierarchy.js.map +1 -0
- package/dist/schemas/index.d.ts +7 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +7 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/tools/compact-session.d.ts +15 -0
- package/dist/tools/compact-session.d.ts.map +1 -0
- package/dist/tools/compact-session.js +76 -0
- package/dist/tools/compact-session.js.map +1 -0
- package/dist/tools/declare-intent.d.ts +15 -0
- package/dist/tools/declare-intent.d.ts.map +1 -0
- package/dist/tools/declare-intent.js +83 -0
- package/dist/tools/declare-intent.js.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +14 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/map-context.d.ts +15 -0
- package/dist/tools/map-context.d.ts.map +1 -0
- package/dist/tools/map-context.js +85 -0
- package/dist/tools/map-context.js.map +1 -0
- package/dist/tools/self-rate.d.ts +15 -0
- package/dist/tools/self-rate.d.ts.map +1 -0
- package/dist/tools/self-rate.js +76 -0
- package/dist/tools/self-rate.js.map +1 -0
- package/package.json +71 -0
- package/src/cli/init.ts +214 -0
- package/src/cli.ts +178 -0
- package/src/dashboard/i18n/en.ts +43 -0
- package/src/dashboard/i18n/index.ts +20 -0
- package/src/dashboard/i18n/vi.ts +43 -0
- package/src/dashboard/server.ts +372 -0
- package/src/hooks/compaction.ts +104 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/session-lifecycle.ts +133 -0
- package/src/hooks/tool-gate.ts +205 -0
- package/src/index.ts +206 -0
- package/src/lib/complexity.ts +96 -0
- package/src/lib/context-refresh.ts +107 -0
- package/src/lib/index.ts +10 -0
- package/src/lib/logging.ts +53 -0
- package/src/lib/persistence.ts +83 -0
- package/src/lib/planning-fs.ts +187 -0
- package/src/lib/sentiment.ts +183 -0
- package/src/schemas/brain-state.ts +257 -0
- package/src/schemas/config.ts +184 -0
- package/src/schemas/hierarchy.ts +58 -0
- package/src/schemas/index.ts +7 -0
- package/src/tools/compact-session.ts +97 -0
- package/src/tools/declare-intent.ts +104 -0
- package/src/tools/index.ts +14 -0
- package/src/tools/map-context.ts +105 -0
- package/src/tools/self-rate.ts +86 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* declare_intent — Unlock session by declaring work mode and focus.
|
|
3
|
+
*
|
|
4
|
+
* Agent Thought: "I want to start working on something"
|
|
5
|
+
*
|
|
6
|
+
* Design: Agent-Native lifecycle verb.
|
|
7
|
+
* 1. Iceberg — 2 args, system handles state machine + file writes
|
|
8
|
+
* 2. Context Inference — session ID from context, governance mode from config
|
|
9
|
+
* 3. Signal-to-Noise — 1-line output
|
|
10
|
+
* 4. No-Shadowing — description matches agent intent
|
|
11
|
+
* 5. Native Parallelism — idempotent, safe to call repeatedly
|
|
12
|
+
*/
|
|
13
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
14
|
+
import { createStateManager, loadConfig } from "../lib/persistence.js";
|
|
15
|
+
import { createBrainState, generateSessionId, unlockSession, resetComplexityNudge, } from "../schemas/brain-state.js";
|
|
16
|
+
import { writeActiveMd, readActiveMd, initializePlanningDirectory, } from "../lib/planning-fs.js";
|
|
17
|
+
const VALID_MODES = ["plan_driven", "quick_fix", "exploration"];
|
|
18
|
+
export function createDeclareIntentTool(directory) {
|
|
19
|
+
return tool({
|
|
20
|
+
description: "Unlock the session by declaring your work mode and focus. " +
|
|
21
|
+
"Call this before doing any work to set your intent.",
|
|
22
|
+
args: {
|
|
23
|
+
mode: tool.schema
|
|
24
|
+
.enum(VALID_MODES)
|
|
25
|
+
.describe("How are you approaching this work? plan_driven | quick_fix | exploration"),
|
|
26
|
+
focus: tool.schema
|
|
27
|
+
.string()
|
|
28
|
+
.describe("What are you working on? (1 sentence)"),
|
|
29
|
+
reason: tool.schema
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Why this mode? (optional context)"),
|
|
33
|
+
},
|
|
34
|
+
async execute(args) {
|
|
35
|
+
const config = await loadConfig(directory);
|
|
36
|
+
const stateManager = createStateManager(directory);
|
|
37
|
+
// Ensure planning directory exists
|
|
38
|
+
await initializePlanningDirectory(directory);
|
|
39
|
+
// Load or create brain state
|
|
40
|
+
let state = await stateManager.load();
|
|
41
|
+
if (!state) {
|
|
42
|
+
const sessionId = generateSessionId();
|
|
43
|
+
state = createBrainState(sessionId, config, args.mode);
|
|
44
|
+
}
|
|
45
|
+
// Unlock session
|
|
46
|
+
state = unlockSession(state);
|
|
47
|
+
state.session.mode = args.mode;
|
|
48
|
+
state.hierarchy.trajectory = args.focus;
|
|
49
|
+
// Reset complexity nudge on new intent declaration
|
|
50
|
+
state = resetComplexityNudge(state);
|
|
51
|
+
// Save state
|
|
52
|
+
await stateManager.save(state);
|
|
53
|
+
// Update active.md with session info
|
|
54
|
+
const activeMd = await readActiveMd(directory);
|
|
55
|
+
activeMd.frontmatter = {
|
|
56
|
+
session_id: state.session.id,
|
|
57
|
+
mode: args.mode,
|
|
58
|
+
governance_status: "OPEN",
|
|
59
|
+
start_time: state.session.start_time,
|
|
60
|
+
last_updated: Date.now(),
|
|
61
|
+
};
|
|
62
|
+
activeMd.body = [
|
|
63
|
+
"# Active Session",
|
|
64
|
+
"",
|
|
65
|
+
"## Current Focus",
|
|
66
|
+
`**Mode**: ${args.mode}`,
|
|
67
|
+
`**Focus**: ${args.focus}`,
|
|
68
|
+
args.reason ? `**Reason**: ${args.reason}` : "",
|
|
69
|
+
"",
|
|
70
|
+
"## Completed",
|
|
71
|
+
"<!-- Items marked [x] get archived -->",
|
|
72
|
+
"",
|
|
73
|
+
"## Notes",
|
|
74
|
+
"<!-- Scratchpad - anything goes -->",
|
|
75
|
+
]
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.join("\n");
|
|
78
|
+
await writeActiveMd(directory, activeMd);
|
|
79
|
+
return `Session: "${args.focus}". Mode: ${args.mode}. Status: OPEN.`;
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=declare-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declare-intent.js","sourceRoot":"","sources":["../../src/tools/declare-intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool barrel exports — HiveMind lifecycle verbs
|
|
3
|
+
*
|
|
4
|
+
* 4 tools total:
|
|
5
|
+
* declare_intent — unlock session, set mode/focus
|
|
6
|
+
* map_context — update hierarchy level
|
|
7
|
+
* compact_session — archive + reset
|
|
8
|
+
* self_rate — agent self-assessment
|
|
9
|
+
*/
|
|
10
|
+
export { createDeclareIntentTool } from "./declare-intent.js";
|
|
11
|
+
export { createMapContextTool } from "./map-context.js";
|
|
12
|
+
export { createCompactSessionTool } from "./compact-session.js";
|
|
13
|
+
export { createSelfRateTool } from "./self-rate.js";
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool barrel exports — HiveMind lifecycle verbs
|
|
3
|
+
*
|
|
4
|
+
* 4 tools total:
|
|
5
|
+
* declare_intent — unlock session, set mode/focus
|
|
6
|
+
* map_context — update hierarchy level
|
|
7
|
+
* compact_session — archive + reset
|
|
8
|
+
* self_rate — agent self-assessment
|
|
9
|
+
*/
|
|
10
|
+
export { createDeclareIntentTool } from "./declare-intent.js";
|
|
11
|
+
export { createMapContextTool } from "./map-context.js";
|
|
12
|
+
export { createCompactSessionTool } from "./compact-session.js";
|
|
13
|
+
export { createSelfRateTool } from "./self-rate.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* map_context — Update focus in the 3-level hierarchy.
|
|
3
|
+
*
|
|
4
|
+
* Agent Thought: "I need to update what I'm focused on"
|
|
5
|
+
*
|
|
6
|
+
* Design: Agent-Native lifecycle verb.
|
|
7
|
+
* 1. Iceberg — 2 args, system handles hierarchy state + file sync
|
|
8
|
+
* 2. Context Inference — reads current hierarchy from brain state
|
|
9
|
+
* 3. Signal-to-Noise — 1-line output with visual beacon
|
|
10
|
+
* 4. No-Shadowing — description matches agent intent
|
|
11
|
+
* 5. Native Parallelism — can update different levels independently
|
|
12
|
+
*/
|
|
13
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
14
|
+
export declare function createMapContextTool(directory: string): ToolDefinition;
|
|
15
|
+
//# sourceMappingURL=map-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-context.d.ts","sourceRoot":"","sources":["../../src/tools/map-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAgBpE,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CA2EtE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* map_context — Update focus in the 3-level hierarchy.
|
|
3
|
+
*
|
|
4
|
+
* Agent Thought: "I need to update what I'm focused on"
|
|
5
|
+
*
|
|
6
|
+
* Design: Agent-Native lifecycle verb.
|
|
7
|
+
* 1. Iceberg — 2 args, system handles hierarchy state + file sync
|
|
8
|
+
* 2. Context Inference — reads current hierarchy from brain state
|
|
9
|
+
* 3. Signal-to-Noise — 1-line output with visual beacon
|
|
10
|
+
* 4. No-Shadowing — description matches agent intent
|
|
11
|
+
* 5. Native Parallelism — can update different levels independently
|
|
12
|
+
*/
|
|
13
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
14
|
+
import { createStateManager } from "../lib/persistence.js";
|
|
15
|
+
import { resetTurnCount, updateHierarchy, } from "../schemas/brain-state.js";
|
|
16
|
+
import { readActiveMd, writeActiveMd, updateIndexMd, } from "../lib/planning-fs.js";
|
|
17
|
+
const VALID_LEVELS = ["trajectory", "tactic", "action"];
|
|
18
|
+
const VALID_STATUSES = ["pending", "active", "complete", "blocked"];
|
|
19
|
+
export function createMapContextTool(directory) {
|
|
20
|
+
return tool({
|
|
21
|
+
description: "Update your current focus in the 3-level hierarchy. " +
|
|
22
|
+
"Call this when changing what you're working on.",
|
|
23
|
+
args: {
|
|
24
|
+
level: tool.schema
|
|
25
|
+
.enum(VALID_LEVELS)
|
|
26
|
+
.describe("Which level to update: trajectory | tactic | action"),
|
|
27
|
+
content: tool.schema
|
|
28
|
+
.string()
|
|
29
|
+
.describe("The new focus (1-2 sentences)"),
|
|
30
|
+
status: tool.schema
|
|
31
|
+
.enum(VALID_STATUSES)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Status of this context item (default: active)"),
|
|
34
|
+
},
|
|
35
|
+
async execute(args) {
|
|
36
|
+
const stateManager = createStateManager(directory);
|
|
37
|
+
const status = args.status ?? "active";
|
|
38
|
+
// Load brain state
|
|
39
|
+
let state = await stateManager.load();
|
|
40
|
+
if (!state) {
|
|
41
|
+
return "ERROR: No active session. Call declare_intent first.";
|
|
42
|
+
}
|
|
43
|
+
// Update hierarchy
|
|
44
|
+
state = updateHierarchy(state, { [args.level]: args.content });
|
|
45
|
+
// Reset turn count on context update (re-engagement signal)
|
|
46
|
+
state = resetTurnCount(state);
|
|
47
|
+
// Save state
|
|
48
|
+
await stateManager.save(state);
|
|
49
|
+
// Sync to planning files
|
|
50
|
+
if (args.level === "trajectory") {
|
|
51
|
+
// Update index.md for trajectory-level changes
|
|
52
|
+
await updateIndexMd(directory, `[${status.toUpperCase()}] ${args.content}`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Update active.md for tactic/action level changes
|
|
56
|
+
const activeMd = await readActiveMd(directory);
|
|
57
|
+
const levelLabel = args.level === "tactic" ? "Tactic" : "Action";
|
|
58
|
+
const focusLine = `**${levelLabel}**: ${args.content} [${status.toUpperCase()}]`;
|
|
59
|
+
// Append to current focus section
|
|
60
|
+
if (activeMd.body.includes("## Current Focus")) {
|
|
61
|
+
const parts = activeMd.body.split("## Current Focus");
|
|
62
|
+
const afterFocus = parts[1] || "";
|
|
63
|
+
const nextSection = afterFocus.indexOf("\n## ");
|
|
64
|
+
const focusContent = nextSection > -1 ? afterFocus.substring(0, nextSection) : afterFocus;
|
|
65
|
+
const rest = nextSection > -1 ? afterFocus.substring(nextSection) : "";
|
|
66
|
+
activeMd.body =
|
|
67
|
+
parts[0] +
|
|
68
|
+
"## Current Focus" +
|
|
69
|
+
focusContent.trimEnd() +
|
|
70
|
+
"\n" +
|
|
71
|
+
focusLine +
|
|
72
|
+
"\n" +
|
|
73
|
+
rest;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
activeMd.body += `\n## Current Focus\n${focusLine}\n`;
|
|
77
|
+
}
|
|
78
|
+
activeMd.frontmatter.last_updated = Date.now();
|
|
79
|
+
await writeActiveMd(directory, activeMd);
|
|
80
|
+
}
|
|
81
|
+
return `[${args.level}] "${args.content}" → ${status}`;
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=map-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-context.js","sourceRoot":"","sources":["../../src/tools/map-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* self_rate — Agent self-assessment tool for drift detection.
|
|
3
|
+
*
|
|
4
|
+
* Agent Thought: "How well am I doing? Let me rate my performance."
|
|
5
|
+
*
|
|
6
|
+
* Design: Agent-Native lifecycle verb.
|
|
7
|
+
* 1. Iceberg — 1-3 args, system handles storage
|
|
8
|
+
* 2. Context Inference — turn number from state
|
|
9
|
+
* 3. Signal-to-Noise — 1-line output
|
|
10
|
+
* 4. No-Shadowing — description matches agent intent
|
|
11
|
+
* 5. Native Parallelism — safe to call multiple times
|
|
12
|
+
*/
|
|
13
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
14
|
+
export declare function createSelfRateTool(directory: string): ToolDefinition;
|
|
15
|
+
//# sourceMappingURL=self-rate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-rate.d.ts","sourceRoot":"","sources":["../../src/tools/self-rate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAMpE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAkEpE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* self_rate — Agent self-assessment tool for drift detection.
|
|
3
|
+
*
|
|
4
|
+
* Agent Thought: "How well am I doing? Let me rate my performance."
|
|
5
|
+
*
|
|
6
|
+
* Design: Agent-Native lifecycle verb.
|
|
7
|
+
* 1. Iceberg — 1-3 args, system handles storage
|
|
8
|
+
* 2. Context Inference — turn number from state
|
|
9
|
+
* 3. Signal-to-Noise — 1-line output
|
|
10
|
+
* 4. No-Shadowing — description matches agent intent
|
|
11
|
+
* 5. Native Parallelism — safe to call multiple times
|
|
12
|
+
*/
|
|
13
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
14
|
+
import { createStateManager } from "../lib/persistence.js";
|
|
15
|
+
import { addSelfRating } from "../schemas/brain-state.js";
|
|
16
|
+
import { createLogger } from "../lib/logging.js";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
export function createSelfRateTool(directory) {
|
|
19
|
+
return tool({
|
|
20
|
+
description: "Rate your own performance on the current task. " +
|
|
21
|
+
"Call this periodically to help detect drift and track progress.",
|
|
22
|
+
args: {
|
|
23
|
+
score: tool.schema
|
|
24
|
+
.number()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(10)
|
|
27
|
+
.describe("Your self-assessment score from 1-10 (10 = excellent)"),
|
|
28
|
+
reason: tool.schema
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Why you gave this score (optional)"),
|
|
32
|
+
turn_context: tool.schema
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("What you're working on right now (optional)"),
|
|
36
|
+
},
|
|
37
|
+
async execute(args) {
|
|
38
|
+
const stateManager = createStateManager(directory);
|
|
39
|
+
const log = await createLogger(join(directory, ".opencode", "planning", "logs"), "self-rate");
|
|
40
|
+
// Load current state
|
|
41
|
+
let state = await stateManager.load();
|
|
42
|
+
if (!state) {
|
|
43
|
+
return "ERROR: No active session. Call declare_intent first.";
|
|
44
|
+
}
|
|
45
|
+
// Add the rating
|
|
46
|
+
state = addSelfRating(state, {
|
|
47
|
+
score: args.score,
|
|
48
|
+
reason: args.reason,
|
|
49
|
+
turn_context: args.turn_context,
|
|
50
|
+
});
|
|
51
|
+
// Save state
|
|
52
|
+
await stateManager.save(state);
|
|
53
|
+
// Log to TUI
|
|
54
|
+
const turnNumber = state.metrics.turn_count;
|
|
55
|
+
const logMessage = `[SelfRate] Turn ${turnNumber}: ${args.score}/10`;
|
|
56
|
+
await log.info(logMessage);
|
|
57
|
+
// Build response
|
|
58
|
+
let response = `Rating recorded: ${args.score}/10 at turn ${turnNumber}`;
|
|
59
|
+
if (args.reason) {
|
|
60
|
+
response += ` — "${args.reason}"`;
|
|
61
|
+
}
|
|
62
|
+
// Provide feedback based on score
|
|
63
|
+
if (args.score <= 3) {
|
|
64
|
+
response += "\n⚠️ Low score detected. Consider using compact_session to reset context.";
|
|
65
|
+
}
|
|
66
|
+
else if (args.score <= 7) {
|
|
67
|
+
response += "\n💡 Score suggests some drift. Consider map_context to refocus.";
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
response += "\n✅ Good progress!";
|
|
71
|
+
}
|
|
72
|
+
return response;
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=self-rate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-rate.js","sourceRoot":"","sources":["../../src/tools/self-rate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAuB,MAAM,0BAA0B,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,OAAO,IAAI,CAAC;QACV,WAAW,EACT,iDAAiD;YACjD,iEAAiE;QACnE,IAAI,EAAE;YACJ,KAAK,EAAE,IAAI,CAAC,MAAM;iBACf,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,EAAE,CAAC;iBACP,QAAQ,CAAC,uDAAuD,CAAC;YACpE,MAAM,EAAE,IAAI,CAAC,MAAM;iBAChB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,oCAAoC,CAAC;YACjD,YAAY,EAAE,IAAI,CAAC,MAAM;iBACtB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,6CAA6C,CAAC;SAC3D;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,MAAM,YAAY,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;YAClD,MAAM,GAAG,GAAG,MAAM,YAAY,CAC5B,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,EAChD,WAAW,CACZ,CAAA;YAED,qBAAqB;YACrB,IAAI,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAA;YACrC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,sDAAsD,CAAA;YAC/D,CAAC;YAED,iBAAiB;YACjB,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE;gBAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,YAAY,EAAE,IAAI,CAAC,YAAY;aAChC,CAAC,CAAA;YAEF,aAAa;YACb,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAE9B,aAAa;YACb,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAA;YAC3C,MAAM,UAAU,GAAG,mBAAmB,UAAU,KAAK,IAAI,CAAC,KAAK,KAAK,CAAA;YACpE,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YAE1B,iBAAiB;YACjB,IAAI,QAAQ,GAAG,oBAAoB,IAAI,CAAC,KAAK,eAAe,UAAU,EAAE,CAAA;YACxE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,QAAQ,IAAI,OAAO,IAAI,CAAC,MAAM,GAAG,CAAA;YACnC,CAAC;YAED,kCAAkC;YAClC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;gBACpB,QAAQ,IAAI,2EAA2E,CAAA;YACzF,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;gBAC3B,QAAQ,IAAI,kEAAkE,CAAA;YAChF,CAAC;iBAAM,CAAC;gBACN,QAAQ,IAAI,oBAAoB,CAAA;YAClC,CAAC;YAED,OAAO,QAAQ,CAAA;QACjB,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hivemind-context-governance",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Context-Aware Governance Layer for OpenCode - prevents drift and manages session state across lifecycles",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"hivemind-context-governance": "dist/cli.js",
|
|
10
|
+
"hivemind": "dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"CHANGELOG.md"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/shynlee04/hivemind-plugin.git"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/shynlee04/hivemind-plugin/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/shynlee04/hivemind-plugin#readme",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"clean": "rm -rf dist",
|
|
29
|
+
"build": "npm run clean && tsc",
|
|
30
|
+
"dev": "tsc --watch",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"test": "tsx --test tests/**/*.test.ts",
|
|
33
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"opencode",
|
|
37
|
+
"opencode-plugin",
|
|
38
|
+
"plugin",
|
|
39
|
+
"governance",
|
|
40
|
+
"context-management",
|
|
41
|
+
"agent-lifecycle",
|
|
42
|
+
"hivemind"
|
|
43
|
+
],
|
|
44
|
+
"author": "HiveMind Contributors",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"yaml": "^2.3.4",
|
|
54
|
+
"zod": "^3.22.4"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@opencode-ai/plugin": "^1.1.53",
|
|
58
|
+
"@types/bun": "^1.2.0",
|
|
59
|
+
"@types/node": "^20.10.0",
|
|
60
|
+
"tsx": "^4.7.0",
|
|
61
|
+
"typescript": "^5.3.0"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@opencode-ai/plugin": "*"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"@opencode-ai/plugin": {
|
|
68
|
+
"optional": false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/cli/init.ts
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HiveMind Init — One-command project initialization.
|
|
3
|
+
*
|
|
4
|
+
* Creates:
|
|
5
|
+
* - .opencode/planning/ directory structure
|
|
6
|
+
* - index.md with template
|
|
7
|
+
* - active.md with LOCKED status
|
|
8
|
+
* - brain.json with initial state
|
|
9
|
+
* - config.json with governance preferences
|
|
10
|
+
* - Auto-registers plugin in opencode.json
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs"
|
|
14
|
+
import { join } from "node:path"
|
|
15
|
+
import type { GovernanceMode, Language, ExpertLevel, OutputStyle } from "../schemas/config.js"
|
|
16
|
+
import { createConfig, isValidGovernanceMode, isValidLanguage, isValidExpertLevel, isValidOutputStyle } from "../schemas/config.js"
|
|
17
|
+
import { createBrainState, generateSessionId } from "../schemas/brain-state.js"
|
|
18
|
+
import { createStateManager, saveConfig } from "../lib/persistence.js"
|
|
19
|
+
import { initializePlanningDirectory } from "../lib/planning-fs.js"
|
|
20
|
+
|
|
21
|
+
export interface InitOptions {
|
|
22
|
+
language?: Language
|
|
23
|
+
governanceMode?: GovernanceMode
|
|
24
|
+
expertLevel?: ExpertLevel
|
|
25
|
+
outputStyle?: OutputStyle
|
|
26
|
+
requireCodeReview?: boolean
|
|
27
|
+
enforceTdd?: boolean
|
|
28
|
+
silent?: boolean
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line no-console
|
|
32
|
+
const log = (msg: string) => console.log(msg)
|
|
33
|
+
|
|
34
|
+
const PLUGIN_NAME = "hivemind-context-governance"
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Auto-register the HiveMind plugin in opencode.json.
|
|
38
|
+
* Creates the file if it doesn't exist.
|
|
39
|
+
* Adds the plugin if not already registered.
|
|
40
|
+
*/
|
|
41
|
+
function registerPluginInConfig(directory: string, silent: boolean): void {
|
|
42
|
+
const configPath = join(directory, "opencode.json")
|
|
43
|
+
|
|
44
|
+
let config: Record<string, unknown> = {}
|
|
45
|
+
|
|
46
|
+
if (existsSync(configPath)) {
|
|
47
|
+
try {
|
|
48
|
+
const raw = readFileSync(configPath, "utf-8")
|
|
49
|
+
config = JSON.parse(raw)
|
|
50
|
+
} catch {
|
|
51
|
+
// Malformed JSON — overwrite
|
|
52
|
+
config = {}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Ensure plugin array exists
|
|
57
|
+
if (!Array.isArray(config.plugin)) {
|
|
58
|
+
config.plugin = []
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const plugins = config.plugin as string[]
|
|
62
|
+
|
|
63
|
+
// Check if already registered (exact match or versioned match)
|
|
64
|
+
const alreadyRegistered = plugins.some(
|
|
65
|
+
(p) => p === PLUGIN_NAME || p.startsWith(PLUGIN_NAME + "@")
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if (alreadyRegistered) {
|
|
69
|
+
if (!silent) {
|
|
70
|
+
log(` ✓ Plugin already registered in opencode.json`)
|
|
71
|
+
}
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
plugins.push(PLUGIN_NAME)
|
|
76
|
+
config.plugin = plugins
|
|
77
|
+
|
|
78
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8")
|
|
79
|
+
|
|
80
|
+
if (!silent) {
|
|
81
|
+
log(` ✓ Plugin registered in opencode.json`)
|
|
82
|
+
log(` → OpenCode will auto-install on next launch`)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function initProject(
|
|
87
|
+
directory: string,
|
|
88
|
+
options: InitOptions = {}
|
|
89
|
+
): Promise<void> {
|
|
90
|
+
const planningDir = join(directory, ".opencode", "planning")
|
|
91
|
+
const brainPath = join(planningDir, "brain.json")
|
|
92
|
+
|
|
93
|
+
// Guard: Check brain.json existence, not just directory.
|
|
94
|
+
// The directory may exist from logger side-effects without full initialization.
|
|
95
|
+
if (existsSync(brainPath)) {
|
|
96
|
+
if (!options.silent) {
|
|
97
|
+
log("⚠ HiveMind already initialized in this project.")
|
|
98
|
+
log(` Directory: ${planningDir}`)
|
|
99
|
+
log(" Use 'npx hivemind-context-governance status' to see current state.")
|
|
100
|
+
}
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!options.silent) {
|
|
105
|
+
log("")
|
|
106
|
+
log("🐝 HiveMind Context Governance — Initialization")
|
|
107
|
+
log("─".repeat(48))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Validate and set governance mode
|
|
111
|
+
const governanceMode = options.governanceMode ?? "assisted"
|
|
112
|
+
if (!isValidGovernanceMode(governanceMode)) {
|
|
113
|
+
log(`✗ Invalid governance mode: ${governanceMode}`)
|
|
114
|
+
log(" Valid: permissive, assisted, strict")
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Validate and set language
|
|
119
|
+
const language = options.language ?? "en"
|
|
120
|
+
if (!isValidLanguage(language)) {
|
|
121
|
+
log(`✗ Invalid language: ${language}`)
|
|
122
|
+
log(" Valid: en, vi")
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Validate and set expert level
|
|
127
|
+
const expertLevel = options.expertLevel ?? "intermediate"
|
|
128
|
+
if (!isValidExpertLevel(expertLevel)) {
|
|
129
|
+
log(`✗ Invalid expert level: ${expertLevel}`)
|
|
130
|
+
log(" Valid: beginner, intermediate, advanced, expert")
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Validate and set output style
|
|
135
|
+
const outputStyle = options.outputStyle ?? "explanatory"
|
|
136
|
+
if (!isValidOutputStyle(outputStyle)) {
|
|
137
|
+
log(`✗ Invalid output style: ${outputStyle}`)
|
|
138
|
+
log(" Valid: explanatory, outline, skeptical, architecture, minimal")
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Create config with agent behavior
|
|
143
|
+
const config = createConfig({
|
|
144
|
+
governance_mode: governanceMode,
|
|
145
|
+
language,
|
|
146
|
+
agent_behavior: {
|
|
147
|
+
language,
|
|
148
|
+
expert_level: expertLevel,
|
|
149
|
+
output_style: outputStyle,
|
|
150
|
+
constraints: {
|
|
151
|
+
require_code_review: options.requireCodeReview ?? false,
|
|
152
|
+
enforce_tdd: options.enforceTdd ?? false,
|
|
153
|
+
max_response_tokens: 2000,
|
|
154
|
+
explain_reasoning: true,
|
|
155
|
+
be_skeptical: outputStyle === "skeptical",
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
if (!options.silent) {
|
|
161
|
+
log(` Governance: ${governanceMode}`)
|
|
162
|
+
log(` Language: ${language}`)
|
|
163
|
+
log(` Expert Level: ${expertLevel}`)
|
|
164
|
+
log(` Output Style: ${outputStyle}`)
|
|
165
|
+
if (options.requireCodeReview) log(" ✓ Code review required")
|
|
166
|
+
if (options.enforceTdd) log(" ✓ TDD enforced")
|
|
167
|
+
log("")
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Create planning directory structure
|
|
171
|
+
if (!options.silent) {
|
|
172
|
+
log("Creating planning directory...")
|
|
173
|
+
}
|
|
174
|
+
await initializePlanningDirectory(directory)
|
|
175
|
+
|
|
176
|
+
// Save config
|
|
177
|
+
await saveConfig(directory, config)
|
|
178
|
+
|
|
179
|
+
// Initialize brain state
|
|
180
|
+
const stateManager = createStateManager(directory)
|
|
181
|
+
const sessionId = generateSessionId()
|
|
182
|
+
const state = createBrainState(sessionId, config)
|
|
183
|
+
await stateManager.save(state)
|
|
184
|
+
|
|
185
|
+
// Auto-register plugin in opencode.json
|
|
186
|
+
registerPluginInConfig(directory, options.silent ?? false)
|
|
187
|
+
|
|
188
|
+
if (!options.silent) {
|
|
189
|
+
log("")
|
|
190
|
+
log("✓ Planning directory created:")
|
|
191
|
+
log(` ${planningDir}/`)
|
|
192
|
+
log(" ├── index.md (project trajectory)")
|
|
193
|
+
log(" ├── active.md (current session)")
|
|
194
|
+
log(" ├── brain.json (machine state)")
|
|
195
|
+
log(" ├── config.json (governance settings)")
|
|
196
|
+
log(" └── archive/ (completed sessions)")
|
|
197
|
+
log("")
|
|
198
|
+
log(`Session ${sessionId} initialized.`)
|
|
199
|
+
log(`Status: ${state.session.governance_status}`)
|
|
200
|
+
log("")
|
|
201
|
+
|
|
202
|
+
if (governanceMode === "strict") {
|
|
203
|
+
log("🔒 STRICT MODE — agents must call declare_intent before writing.")
|
|
204
|
+
} else if (governanceMode === "assisted") {
|
|
205
|
+
log("🔔 ASSISTED MODE — agents get warnings but can proceed.")
|
|
206
|
+
} else {
|
|
207
|
+
log("🟢 PERMISSIVE MODE — agents work freely, activity tracked.")
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
log("")
|
|
211
|
+
log("✅ Done! Open OpenCode in this project — HiveMind is active.")
|
|
212
|
+
log("")
|
|
213
|
+
}
|
|
214
|
+
}
|