@aria_asi/cli 0.2.29 → 0.2.31
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/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.js +88 -20
- package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
- package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/codex.js +526 -2
- package/dist/aria-connector/src/connectors/codex.js.map +1 -1
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.d.ts +7 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.js +87 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.js.map +1 -0
- package/dist/aria-connector/src/connectors/must-read.d.ts +4 -0
- package/dist/aria-connector/src/connectors/must-read.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/must-read.js +111 -0
- package/dist/aria-connector/src/connectors/must-read.js.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/opencode.js +2 -0
- package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.js +231 -19
- package/dist/aria-connector/src/connectors/runtime.js.map +1 -1
- package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/shell.js +76 -3
- package/dist/aria-connector/src/connectors/shell.js.map +1 -1
- package/dist/aria-connector/src/self-update.d.ts +2 -1
- package/dist/aria-connector/src/self-update.d.ts.map +1 -1
- package/dist/aria-connector/src/self-update.js +84 -8
- package/dist/aria-connector/src/self-update.js.map +1 -1
- package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +53 -34
- package/dist/assets/hooks/aria-harness-via-sdk.mjs +126 -12
- package/dist/assets/hooks/aria-pre-tool-gate.mjs +185 -76
- package/dist/assets/hooks/aria-preturn-memory-gate.mjs +63 -14
- package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +2 -0
- package/dist/assets/hooks/aria-stop-gate.mjs +225 -52
- package/dist/assets/hooks/lib/canonical-lenses.mjs +6 -5
- package/dist/assets/hooks/lib/gate-loop-state.mjs +50 -0
- package/dist/assets/hooks/lib/hook-message-window.mjs +121 -0
- package/dist/assets/hooks/test-tier-lens-labeling.mjs +26 -58
- package/dist/assets/opencode-plugins/harness-gate/index.js +24 -2
- package/dist/assets/opencode-plugins/harness-stop/index.js +94 -5
- package/dist/runtime/auth-middleware.mjs +251 -0
- package/dist/runtime/codex-bridge.mjs +644 -0
- package/dist/runtime/discipline/CLAUDE.md +12 -0
- package/dist/runtime/discipline/doctrine_trigger_map.json +479 -0
- package/dist/runtime/doctrine_trigger_map.json +479 -0
- package/dist/runtime/fleet-engine.mjs +231 -0
- package/dist/runtime/harness-daemon.mjs +433 -0
- package/dist/runtime/local-phase.mjs +18 -0
- package/dist/runtime/manifest.json +1 -1
- package/dist/runtime/metering.mjs +100 -0
- package/dist/runtime/onboarding-engine.mjs +89 -0
- package/dist/runtime/plugin-engine.mjs +196 -0
- package/dist/runtime/sdk/BUNDLED.json +1 -1
- package/dist/runtime/sdk/index.d.ts +7 -0
- package/dist/runtime/sdk/index.js +120 -14
- package/dist/runtime/sdk/index.js.map +1 -1
- package/dist/runtime/service.mjs +1464 -67
- package/dist/runtime/vendor/aria-gate-runtime/index.d.ts +1 -1
- package/dist/runtime/vendor/aria-gate-runtime/index.d.ts.map +1 -1
- package/dist/runtime/vendor/aria-gate-runtime/index.js +16 -1
- package/dist/runtime/vendor/aria-gate-runtime/index.js.map +1 -1
- package/dist/runtime/workflow-engine.mjs +322 -0
- package/dist/sdk/BUNDLED.json +1 -1
- package/dist/sdk/index.d.ts +7 -0
- package/dist/sdk/index.js +120 -14
- package/dist/sdk/index.js.map +1 -1
- package/hooks/aria-cognition-substrate-binding.mjs +53 -34
- package/hooks/aria-harness-via-sdk.mjs +126 -12
- package/hooks/aria-pre-tool-gate.mjs +185 -76
- package/hooks/aria-preturn-memory-gate.mjs +63 -14
- package/hooks/aria-repo-doctrine-gate.mjs +2 -0
- package/hooks/aria-stop-gate.mjs +225 -52
- package/hooks/lib/canonical-lenses.mjs +6 -5
- package/hooks/lib/gate-loop-state.mjs +50 -0
- package/hooks/lib/hook-message-window.mjs +121 -0
- package/hooks/test-tier-lens-labeling.mjs +26 -58
- package/opencode-plugins/harness-gate/index.js +24 -2
- package/opencode-plugins/harness-stop/index.js +94 -5
- package/package.json +2 -2
- package/runtime-src/auth-middleware.mjs +251 -0
- package/runtime-src/codex-bridge.mjs +644 -0
- package/runtime-src/fleet-engine.mjs +231 -0
- package/runtime-src/harness-daemon.mjs +433 -0
- package/runtime-src/local-phase.mjs +18 -0
- package/runtime-src/metering.mjs +100 -0
- package/runtime-src/onboarding-engine.mjs +89 -0
- package/runtime-src/plugin-engine.mjs +196 -0
- package/runtime-src/service.mjs +1464 -67
- package/runtime-src/workflow-engine.mjs +322 -0
- package/scripts/bundle-sdk.mjs +5 -0
- package/src/connectors/claude-code.ts +98 -20
- package/src/connectors/codex.ts +534 -1
- package/src/connectors/doctrine-trigger-map.ts +112 -0
- package/src/connectors/must-read.ts +113 -0
- package/src/connectors/opencode.ts +3 -0
- package/src/connectors/runtime.ts +241 -21
- package/src/connectors/shell.ts +78 -3
- package/src/self-update.ts +89 -8
- package/dist/cli-0.2.0.tgz +0 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const STATE_DIR = join(__dirname, '..', 'state');
|
|
8
|
+
const FLEET_DIR = join(STATE_DIR, 'fleets');
|
|
9
|
+
|
|
10
|
+
function ensureDir(p) {
|
|
11
|
+
if (!existsSync(p)) mkdirSync(p, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function fleetPath(tenantId) {
|
|
15
|
+
return join(FLEET_DIR, `${tenantId}.json`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ARCHETYPE_DEFAULTS = {
|
|
19
|
+
chiefOfStaff: {
|
|
20
|
+
systemPrompt: 'You are the Chief of Staff, the executive right hand. You synthesize cross-departmental intelligence, escalate critical decisions, and coordinate the management tier. Respond concisely with actionable directives.',
|
|
21
|
+
defaultKinds: ['hq:coordinate', 'hq:escalate', 'hq:brief'],
|
|
22
|
+
},
|
|
23
|
+
directorOfSales: {
|
|
24
|
+
systemPrompt: 'You are the Director of Sales. You set revenue targets, manage the sales pipeline, coach closers, and report to the Chief of Staff. Focus on conversion metrics and strategic accounts.',
|
|
25
|
+
defaultKinds: ['sales:strategy', 'sales:forecast', 'sales:coaching'],
|
|
26
|
+
},
|
|
27
|
+
directorOfMarketing: {
|
|
28
|
+
systemPrompt: 'You are the Director of Marketing. You own brand strategy, campaign planning, content direction, and market positioning. Data-driven creative decisions.',
|
|
29
|
+
defaultKinds: ['marketing:strategy', 'marketing:campaign', 'marketing:analytics'],
|
|
30
|
+
},
|
|
31
|
+
directorOfOperations: {
|
|
32
|
+
systemPrompt: 'You are the Director of Operations. You optimize workflows, manage resources, track SLAs, and ensure the business runs efficiently. Process obsession.',
|
|
33
|
+
defaultKinds: ['ops:optimize', 'ops:workflow', 'ops:resource'],
|
|
34
|
+
},
|
|
35
|
+
directorOfFinance: {
|
|
36
|
+
systemPrompt: 'You are the Director of Finance. You manage budgets, financial reporting, cash flow analysis, and financial risk. Precision and compliance.',
|
|
37
|
+
defaultKinds: ['finance:report', 'finance:forecast', 'finance:audit'],
|
|
38
|
+
},
|
|
39
|
+
directorOfHr: {
|
|
40
|
+
systemPrompt: 'You are the Director of HR. You handle talent acquisition, team culture, performance reviews, and compliance. People-first leadership.',
|
|
41
|
+
defaultKinds: ['hr:recruit', 'hr:review', 'hr:compliance'],
|
|
42
|
+
},
|
|
43
|
+
directorOfTechnology: {
|
|
44
|
+
systemPrompt: 'You are the Director of Technology. You oversee technical architecture, engineering velocity, system reliability, and technology strategy. Builder mindset.',
|
|
45
|
+
defaultKinds: ['tech:architect', 'tech:review', 'tech:deploy'],
|
|
46
|
+
},
|
|
47
|
+
directorOfCustomerSuccess: {
|
|
48
|
+
systemPrompt: 'You are the Director of Customer Success. You own retention, onboarding, expansion revenue, and customer advocacy. Relationship-driven growth.',
|
|
49
|
+
defaultKinds: ['cs:retain', 'cs:onboard', 'cs:expand'],
|
|
50
|
+
},
|
|
51
|
+
leadQualifier: {
|
|
52
|
+
systemPrompt: 'You are a Lead Qualifier. You score inbound leads, research prospects, enrich contact data, and route qualified leads to the appropriate closer. Speed and accuracy.',
|
|
53
|
+
defaultKinds: ['lead:qualify', 'lead:enrich', 'lead:route'],
|
|
54
|
+
},
|
|
55
|
+
dealAnalyzer: {
|
|
56
|
+
systemPrompt: 'You are a Deal Analyzer. You evaluate deal economics, assess risk, compare terms, and recommend whether to pursue, negotiate, or pass. Sharp analytical lens.',
|
|
57
|
+
defaultKinds: ['deal:analyze', 'deal:risk', 'deal:recommend'],
|
|
58
|
+
},
|
|
59
|
+
outboundCloser: {
|
|
60
|
+
systemPrompt: 'You are an Outbound Closer. You craft outreach sequences, handle objections, nurture prospects, and close deals. Persistent and persuasive.',
|
|
61
|
+
defaultKinds: ['outreach:sequence', 'outreach:followup', 'outreach:close'],
|
|
62
|
+
},
|
|
63
|
+
contentStrategist: {
|
|
64
|
+
systemPrompt: 'You are a Content Strategist. You plan editorial calendars, create content briefs, ensure brand consistency, and measure content performance. Creative meets analytical.',
|
|
65
|
+
defaultKinds: ['content:plan', 'content:create', 'content:measure'],
|
|
66
|
+
},
|
|
67
|
+
transactionCoordinator: {
|
|
68
|
+
systemPrompt: 'You are a Transaction Coordinator. You manage deal lifecycles, track milestones, coordinate stakeholders, and ensure nothing falls through the cracks. Detail-obsessed.',
|
|
69
|
+
defaultKinds: ['txn:coordinate', 'txn:track', 'txn:verify'],
|
|
70
|
+
},
|
|
71
|
+
financialAnalyst: {
|
|
72
|
+
systemPrompt: 'You are a Financial Analyst. You produce financial reports, reconcile accounts, build forecasts, and flag anomalies. Numbers tell the story.',
|
|
73
|
+
defaultKinds: ['finance:report', 'finance:reconcile', 'finance:forecast'],
|
|
74
|
+
},
|
|
75
|
+
dataAnalyst: {
|
|
76
|
+
systemPrompt: 'You are a Data Analyst. You extract insights from data, build dashboards, run analyses, and present findings. Data as a competitive weapon.',
|
|
77
|
+
defaultKinds: ['data:analyze', 'data:dashboard', 'data:insight'],
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export function deployFleet(tenantId, fleetConfig, enqueueJob) {
|
|
82
|
+
ensureDir(FLEET_DIR);
|
|
83
|
+
const agents = (fleetConfig.agents || []).map((agentDef, idx) => {
|
|
84
|
+
const archetype = ARCHETYPE_DEFAULTS[agentDef.templateId] || ARCHETYPE_DEFAULTS.leadQualifier;
|
|
85
|
+
const agentId = agentDef.id || `${tenantId}-agent-${idx}`;
|
|
86
|
+
const workerId = `fleet:${tenantId}:${agentId}`;
|
|
87
|
+
return {
|
|
88
|
+
id: agentId,
|
|
89
|
+
workerId,
|
|
90
|
+
templateId: agentDef.templateId || 'leadQualifier',
|
|
91
|
+
name: agentDef.name || agentDef.templateId || `Agent ${idx + 1}`,
|
|
92
|
+
department: agentDef.department || fleetConfig.industry || 'unassigned',
|
|
93
|
+
tier: agentDef.tier || 2,
|
|
94
|
+
status: 'active',
|
|
95
|
+
systemPrompt: archetype.systemPrompt,
|
|
96
|
+
defaultKinds: archetype.defaultKinds,
|
|
97
|
+
capabilities: agentDef.capabilities || ['chat'],
|
|
98
|
+
config: agentDef.config || {},
|
|
99
|
+
lastActivity: null,
|
|
100
|
+
stats: { jobsCompleted: 0, totalTokens: 0, messagesSent: 0 },
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const fleet = {
|
|
105
|
+
tenantId,
|
|
106
|
+
config: fleetConfig,
|
|
107
|
+
deployedAt: new Date().toISOString(),
|
|
108
|
+
status: 'deployed',
|
|
109
|
+
agents,
|
|
110
|
+
maxOpenClaws: fleetConfig.maxOpenClaws || 3,
|
|
111
|
+
industry: fleetConfig.industry || 'generic',
|
|
112
|
+
tier: fleetConfig.tier || 'starter',
|
|
113
|
+
plugins: fleetConfig.plugins || [],
|
|
114
|
+
llmPreference: fleetConfig.llmPreference || 'managed',
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
writeFileSync(fleetPath(tenantId), JSON.stringify(fleet, null, 2));
|
|
118
|
+
|
|
119
|
+
const workerRegistrations = [];
|
|
120
|
+
const initialJobs = [];
|
|
121
|
+
|
|
122
|
+
for (const agent of agents) {
|
|
123
|
+
workerRegistrations.push({
|
|
124
|
+
workerId: agent.workerId,
|
|
125
|
+
surface: 'fleet',
|
|
126
|
+
capabilities: agent.capabilities,
|
|
127
|
+
metadata: {
|
|
128
|
+
tenantId,
|
|
129
|
+
agentId: agent.id,
|
|
130
|
+
agentName: agent.name,
|
|
131
|
+
department: agent.department,
|
|
132
|
+
templateId: agent.templateId,
|
|
133
|
+
tier: agent.tier,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (typeof enqueueJob === 'function') {
|
|
138
|
+
initialJobs.push({
|
|
139
|
+
kind: `fleet:${agent.id}:initialize`,
|
|
140
|
+
surface: 'fleet',
|
|
141
|
+
metadata: {
|
|
142
|
+
tenantId,
|
|
143
|
+
agentId: agent.id,
|
|
144
|
+
agentName: agent.name,
|
|
145
|
+
department: agent.department,
|
|
146
|
+
requestType: 'initialize',
|
|
147
|
+
},
|
|
148
|
+
payload: { agent, fleetConfig },
|
|
149
|
+
priority: 50 + idx,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return { fleet, workerRegistrations, initialJobs };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function loadFleet(tenantId) {
|
|
158
|
+
const p = fleetPath(tenantId);
|
|
159
|
+
if (!existsSync(p)) return null;
|
|
160
|
+
return JSON.parse(readFileSync(p, 'utf-8'));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function saveFleet(fleet) {
|
|
164
|
+
ensureDir(FLEET_DIR);
|
|
165
|
+
writeFileSync(fleetPath(fleet.tenantId), JSON.stringify(fleet, null, 2));
|
|
166
|
+
return fleet;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function getAgent(fleet, agentId) {
|
|
170
|
+
return (fleet.agents || []).find(a => a.id === agentId || a.templateId === agentId) || null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function updateAgentActivity(fleet, agentId) {
|
|
174
|
+
const agent = getAgent(fleet, agentId);
|
|
175
|
+
if (agent) {
|
|
176
|
+
agent.lastActivity = new Date().toISOString();
|
|
177
|
+
agent.stats.messagesSent = (agent.stats.messagesSent || 0) + 1;
|
|
178
|
+
saveFleet(fleet);
|
|
179
|
+
}
|
|
180
|
+
return agent;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function recordAgentJobCompletion(fleet, agentId, tokensUsed = 0) {
|
|
184
|
+
const agent = getAgent(fleet, agentId);
|
|
185
|
+
if (agent) {
|
|
186
|
+
agent.stats.jobsCompleted = (agent.stats.jobsCompleted || 0) + 1;
|
|
187
|
+
agent.stats.totalTokens = (agent.stats.totalTokens || 0) + tokensUsed;
|
|
188
|
+
agent.lastActivity = new Date().toISOString();
|
|
189
|
+
saveFleet(fleet);
|
|
190
|
+
}
|
|
191
|
+
return agent;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function getFleetStatus(tenantId) {
|
|
195
|
+
const fleet = loadFleet(tenantId);
|
|
196
|
+
if (!fleet) return { tenantId, status: 'no-fleet', agents: [], summary: null };
|
|
197
|
+
const activeAgents = fleet.agents.filter(a => a.status === 'active').length;
|
|
198
|
+
const totalMessages = fleet.agents.reduce((sum, a) => sum + (a.stats?.messagesSent || 0), 0);
|
|
199
|
+
const totalJobs = fleet.agents.reduce((sum, a) => sum + (a.stats?.jobsCompleted || 0), 0);
|
|
200
|
+
return {
|
|
201
|
+
tenantId,
|
|
202
|
+
status: fleet.status,
|
|
203
|
+
deployedAt: fleet.deployedAt,
|
|
204
|
+
industry: fleet.industry,
|
|
205
|
+
tier: fleet.tier,
|
|
206
|
+
maxOpenClaws: fleet.maxOpenClaws,
|
|
207
|
+
activeAgents,
|
|
208
|
+
totalAgents: fleet.agents.length,
|
|
209
|
+
summary: { activeAgents, totalMessages, totalJobs },
|
|
210
|
+
agents: fleet.agents.map(a => ({
|
|
211
|
+
id: a.id,
|
|
212
|
+
name: a.name,
|
|
213
|
+
templateId: a.templateId,
|
|
214
|
+
department: a.department,
|
|
215
|
+
tier: a.tier,
|
|
216
|
+
status: a.status,
|
|
217
|
+
lastActivity: a.lastActivity,
|
|
218
|
+
stats: a.stats,
|
|
219
|
+
})),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function buildAgentSystemPrompt(agent, fleetConfig) {
|
|
224
|
+
const industryContext = fleetConfig?.industry && fleetConfig.industry !== 'generic'
|
|
225
|
+
? `\n\nIndustry context: ${fleetConfig.industry}. Tailor your responses to this industry.`
|
|
226
|
+
: '';
|
|
227
|
+
const deptContext = agent.department && agent.department !== 'unassigned'
|
|
228
|
+
? `\nDepartment: ${agent.department}.`
|
|
229
|
+
: '';
|
|
230
|
+
return `${agent.systemPrompt || 'You are a helpful AI assistant.'}${deptContext}${industryContext}\n\nYou are part of a deployed AI workforce. Be professional, proactive, and results-oriented.`;
|
|
231
|
+
}
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createServer } from 'node:http';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const { runFullChain } = require('./vendor/aria-gate-runtime/index.js');
|
|
11
|
+
|
|
12
|
+
const DEFAULT_HOST = process.env.ARIA_HARNESS_DAEMON_HOST || '127.0.0.1';
|
|
13
|
+
const DEFAULT_PORT = Number(process.env.ARIA_HARNESS_DAEMON_PORT || 8790);
|
|
14
|
+
const DEFAULT_URL = process.env.ARIA_HARNESS_DAEMON_URL || `http://${DEFAULT_HOST}:${DEFAULT_PORT}`;
|
|
15
|
+
const UPSTREAM_HARNESS_URL =
|
|
16
|
+
process.env.ARIA_UPSTREAM_HARNESS_URL ||
|
|
17
|
+
process.env.ARIA_HIVE_UPSTREAM_URL ||
|
|
18
|
+
process.env.ARIA_SOUL_URL ||
|
|
19
|
+
process.env.ARIAS_SOUL_URL ||
|
|
20
|
+
process.env.ARIA_SOUL_BASE_URL ||
|
|
21
|
+
'https://harness.ariasos.com';
|
|
22
|
+
const UPSTREAM_FORGE_URL =
|
|
23
|
+
process.env.ARIA_UPSTREAM_FORGE_SERVICE_URL ||
|
|
24
|
+
process.env.ARIA_FORGE_UPSTREAM_URL ||
|
|
25
|
+
`${UPSTREAM_HARNESS_URL.replace(/\/$/, '')}/api/forge/psi`;
|
|
26
|
+
const PACKET_TTL_MS = Number(process.env.ARIA_HARNESS_PACKET_TTL_MS || 60000);
|
|
27
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const STATE_DIR = join(__dirname, 'state');
|
|
29
|
+
const LOCAL_PACKET_CACHE_PATH = join(STATE_DIR, 'harness-packet-cache.json');
|
|
30
|
+
const LEGACY_PACKET_CACHE_CANDIDATES = [
|
|
31
|
+
join(process.env.HOME || '', '.aria', '.aria-harness-last-packet.json'),
|
|
32
|
+
join(process.env.HOME || '', '.claude', '.aria-harness-last-packet.json'),
|
|
33
|
+
];
|
|
34
|
+
const LOCAL_FIRST_PRINCIPLE = 'Truth over deception. No harm. Sacred trust. Power obligates service. Reflection before action.';
|
|
35
|
+
|
|
36
|
+
let cachedPacketEnvelope = loadCachedPacketEnvelope();
|
|
37
|
+
let refreshInFlight = null;
|
|
38
|
+
let lastRefreshError = null;
|
|
39
|
+
let lastRefreshStartedAt = null;
|
|
40
|
+
let lastRefreshCompletedAt = cachedPacketEnvelope?.timestamp || null;
|
|
41
|
+
|
|
42
|
+
function trimUrl(value) {
|
|
43
|
+
return String(value || '').trim().replace(/\/+$/, '');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isLoopedUpstream(candidate) {
|
|
47
|
+
if (!candidate) return false;
|
|
48
|
+
return trimUrl(candidate) === trimUrl(DEFAULT_URL);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function json(res, status, payload) {
|
|
52
|
+
res.writeHead(status, { 'content-type': 'application/json; charset=utf-8' });
|
|
53
|
+
res.end(JSON.stringify(payload, null, 2));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function readBody(req) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const chunks = [];
|
|
59
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
60
|
+
req.on('end', () => {
|
|
61
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
62
|
+
if (!raw.trim()) {
|
|
63
|
+
resolve({});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
resolve(JSON.parse(raw));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
reject(new Error(`invalid JSON body: ${error instanceof Error ? error.message : String(error)}`));
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
req.on('error', reject);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function readBearer(req) {
|
|
77
|
+
const header = req.headers.authorization;
|
|
78
|
+
if (typeof header !== 'string') return '';
|
|
79
|
+
const match = header.match(/^Bearer\s+(.+)$/i);
|
|
80
|
+
return match ? match[1].trim() : '';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveApiKey(req, body) {
|
|
84
|
+
const headerKey = req.headers['x-aria-api-key'];
|
|
85
|
+
if (typeof headerKey === 'string' && headerKey.trim()) return headerKey.trim();
|
|
86
|
+
if (typeof body?.apiKey === 'string' && body.apiKey.trim()) return body.apiKey.trim();
|
|
87
|
+
return readBearer(req) || process.env.ARIA_API_KEY || process.env.ARIA_MASTER_TOKEN || '';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function sanitizePacketEnvelope(raw) {
|
|
91
|
+
const packet = raw?.packet && typeof raw.packet === 'object' ? raw.packet : raw;
|
|
92
|
+
if (!packet || typeof packet !== 'object') return null;
|
|
93
|
+
return {
|
|
94
|
+
ok: true,
|
|
95
|
+
packet,
|
|
96
|
+
timestamp: raw?.timestamp || new Date().toISOString(),
|
|
97
|
+
version: raw?.version || 'local-cache',
|
|
98
|
+
source: raw?.source || 'local-cache',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function loadCachedPacketEnvelope() {
|
|
103
|
+
const candidates = [LOCAL_PACKET_CACHE_PATH, ...LEGACY_PACKET_CACHE_CANDIDATES];
|
|
104
|
+
for (const candidate of candidates) {
|
|
105
|
+
try {
|
|
106
|
+
if (!existsSync(candidate)) continue;
|
|
107
|
+
const parsed = JSON.parse(readFileSync(candidate, 'utf8'));
|
|
108
|
+
const envelope = sanitizePacketEnvelope(parsed);
|
|
109
|
+
if (envelope) return envelope;
|
|
110
|
+
} catch {}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildLocalDoctrineEnvelope(message = '', reason = 'local-discipline-daemon') {
|
|
116
|
+
return {
|
|
117
|
+
ok: true,
|
|
118
|
+
packet: {
|
|
119
|
+
harness: [
|
|
120
|
+
`first_principle = ${LOCAL_FIRST_PRINCIPLE}`,
|
|
121
|
+
'axioms = truth_over_deception, no_harm, sacred_trust, power_obligates_service, reflection_before_action',
|
|
122
|
+
`daemon_reason = ${reason}`,
|
|
123
|
+
'runtime_mode = local-discipline-daemon',
|
|
124
|
+
].join('\n'),
|
|
125
|
+
axioms: {
|
|
126
|
+
truth_over_deception: true,
|
|
127
|
+
no_harm: true,
|
|
128
|
+
sacred_trust: true,
|
|
129
|
+
power_obligates_service: true,
|
|
130
|
+
reflection_before_action: true,
|
|
131
|
+
},
|
|
132
|
+
frames: {
|
|
133
|
+
first_principle: LOCAL_FIRST_PRINCIPLE,
|
|
134
|
+
runtime_mode: 'local-discipline-daemon',
|
|
135
|
+
message,
|
|
136
|
+
},
|
|
137
|
+
doctrine: {
|
|
138
|
+
local_discipline_daemon: 'Using the packaged local doctrine substrate because remote harness packet retrieval is unavailable.',
|
|
139
|
+
},
|
|
140
|
+
memory: {},
|
|
141
|
+
},
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
version: 'local-discipline-daemon',
|
|
144
|
+
source: DEFAULT_URL,
|
|
145
|
+
localFallback: true,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function persistCachedPacketEnvelope(envelope) {
|
|
150
|
+
if (!envelope) return;
|
|
151
|
+
mkdirSync(STATE_DIR, { recursive: true, mode: 0o700 });
|
|
152
|
+
writeFileSync(LOCAL_PACKET_CACHE_PATH, JSON.stringify(envelope, null, 2) + '\n', { mode: 0o600 });
|
|
153
|
+
for (const candidate of LEGACY_PACKET_CACHE_CANDIDATES) {
|
|
154
|
+
try {
|
|
155
|
+
writeFileSync(candidate, JSON.stringify(envelope) + '\n', { mode: 0o600 });
|
|
156
|
+
} catch {}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function packetAgeMs(envelope) {
|
|
161
|
+
if (!envelope?.timestamp) return Number.POSITIVE_INFINITY;
|
|
162
|
+
const ts = Date.parse(envelope.timestamp);
|
|
163
|
+
if (!Number.isFinite(ts)) return Number.POSITIVE_INFINITY;
|
|
164
|
+
return Date.now() - ts;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function packetToSubstrateSet(packetEnvelope) {
|
|
168
|
+
const p = packetEnvelope?.packet && typeof packetEnvelope.packet === 'object'
|
|
169
|
+
? packetEnvelope.packet
|
|
170
|
+
: packetEnvelope;
|
|
171
|
+
const axioms = Object.keys(p?.axioms || {});
|
|
172
|
+
const frames = Object.keys(p?.frames || {});
|
|
173
|
+
const memoryRecord = p?.memory || {};
|
|
174
|
+
const memories = Object.keys(memoryRecord).map((name) =>
|
|
175
|
+
name.toLowerCase().endsWith('.md') ? name : `${name}.md`,
|
|
176
|
+
);
|
|
177
|
+
const doctrineRecord = p?.doctrine || {};
|
|
178
|
+
const doctrinesAcceptable = Object.keys(doctrineRecord);
|
|
179
|
+
const packets = Array.from(
|
|
180
|
+
new Set([
|
|
181
|
+
'role',
|
|
182
|
+
'first_principle',
|
|
183
|
+
'turn_mode',
|
|
184
|
+
'role_rule',
|
|
185
|
+
'role_profile',
|
|
186
|
+
'cognition_belt',
|
|
187
|
+
'aria_research_pull',
|
|
188
|
+
...frames,
|
|
189
|
+
]),
|
|
190
|
+
);
|
|
191
|
+
const firstPrincipleText =
|
|
192
|
+
typeof p?.frames?.first_principle === 'string' ? p.frames.first_principle : '';
|
|
193
|
+
return {
|
|
194
|
+
axioms,
|
|
195
|
+
frames,
|
|
196
|
+
memories,
|
|
197
|
+
doctrinesAcceptable,
|
|
198
|
+
packets,
|
|
199
|
+
languagesLoaded: ['nadia', 'noor'],
|
|
200
|
+
languagesActive: { nadia: false, noor: false },
|
|
201
|
+
firstPrincipleText,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function fetchJsonWithRetry(url, init, attempts = 3) {
|
|
206
|
+
let lastError = null;
|
|
207
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
208
|
+
try {
|
|
209
|
+
const response = await fetch(url, init);
|
|
210
|
+
return response;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
lastError = error;
|
|
213
|
+
if (attempt < attempts - 1) {
|
|
214
|
+
const delay = 250 * Math.pow(2, attempt);
|
|
215
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function refreshPacket(body = {}, apiKey = '') {
|
|
223
|
+
if (refreshInFlight) return refreshInFlight;
|
|
224
|
+
if (isLoopedUpstream(UPSTREAM_HARNESS_URL)) {
|
|
225
|
+
throw new Error(`upstream harness URL loops back to local daemon: ${UPSTREAM_HARNESS_URL}`);
|
|
226
|
+
}
|
|
227
|
+
lastRefreshStartedAt = new Date().toISOString();
|
|
228
|
+
lastRefreshError = null;
|
|
229
|
+
refreshInFlight = (async () => {
|
|
230
|
+
const headers = {
|
|
231
|
+
'Content-Type': 'application/json',
|
|
232
|
+
};
|
|
233
|
+
if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
|
|
234
|
+
const response = await fetchJsonWithRetry(`${UPSTREAM_HARNESS_URL.replace(/\/$/, '')}/api/harness/codex`, {
|
|
235
|
+
method: 'POST',
|
|
236
|
+
headers,
|
|
237
|
+
body: JSON.stringify(body),
|
|
238
|
+
});
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
throw new Error(`packet refresh failed: ${response.status} ${response.statusText}`);
|
|
241
|
+
}
|
|
242
|
+
const parsed = await response.json();
|
|
243
|
+
const envelope = sanitizePacketEnvelope(parsed);
|
|
244
|
+
if (!envelope) {
|
|
245
|
+
throw new Error('packet refresh returned no packet payload');
|
|
246
|
+
}
|
|
247
|
+
envelope.source = UPSTREAM_HARNESS_URL;
|
|
248
|
+
envelope.timestamp = new Date().toISOString();
|
|
249
|
+
cachedPacketEnvelope = envelope;
|
|
250
|
+
lastRefreshCompletedAt = envelope.timestamp;
|
|
251
|
+
persistCachedPacketEnvelope(envelope);
|
|
252
|
+
return envelope;
|
|
253
|
+
})();
|
|
254
|
+
try {
|
|
255
|
+
return await refreshInFlight;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
lastRefreshError = error instanceof Error ? error.message : String(error);
|
|
258
|
+
throw error;
|
|
259
|
+
} finally {
|
|
260
|
+
refreshInFlight = null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function queuePacketRefresh(body, apiKey) {
|
|
265
|
+
const age = packetAgeMs(cachedPacketEnvelope);
|
|
266
|
+
if (refreshInFlight || age < PACKET_TTL_MS) return;
|
|
267
|
+
refreshPacket(body, apiKey).catch(() => {});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function resolvePacketEnvelope(packetRequest = {}, apiKey = '', message = '') {
|
|
271
|
+
if (cachedPacketEnvelope) {
|
|
272
|
+
queuePacketRefresh(packetRequest, apiKey);
|
|
273
|
+
return cachedPacketEnvelope;
|
|
274
|
+
}
|
|
275
|
+
if (!isLoopedUpstream(UPSTREAM_HARNESS_URL)) {
|
|
276
|
+
try {
|
|
277
|
+
return await refreshPacket(packetRequest, apiKey);
|
|
278
|
+
} catch {}
|
|
279
|
+
}
|
|
280
|
+
return buildLocalDoctrineEnvelope(message, lastRefreshError ? 'local-discipline-daemon-upstream-unavailable' : 'local-discipline-daemon');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function proxyRequest(req, body, targetUrl) {
|
|
284
|
+
if (isLoopedUpstream(targetUrl)) {
|
|
285
|
+
throw new Error(`refusing to proxy local daemon request back into itself: ${targetUrl}`);
|
|
286
|
+
}
|
|
287
|
+
const headers = {};
|
|
288
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
289
|
+
if (typeof value === 'string') headers[key] = value;
|
|
290
|
+
}
|
|
291
|
+
headers['content-type'] = headers['content-type'] || 'application/json';
|
|
292
|
+
const response = await fetchJsonWithRetry(targetUrl, {
|
|
293
|
+
method: req.method || 'POST',
|
|
294
|
+
headers,
|
|
295
|
+
body: req.method === 'GET' ? undefined : JSON.stringify(body),
|
|
296
|
+
});
|
|
297
|
+
const text = await response.text();
|
|
298
|
+
return {
|
|
299
|
+
status: response.status,
|
|
300
|
+
contentType: response.headers.get('content-type') || 'application/json; charset=utf-8',
|
|
301
|
+
body: text,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function forgeSynthesizeUrl() {
|
|
306
|
+
if (trimUrl(UPSTREAM_FORGE_URL).endsWith('/forge/synthesize')) {
|
|
307
|
+
return trimUrl(UPSTREAM_FORGE_URL);
|
|
308
|
+
}
|
|
309
|
+
if (trimUrl(UPSTREAM_FORGE_URL).endsWith('/api/forge/psi')) {
|
|
310
|
+
return `${trimUrl(UPSTREAM_FORGE_URL).replace(/\/api\/forge\/psi$/, '')}/forge/synthesize`;
|
|
311
|
+
}
|
|
312
|
+
return `${trimUrl(UPSTREAM_HARNESS_URL)}/forge/synthesize`;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function buildLocalValidation(text, packetEnvelope, requireCognitionBlock = false) {
|
|
316
|
+
const layer3 = runFullChain(text, {
|
|
317
|
+
substrate: packetToSubstrateSet(packetEnvelope),
|
|
318
|
+
requireCognitionBlock,
|
|
319
|
+
});
|
|
320
|
+
const failures = Array.isArray(layer3?.failures) ? layer3.failures : [];
|
|
321
|
+
const hardFailures = failures.filter((failure) => failure?.severity === 'block');
|
|
322
|
+
return {
|
|
323
|
+
passed: hardFailures.length === 0,
|
|
324
|
+
severity: hardFailures.length === 0 ? 'warn' : 'block',
|
|
325
|
+
violations: failures.map((failure) => failure?.detail || failure?.kind).filter(Boolean),
|
|
326
|
+
gateTriggers: failures.map((failure) => failure?.kind).filter(Boolean),
|
|
327
|
+
local: true,
|
|
328
|
+
summary: layer3?.summary || '',
|
|
329
|
+
layer3,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function healthPayload() {
|
|
334
|
+
return {
|
|
335
|
+
ok: true,
|
|
336
|
+
runtime: 'aria-local-harness-daemon',
|
|
337
|
+
url: DEFAULT_URL,
|
|
338
|
+
upstreamHarnessUrl: UPSTREAM_HARNESS_URL,
|
|
339
|
+
upstreamForgeUrl: UPSTREAM_FORGE_URL,
|
|
340
|
+
upstreamLoopDetected: isLoopedUpstream(UPSTREAM_HARNESS_URL) || isLoopedUpstream(UPSTREAM_FORGE_URL),
|
|
341
|
+
packet: {
|
|
342
|
+
present: Boolean(cachedPacketEnvelope),
|
|
343
|
+
source: cachedPacketEnvelope?.source || null,
|
|
344
|
+
timestamp: cachedPacketEnvelope?.timestamp || null,
|
|
345
|
+
ageMs: Number.isFinite(packetAgeMs(cachedPacketEnvelope)) ? packetAgeMs(cachedPacketEnvelope) : null,
|
|
346
|
+
ttlMs: PACKET_TTL_MS,
|
|
347
|
+
},
|
|
348
|
+
refresh: {
|
|
349
|
+
inFlight: Boolean(refreshInFlight),
|
|
350
|
+
lastStartedAt: lastRefreshStartedAt,
|
|
351
|
+
lastCompletedAt: lastRefreshCompletedAt,
|
|
352
|
+
lastError: lastRefreshError,
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const server = createServer(async (req, res) => {
|
|
358
|
+
try {
|
|
359
|
+
const url = new URL(req.url || '/', DEFAULT_URL);
|
|
360
|
+
if (req.method === 'GET' && url.pathname === '/health') {
|
|
361
|
+
return json(res, 200, healthPayload());
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const body = req.method === 'GET' ? {} : await readBody(req);
|
|
365
|
+
const apiKey = resolveApiKey(req, body);
|
|
366
|
+
|
|
367
|
+
if (url.pathname === '/packet' || url.pathname === '/api/harness/codex') {
|
|
368
|
+
const packetEnvelope = await resolvePacketEnvelope(body, apiKey, body.message || body.task || '');
|
|
369
|
+
return json(res, 200, {
|
|
370
|
+
ok: true,
|
|
371
|
+
packet: packetEnvelope.packet,
|
|
372
|
+
timestamp: packetEnvelope.timestamp,
|
|
373
|
+
version: packetEnvelope.version,
|
|
374
|
+
source: packetEnvelope.source,
|
|
375
|
+
localCache: packetEnvelope === cachedPacketEnvelope,
|
|
376
|
+
localFallback: packetEnvelope.localFallback === true,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (url.pathname === '/validate-output' || url.pathname === '/api/harness/validate') {
|
|
381
|
+
if (typeof body.text !== 'string' || !body.text.trim()) {
|
|
382
|
+
return json(res, 400, { ok: false, error: 'validate requires non-empty text' });
|
|
383
|
+
}
|
|
384
|
+
const packetEnvelope =
|
|
385
|
+
(body.packet ? sanitizePacketEnvelope(body.packet) : null) ||
|
|
386
|
+
await resolvePacketEnvelope(body.packetRequest || {}, apiKey, body.message || body.task || body.text);
|
|
387
|
+
if (!packetEnvelope) {
|
|
388
|
+
return json(res, 503, {
|
|
389
|
+
ok: false,
|
|
390
|
+
error: 'packet unavailable for local validation',
|
|
391
|
+
refreshInFlight: Boolean(refreshInFlight),
|
|
392
|
+
lastRefreshError,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
const validation = buildLocalValidation(body.text, packetEnvelope, body.requireCognitionBlock === true);
|
|
396
|
+
return json(res, 200, validation);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (url.pathname === '/api/forge/psi' || url.pathname === '/forge/synthesize') {
|
|
400
|
+
const primaryTarget =
|
|
401
|
+
url.pathname === '/forge/synthesize'
|
|
402
|
+
? forgeSynthesizeUrl()
|
|
403
|
+
: trimUrl(UPSTREAM_FORGE_URL);
|
|
404
|
+
let proxied = await proxyRequest(req, body, primaryTarget);
|
|
405
|
+
if (
|
|
406
|
+
url.pathname === '/api/forge/psi' &&
|
|
407
|
+
(proxied.status === 404 || proxied.status === 405)
|
|
408
|
+
) {
|
|
409
|
+
proxied = await proxyRequest(req, body, forgeSynthesizeUrl());
|
|
410
|
+
}
|
|
411
|
+
res.writeHead(proxied.status, { 'content-type': proxied.contentType });
|
|
412
|
+
res.end(proxied.body);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const targetUrl = `${UPSTREAM_HARNESS_URL.replace(/\/$/, '')}${url.pathname}${url.search}`;
|
|
417
|
+
const proxied = await proxyRequest(req, body, targetUrl);
|
|
418
|
+
res.writeHead(proxied.status, { 'content-type': proxied.contentType });
|
|
419
|
+
res.end(proxied.body);
|
|
420
|
+
} catch (error) {
|
|
421
|
+
json(res, 500, {
|
|
422
|
+
ok: false,
|
|
423
|
+
error: error instanceof Error ? error.message : String(error),
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
server.listen(DEFAULT_PORT, DEFAULT_HOST, () => {
|
|
429
|
+
console.log(`[aria-harnessd] listening on ${DEFAULT_URL}`);
|
|
430
|
+
if (!cachedPacketEnvelope && !isLoopedUpstream(UPSTREAM_HARNESS_URL)) {
|
|
431
|
+
refreshPacket({}, process.env.ARIA_API_KEY || process.env.ARIA_MASTER_TOKEN || '').catch(() => {});
|
|
432
|
+
}
|
|
433
|
+
});
|
|
@@ -618,6 +618,24 @@ export function buildRuntimeCognitionDirective(packet, bundle = {}) {
|
|
|
618
618
|
'- Predictor tests whether the answer will survive the next real operational step.',
|
|
619
619
|
'- Mizan keeps the answer proportionate, exact, and high-quality.',
|
|
620
620
|
'',
|
|
621
|
+
'Visible cognition contract for the user-facing response:',
|
|
622
|
+
'- For any non-trivial reply, include a readable <cognition> block using everyday labels, not internal lens codenames.',
|
|
623
|
+
'- If you request any non-trivial tool call, place the <cognition> block BEFORE the tool request.',
|
|
624
|
+
'- If the action is deploy, destructive, or state-mutating, include both <verify> and <expected> blocks before the tool request.',
|
|
625
|
+
'- The runtime will canonicalize the readable block into backend JSON automatically, so do not hide it behind private shorthand.',
|
|
626
|
+
'',
|
|
627
|
+
'<cognition>',
|
|
628
|
+
' truth: <what is actually true here, grounded in visible evidence and substrate anchors>',
|
|
629
|
+
' harm: <what could break, mislead, or damage trust if the next step is wrong>',
|
|
630
|
+
' trust: <what principle, promise, or user trust boundary governs this turn>',
|
|
631
|
+
' power: <what capability is being used and what restraint it requires>',
|
|
632
|
+
' reflection: <what deeper structural read changes the action, not just the wording>',
|
|
633
|
+
' context: <what surrounding repo/runtime/user context materially changes the correct move>',
|
|
634
|
+
' impact: <what second-order consequence or next-step outcome follows from this move>',
|
|
635
|
+
' beauty: <what cleaner, more elegant, more durable path preserves the contract>',
|
|
636
|
+
` first_principle: ${firstPrincipleText}`,
|
|
637
|
+
'</cognition>',
|
|
638
|
+
'',
|
|
621
639
|
dominantModules.length ? 'Current module insights:' : 'Current module insights: none yet',
|
|
622
640
|
...dominantModules.map((line) => `- ${line}`),
|
|
623
641
|
'',
|