Skip to content

Commit fdf7407

Browse files
committed
docs: Add Strategic Co-Founder Protocol to AGENTS.md (#9684)
- Mandates the use of mutate_frontier tool when the user pivots context. - Maintains dynamic alignment in Native Graph topology for agent orchestration.
1 parent 168dbb1 commit fdf7407

5 files changed

Lines changed: 156 additions & 6 deletions

File tree

AGENTS.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,14 @@ Adhering to this recovery protocol is paramount for:
113113
- **Accurate Analysis:** Ensuring that future session summaries and memory queries are based on a complete and truthful record.
114114
- **Agent Learning:** Providing the necessary data for the agent to learn from its past interactions, including its own errors and recovery attempts.
115115

116-
## 5. Request Triage
116+
## 5. The Strategic Co-Founder Protocol (Active Context Mutation)
117+
118+
If the user explicitly pivots the top-level focus of the session (e.g., "Let's switch from the Database to the Next.js UI layer", or "Let's focus on Item 2 of the epic"), you **MUST** actively update the Native Graph so that the context window strategy remains aligned.
119+
120+
- **Action:** You MUST invoke the `mutate_frontier` tool, passing the new conceptual target as `targetNodeId` (e.g. `nextjs-ui`).
121+
- **Why:** This establishes a high-weight edge in the native graph topology, ensuring the Context Priming Engine (`get_context_frontier`) passes the updated reality to future turns and sessions (Session Amnesia prevention). This also functions as the trigger for background Librarian workflows to perform deep topological re-organizations.
122+
123+
## 6. Request Triage
117124

118125
First, classify the user's request into one of two categories:
119126

@@ -125,13 +132,13 @@ First, classify the user's request into one of two categories:
125132

126133
**Note:** A conceptual discussion can become an actionable task. The moment the intent shifts from "what if..." to "let's do...", you must treat it as a new actionable request and apply the Ticket-First Gate.
127134

128-
## 6. Git Protocol
135+
## 7. Git Protocol
129136

130137
- **Ticket ID Required:** The commit subject line **MUST** end with `(#TICKET_ID)`.
131138
- **Correct:** `feat: Add infinite canvas (#8392)`
132139
- **Standard:** Follow Conventional Commits.
133140

134-
## 7. Ticket Closure Protocol (Definition of Done)
141+
## 8. Ticket Closure Protocol (Definition of Done)
135142

136143
You **MUST** perform these steps in order before marking a task as complete:
137144

@@ -142,7 +149,7 @@ You **MUST** perform these steps in order before marking a task as complete:
142149
- The task is complete (summarize the result).
143150
4. **Close:** Only after steps 1-3 are complete can you close the ticket.
144151

145-
## 8. Preventing Context Corruption (State Management)
152+
## 9. Preventing Context Corruption (State Management)
146153

147154
Working on the Neo platform requires long, complex sessions. To prevent your context window from becoming corrupted with multiple competing versions of the same file after several edits, you MUST adhere to this protocol:
148155

@@ -152,15 +159,15 @@ Working on the Neo platform requires long, complex sessions. To prevent your con
152159
4. **Use `grep_search` for Method Verification:** If you need to verify the current state of a specific method after changes, use `grep_search` with the `context` parameter to surgically extract only that method.
153160
5. **No Shell Fallbacks:** You are strictly forbidden from using `cat` or `grep` via `run_shell_command` to read files. Always use the native `read_file` or `grep_search` tools.
154161

155-
## 9. Testing and Validation Protocol
162+
## 10. Testing and Validation Protocol
156163

157164
To maintain repository hygiene and improve test coverage, you MUST adhere to the following rules when validating your work:
158165

159166
1. **Micro-Benchmarking (V8 Physics):** If you need to quickly test raw JavaScript engine performance or syntax (e.g., variable hoisting, iteration speed), you may use `run_shell_command` with `node -e '...'`. This is preferred for ephemeral, non-framework tests.
160167
2. **No Throwaway Scripts:** You are strictly **FORBIDDEN** from using `run_shell_command` (e.g., `cat << EOF > test.js`) to create temporary testing scripts on the filesystem.
161168
3. **Permanent Coverage:** If you are testing or validating Neo.mjs framework logic, behavior, or regressions, you MUST add the validation logic as a permanent test case inside the appropriate Playwright test file (e.g., `test/playwright/unit/data/Store.spec.mjs`). Use the `replace` or `write_file` tools to do this. A task is not complete unless its framework logic is permanently verifiable.
162169

163-
## 10. File Editing Tool Selection (The "Append Gap")
170+
## 11. File Editing Tool Selection (The "Append Gap")
164171

165172
Due to the constraints of the agentic environment, you MUST adhere to the following rules when modifying files to prevent JSON escaping errors and tool contract violations:
166173

ai/mcp/server/memory-core/openapi.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,54 @@ paths:
266266
schema:
267267
$ref: '#/components/schemas/ErrorResponse'
268268

269+
/context/frontier/mutate:
270+
post:
271+
summary: Mutate Context Frontier
272+
operationId: mutate_frontier
273+
x-pass-as-object: true
274+
description: |
275+
Actively manages the [Frontier] node. When project priorities pivot, this injects those new priorities into the Graph's Edge relationships in real-time.
276+
tags: [System]
277+
requestBody:
278+
required: true
279+
content:
280+
application/json:
281+
schema:
282+
type: object
283+
required:
284+
- targetNodeId
285+
properties:
286+
targetNodeId:
287+
type: string
288+
description: The target node ID to pivot focus to.
289+
weight:
290+
type: number
291+
description: Importance weight, typically very high for a new pivot.
292+
default: 1.0
293+
relationship:
294+
type: string
295+
description: The semantic edge type
296+
default: "STRATEGIC_PIVOT"
297+
responses:
298+
'200':
299+
description: OK
300+
content:
301+
application/json:
302+
schema:
303+
type: object
304+
'400':
305+
description: Invalid request body
306+
content:
307+
application/json:
308+
schema:
309+
$ref: '#/components/schemas/ErrorResponse'
310+
'500':
311+
description: Internal server error.
312+
content:
313+
application/json:
314+
schema:
315+
$ref: '#/components/schemas/ErrorResponse'
316+
269317
/summaries:
270318
get:
271319
summary: Get All Summaries

ai/mcp/server/memory-core/services/GraphService.mjs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,67 @@ class GraphService extends Base {
220220

221221
return topology;
222222
}
223+
224+
/**
225+
* Actively mutates the relationships originating from the frontier node.
226+
* Upserts the frontier node if necessary, establishes the new relationship, and safely
227+
* decays older strategic neighbors to prevent context saturation.
228+
* @param {Object} args
229+
* @param {String} args.targetNodeId The ID of the node to pivot focus to.
230+
* @param {Number} [args.weight=1.0] Importance weight, typically very high for a new pivot.
231+
* @param {String} [args.relationship='STRATEGIC_PIVOT'] The semantic edge type.
232+
*/
233+
mutateFrontier({ targetNodeId, weight = 1.0, relationship = 'STRATEGIC_PIVOT' }) {
234+
let frontierNode = this.db.nodes.get('frontier');
235+
if (!frontierNode) {
236+
this.upsertNode({
237+
id: 'frontier',
238+
type: 'SYSTEM_ANCHOR',
239+
name: 'Active Context Frontier',
240+
description: 'The shifting focal point of the active Neo OS agent session.'
241+
});
242+
}
243+
244+
// First, apply decay to existing frontier edges to prevent saturation
245+
const outbound = this.db.edges.getByIndex('source', 'frontier');
246+
outbound.forEach(e => {
247+
if (e.target !== targetNodeId) {
248+
// Decay by 50%
249+
let currentWeight = e.properties?.weight || 1.0;
250+
e.properties.weight = currentWeight * 0.5;
251+
this.db.edges.update(e);
252+
}
253+
});
254+
255+
// Upsert target node placeholder if it doesn't exist, to prevent getContextFrontier filtering it out
256+
if (!this.db.nodes.get(targetNodeId)) {
257+
this.upsertNode({
258+
id: targetNodeId,
259+
type: 'CONTEXT_NODE',
260+
name: targetNodeId,
261+
description: `Dynamically injected context target during a STRATEGIC_PIVOT.`
262+
});
263+
}
264+
265+
// Establish the new high-weight connection
266+
let existingEdge = this.db.edges.items.find(e => e.source === 'frontier' && e.target === targetNodeId && e.type === relationship);
267+
if (existingEdge) {
268+
existingEdge.properties.weight = weight;
269+
this.db.edges.update(existingEdge);
270+
} else {
271+
this.db.addEdge({
272+
id: Neo.getId('edge'),
273+
source: 'frontier',
274+
target: targetNodeId,
275+
type: relationship,
276+
properties: { weight }
277+
});
278+
}
279+
280+
logger.info(`[GraphService] Mutated [Frontier] -> ${targetNodeId} w/ weight ${weight}`);
281+
282+
return { success: true, targetNodeId, newWeight: weight };
283+
}
223284
}
224285

225286
export default Neo.setupClass(GraphService);

ai/mcp/server/memory-core/services/MemoryService.mjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,39 @@ class MemoryService extends Base {
263263
};
264264
}
265265
}
266+
267+
/**
268+
* Mutates the active context frontier in the native knowledge graph.
269+
* @param {Object} options
270+
* @param {String} options.targetNodeId The semantic target ID.
271+
* @param {Number} [options.weight=1.0] Importance weighting.
272+
* @param {String} [options.relationship='STRATEGIC_PIVOT'] Relationships label.
273+
* @returns {Promise<Object>}
274+
*/
275+
async mutateFrontier({targetNodeId, weight = 1.0, relationship = 'STRATEGIC_PIVOT'}) {
276+
try {
277+
if (!targetNodeId) {
278+
return {
279+
error : 'targetNodeId is required',
280+
code : 'INVALID_PARAMETERS'
281+
};
282+
}
283+
284+
const result = GraphService.mutateFrontier({ targetNodeId, weight, relationship });
285+
286+
return {
287+
message: 'Successfully mutated the context frontier.',
288+
result
289+
};
290+
} catch (error) {
291+
logger.error('[MemoryService] Error running mutateFrontier:', error);
292+
return {
293+
error : 'Failed to mutate context frontier',
294+
message: error.message,
295+
code : 'MUTATE_FRONTIER_ERROR'
296+
};
297+
}
298+
}
266299
}
267300

268301
export default Neo.setupClass(MemoryService);

ai/mcp/server/memory-core/services/toolService.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const serviceMapping = {
2424
healthcheck : HealthService .healthcheck .bind(HealthService),
2525
manage_database : DatabaseLifecycleService.manageDatabase .bind(DatabaseLifecycleService),
2626
manage_database_backup: DatabaseService .manageDatabaseBackup.bind(DatabaseService),
27+
mutate_frontier : MemoryService .mutateFrontier .bind(MemoryService),
2728
query_raw_memories : MemoryService .queryMemories .bind(MemoryService),
2829
query_summaries : SummaryService .querySummaries .bind(SummaryService),
2930
search_nodes : GraphService .searchNodes .bind(GraphService),

0 commit comments

Comments
 (0)