@ornexus/neocortex 4.60.27 → 4.60.29

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,343 @@
1
+ /**
2
+ * Public, deterministic branch-unit contract for epic-owned YOLO/YOLOOP runs.
3
+ * Pure data/functions only: callers own Git and filesystem effects.
4
+ */
5
+ export const BRANCH_UNIT_MODES = Object.freeze(['epic', 'story']);
6
+ const LEGACY_INTEGRATION_STEPS = new Set([
7
+ 'step-c-09-sync-main',
8
+ 'step-c-10-create-pr',
9
+ 'step-c-11-review-pr',
10
+ 'step-c-12-merge-pr',
11
+ ]);
12
+ /** Resolve once from persisted state. Existing Git progress always wins. */
13
+ export function resolveBranchUnit(epic, stories) {
14
+ const legacyProgress = stories.some(hasLegacyStoryGitProgress);
15
+ if (epic.branch_mode === 'story') {
16
+ return resolution('story', 'recorded', true, epic, ['branch-mode-recorded-story']);
17
+ }
18
+ if (epic.branch_mode === 'epic') {
19
+ const conflictingEvidence = classifyRecordedEpicStoryGitEvidence(epic, stories);
20
+ if (conflictingEvidence === 'strong') {
21
+ return resolution('story', 'legacy-progress', true, epic, [
22
+ 'branch-mode-conflict-legacy-progress-preserved',
23
+ 'branch-mode-recorded-epic-not-applied',
24
+ ]);
25
+ }
26
+ if (conflictingEvidence === 'ambiguous') {
27
+ return resolution('story', 'legacy-progress', true, epic, [
28
+ 'branch-mode-conflict-legacy-progress-preserved',
29
+ 'branch-mode-conflict-ambiguous-story-git-evidence',
30
+ 'branch-mode-recorded-epic-not-applied',
31
+ ]);
32
+ }
33
+ return resolution('epic', 'recorded', hasEpicGitProgress(epic, stories), epic, ['branch-mode-recorded-epic']);
34
+ }
35
+ if (legacyProgress || stories.some(hasAnyStoryProgress)) {
36
+ return resolution('story', 'legacy-progress', true, epic, ['legacy-story-git-progress-detected']);
37
+ }
38
+ if (nonEmpty(epic.execution_branch)) {
39
+ return resolution('epic', 'epic-boundary', hasEpicGitProgress(epic, stories), epic, ['epic-execution-branch-declared']);
40
+ }
41
+ return resolution('epic', 'new-epic-default', false, {
42
+ ...epic,
43
+ execution_branch: `epic/${epic.id}`,
44
+ // Setup records the real current branch before switching. Pure planning
45
+ // must not invent a default origin.
46
+ origin_branch: epic.origin_branch,
47
+ }, ['missing-branch-mode-new-epic-default']);
48
+ }
49
+ /** Retry-safe checkpoint persistence decision; same key may never change range. */
50
+ export function reconcileStoryCheckpoint(current, requested) {
51
+ if (!current)
52
+ return { kind: 'accepted', checkpoint: requested };
53
+ if (current.idempotencyKey !== requested.idempotencyKey)
54
+ return { kind: 'accepted', checkpoint: requested };
55
+ if (current.storyId === requested.storyId &&
56
+ current.epicId === requested.epicId &&
57
+ current.branch === requested.branch &&
58
+ current.baseSha === requested.baseSha &&
59
+ current.headSha === requested.headSha &&
60
+ sameStrings(current.commits, requested.commits) &&
61
+ current.dispatchId === requested.dispatchId &&
62
+ current.bundleId === requested.bundleId &&
63
+ current.bundleDigest === requested.bundleDigest &&
64
+ current.graphRevision === requested.graphRevision &&
65
+ current.claimRevision === requested.claimRevision &&
66
+ sameEvidenceReceipt(current.qaReceipt, requested.qaReceipt) &&
67
+ sameEvidenceReceipt(current.reviewReceipt, requested.reviewReceipt))
68
+ return { kind: 'reused', checkpoint: current };
69
+ return { kind: 'blocked', reasonCode: 'checkpoint-idempotency-conflict' };
70
+ }
71
+ /** Plan a rollback that reverts only the selected story and protects later ranges. */
72
+ export function buildStoryRollbackPlan(target, later) {
73
+ const protectedLaterCommits = [...new Set(later.flatMap((item) => item.commits))];
74
+ if (target.commits.some((sha) => protectedLaterCommits.includes(sha))) {
75
+ return { blocked: true, reasonCode: 'overlapping-story-checkpoints' };
76
+ }
77
+ return Object.freeze({
78
+ schemaVersion: 1,
79
+ storyId: target.storyId,
80
+ epicId: target.epicId,
81
+ strategy: 'additive-revert',
82
+ targetCommitsNewestFirst: Object.freeze([...target.commits].reverse()),
83
+ protectedLaterCommits: Object.freeze(protectedLaterCommits),
84
+ historyRewrite: false,
85
+ });
86
+ }
87
+ export function acquireEpicBranchLease(current, requested, nowIso) {
88
+ if (!current || current.expiresAt <= nowIso)
89
+ return { kind: 'acquired', lease: requested };
90
+ if (current.ownerStoryId === requested.ownerStoryId &&
91
+ current.sessionId === requested.sessionId &&
92
+ current.idempotencyKey === requested.idempotencyKey)
93
+ return { kind: 'reused', lease: current };
94
+ return {
95
+ kind: 'blocked',
96
+ reasonCode: 'epic-worktree-writer-active',
97
+ canonicalReasonCode: 'epic-checkout-writer-active',
98
+ holderStoryId: current.ownerStoryId,
99
+ };
100
+ }
101
+ export function validateStoryCheckpoint(checkpoint, resolution) {
102
+ const errors = [];
103
+ if (resolution.mode !== 'epic')
104
+ errors.push('checkpoint-requires-epic-branch-mode');
105
+ if (checkpoint.schemaVersion !== 1)
106
+ errors.push('checkpoint-schema-version-invalid');
107
+ if (checkpoint.epicId !== resolution.epicId)
108
+ errors.push('checkpoint-epic-mismatch');
109
+ if (!nonEmpty(checkpoint.storyId) || !checkpoint.storyId.startsWith(`${checkpoint.epicId}.`))
110
+ errors.push('checkpoint-story-mismatch');
111
+ if (!isSha(checkpoint.baseSha) || !isSha(checkpoint.headSha))
112
+ errors.push('checkpoint-invalid-sha');
113
+ if (checkpoint.baseSha === checkpoint.headSha)
114
+ errors.push('checkpoint-empty-range');
115
+ if (!Array.isArray(checkpoint.commits) || checkpoint.commits.length === 0 || checkpoint.commits.some((sha) => !isSha(sha))) {
116
+ errors.push('checkpoint-invalid-commits');
117
+ }
118
+ else {
119
+ if (!checkpoint.commits.includes(checkpoint.headSha))
120
+ errors.push('checkpoint-head-not-in-commits');
121
+ if (new Set(checkpoint.commits).size !== checkpoint.commits.length)
122
+ errors.push('checkpoint-duplicate-commits');
123
+ }
124
+ if (!nonEmpty(checkpoint.branch))
125
+ errors.push('checkpoint-branch-missing');
126
+ if (resolution.executionBranch && checkpoint.branch !== resolution.executionBranch)
127
+ errors.push('checkpoint-branch-mismatch');
128
+ if (!nonEmpty(checkpoint.idempotencyKey))
129
+ errors.push('checkpoint-idempotency-key-missing');
130
+ if (checkpoint.dispatchId !== undefined && !isHash(checkpoint.dispatchId))
131
+ errors.push('checkpoint-dispatch-invalid');
132
+ if (checkpoint.bundleId !== undefined && !isHash(checkpoint.bundleId))
133
+ errors.push('checkpoint-bundle-id-invalid');
134
+ if (checkpoint.bundleDigest !== undefined && !isHash(checkpoint.bundleDigest))
135
+ errors.push('checkpoint-bundle-digest-invalid');
136
+ if (checkpoint.graphRevision !== undefined && !isHash(checkpoint.graphRevision))
137
+ errors.push('checkpoint-graph-revision-invalid');
138
+ if (checkpoint.claimRevision === undefined)
139
+ errors.push('checkpoint-claim-revision-required');
140
+ else if (!isHash(checkpoint.claimRevision))
141
+ errors.push('checkpoint-claim-revision-invalid');
142
+ if (!Array.isArray(checkpoint.receiptRefs) || checkpoint.receiptRefs.length === 0 || checkpoint.receiptRefs.some((ref) => !nonEmpty(ref))) {
143
+ errors.push('checkpoint-receipts-missing');
144
+ }
145
+ if (checkpoint.qaVerdict !== 'passed' && checkpoint.qaVerdict !== 'blocked')
146
+ errors.push('checkpoint-qa-verdict-invalid');
147
+ if (!['approved', 'changes-requested', 'pending'].includes(checkpoint.reviewVerdict))
148
+ errors.push('checkpoint-review-verdict-invalid');
149
+ if (!nonEmpty(checkpoint.recordedAt) || !Number.isFinite(Date.parse(checkpoint.recordedAt)))
150
+ errors.push('checkpoint-recorded-at-invalid');
151
+ if (checkpoint.reviewVerdict === 'approved' && checkpoint.qaVerdict !== 'passed')
152
+ errors.push('checkpoint-review-without-qa');
153
+ errors.push(...validateCheckpointEvidence(checkpoint));
154
+ return Object.freeze([...new Set(errors)]);
155
+ }
156
+ function validateCheckpointEvidence(checkpoint) {
157
+ const errors = [];
158
+ const qa = checkpoint.qaReceipt;
159
+ const review = checkpoint.reviewReceipt;
160
+ if (!qa)
161
+ errors.push('checkpoint-qa-evidence-required');
162
+ else {
163
+ if (qa.schemaVersion !== 1 || qa.kind !== 'story_qa_evidence' || qa.producer !== 'local-yolo-tdd'
164
+ || (qa.evidenceVersion !== undefined && qa.evidenceVersion !== 'git-immutable-v1'
165
+ && qa.evidenceVersion !== 'p205-execution-v2')
166
+ || qa.verdict !== checkpoint.qaVerdict || !evidenceBindingMatches(checkpoint, qa)
167
+ || !isHash(qa.sourceEvidenceDigest) || !nonEmpty(qa.receiptRef)
168
+ || qa.receiptRef !== `story-qa:${qa.sourceEvidenceDigest}`
169
+ || !Number.isFinite(Date.parse(qa.checkedAt))) {
170
+ errors.push('checkpoint-qa-evidence-invalid');
171
+ }
172
+ else if (qa.evidenceVersion === 'p205-execution-v2' && (qa.contract !== 'P205-CI-02'
173
+ || qa.command !== 'node scripts/test-root.mjs --gate complete'
174
+ || typeof qa.manifestDigest !== 'string' || !isHash(qa.manifestDigest)
175
+ || !Array.isArray(qa.gateIds) || qa.gateIds.length === 0 || qa.gateIds.some((gateId) => !nonEmpty(gateId))
176
+ || typeof qa.resultDigest !== 'string' || !isHash(qa.resultDigest))) {
177
+ errors.push('checkpoint-qa-execution-evidence-invalid');
178
+ }
179
+ }
180
+ if (checkpoint.reviewVerdict !== 'pending') {
181
+ if (!review)
182
+ errors.push('checkpoint-review-evidence-required');
183
+ else if (review.schemaVersion !== 1 || review.kind !== 'story_review_evidence'
184
+ || review.producer !== 'root-commit-range-review' || review.verdict !== checkpoint.reviewVerdict
185
+ || !evidenceBindingMatches(checkpoint, review) || !isHash(review.sourceEvidenceDigest)
186
+ || !nonEmpty(review.receiptRef) || review.receiptRef !== `story-review:${review.sourceEvidenceDigest}`
187
+ || !Number.isFinite(Date.parse(review.reviewedAt))) {
188
+ errors.push('checkpoint-review-evidence-invalid');
189
+ }
190
+ }
191
+ else if (review) {
192
+ errors.push('checkpoint-review-evidence-unexpected');
193
+ }
194
+ if (qa && review) {
195
+ if (qa.receiptRef === review.receiptRef || review.qaReceiptRef !== qa.receiptRef) {
196
+ errors.push('checkpoint-evidence-not-independent');
197
+ }
198
+ if (!checkpoint.receiptRefs.includes(qa.receiptRef) || !checkpoint.receiptRefs.includes(review.receiptRef)) {
199
+ errors.push('checkpoint-evidence-refs-unbound');
200
+ }
201
+ if (Date.parse(review.reviewedAt) < Date.parse(qa.checkedAt))
202
+ errors.push('checkpoint-review-before-qa');
203
+ }
204
+ return errors;
205
+ }
206
+ function evidenceBindingMatches(checkpoint, evidence) {
207
+ return evidence.storyId === checkpoint.storyId
208
+ && evidence.epicId === checkpoint.epicId
209
+ && evidence.baseSha === checkpoint.baseSha
210
+ && evidence.headSha === checkpoint.headSha
211
+ && Boolean(checkpoint.bundleDigest) && evidence.bundleDigest === checkpoint.bundleDigest
212
+ && Boolean(checkpoint.graphRevision) && evidence.graphRevision === checkpoint.graphRevision;
213
+ }
214
+ function sameEvidenceReceipt(left, right) {
215
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
216
+ }
217
+ export function toStoryReviewRequest(checkpoint) {
218
+ return Object.freeze({
219
+ schemaVersion: 1,
220
+ kind: 'commit-range-review',
221
+ storyId: checkpoint.storyId,
222
+ epicId: checkpoint.epicId,
223
+ baseSha: checkpoint.baseSha,
224
+ headSha: checkpoint.headSha,
225
+ receiptRefs: checkpoint.receiptRefs,
226
+ gitPullRequest: false,
227
+ });
228
+ }
229
+ export function validateStoryRollback(receipt) {
230
+ const errors = [];
231
+ if (!isSha(receipt.originalBaseSha) || !isSha(receipt.originalHeadSha))
232
+ errors.push('rollback-invalid-original-range');
233
+ if (receipt.revertCommits.length === 0 || receipt.revertCommits.some((sha) => !isSha(sha)))
234
+ errors.push('rollback-revert-commits-required');
235
+ if (receipt.preservesLaterCommits !== true)
236
+ errors.push('rollback-must-preserve-later-commits');
237
+ if (receipt.historyRewrite !== false)
238
+ errors.push('rollback-history-rewrite-forbidden');
239
+ return Object.freeze([...new Set(errors)]);
240
+ }
241
+ export function assessEpicIntegrationReadiness(resolution, expectedStoryIds, checkpoints) {
242
+ const reasons = [];
243
+ if (resolution.mode !== 'epic')
244
+ reasons.push('epic-integration-not-applicable-to-story-mode');
245
+ if (!nonEmpty(resolution.executionBranch) || !nonEmpty(resolution.originBranch))
246
+ reasons.push('epic-branch-boundary-incomplete');
247
+ const byStory = new Map();
248
+ for (const checkpoint of checkpoints) {
249
+ if (!expectedStoryIds.includes(checkpoint.storyId))
250
+ reasons.push(`unexpected-story-checkpoint:${checkpoint.storyId}`);
251
+ if (byStory.has(checkpoint.storyId))
252
+ reasons.push(`duplicate-story-checkpoint:${checkpoint.storyId}`);
253
+ else
254
+ byStory.set(checkpoint.storyId, checkpoint);
255
+ }
256
+ for (const storyId of expectedStoryIds) {
257
+ const checkpoint = byStory.get(storyId);
258
+ if (!checkpoint)
259
+ reasons.push(`missing-story-checkpoint:${storyId}`);
260
+ else {
261
+ const validationErrors = validateStoryCheckpoint(checkpoint, resolution);
262
+ if (validationErrors.length > 0)
263
+ reasons.push(`invalid-story-checkpoint:${storyId}:${validationErrors.join(',')}`);
264
+ else if (checkpoint.qaVerdict !== 'passed' || checkpoint.reviewVerdict !== 'approved')
265
+ reasons.push(`unaccepted-story-checkpoint:${storyId}`);
266
+ }
267
+ }
268
+ return Object.freeze({
269
+ ready: reasons.length === 0,
270
+ gitPullRequestOwner: 'epic',
271
+ reasonCodes: Object.freeze(reasons),
272
+ checkpointStoryIds: Object.freeze(checkpoints.map((item) => item.storyId)),
273
+ });
274
+ }
275
+ function hasLegacyStoryGitProgress(story) {
276
+ return nonEmpty(story.branch_name) ||
277
+ (typeof story.pr_number === 'number' && story.pr_number > 0) ||
278
+ (story.steps_completed ?? []).some((step) => LEGACY_INTEGRATION_STEPS.has(step) && !(step === 'step-c-11-review-pr' && story.checkpoint));
279
+ }
280
+ /**
281
+ * An explicit epic boundary may coexist with steps written by older runners.
282
+ * Those step labels are not physical proof of a story-owned branch or PR. Only
283
+ * a distinct branch/ref, a positive story PR, C12, or a checkpoint bound to a
284
+ * different branch can override the immutable epic boundary. Malformed PR
285
+ * metadata at a PR-producing step remains fail-closed and publicly diagnosable.
286
+ */
287
+ function classifyRecordedEpicStoryGitEvidence(epic, stories) {
288
+ let result = 'none';
289
+ const executionBranch = nonEmpty(epic.execution_branch) ? epic.execution_branch.trim() : null;
290
+ for (const story of stories) {
291
+ const storyBranch = nonEmpty(story.branch_name) ? story.branch_name.trim() : null;
292
+ const checkpointBranch = nonEmpty(story.checkpoint?.branch) ? story.checkpoint.branch.trim() : null;
293
+ const steps = new Set(story.steps_completed ?? []);
294
+ if ((storyBranch && storyBranch !== executionBranch) ||
295
+ (checkpointBranch && checkpointBranch !== executionBranch) ||
296
+ (typeof story.pr_number === 'number' && story.pr_number > 0) ||
297
+ steps.has('step-c-12-merge-pr')) {
298
+ return 'strong';
299
+ }
300
+ const hasPrProducingStep = steps.has('step-c-10-create-pr');
301
+ const hasMalformedPrMarker = story.pr_number !== null && story.pr_number !== undefined &&
302
+ !(typeof story.pr_number === 'number' && story.pr_number > 0);
303
+ if (hasPrProducingStep && hasMalformedPrMarker)
304
+ result = 'ambiguous';
305
+ }
306
+ return result;
307
+ }
308
+ function hasAnyStoryProgress(story) {
309
+ return nonEmpty(story.branch_name) ||
310
+ (typeof story.pr_number === 'number' && story.pr_number > 0) ||
311
+ (story.steps_completed ?? []).length > 0 ||
312
+ Boolean(story.checkpoint);
313
+ }
314
+ function hasEpicGitProgress(epic, stories) {
315
+ return nonEmpty(epic.execution_branch) ||
316
+ Boolean(epic.branch_lease) ||
317
+ (typeof epic.pr_number === 'number' && epic.pr_number > 0) ||
318
+ stories.some((story) => Boolean(story.checkpoint));
319
+ }
320
+ function resolution(mode, source, immutable, epic, reasonCodes) {
321
+ return Object.freeze({
322
+ schemaVersion: 1,
323
+ epicId: epic.id,
324
+ mode,
325
+ source,
326
+ immutable,
327
+ ...(nonEmpty(epic.execution_branch) ? { executionBranch: epic.execution_branch } : {}),
328
+ ...(nonEmpty(epic.origin_branch) ? { originBranch: epic.origin_branch } : {}),
329
+ reasonCodes: Object.freeze([...reasonCodes]),
330
+ });
331
+ }
332
+ function nonEmpty(value) {
333
+ return typeof value === 'string' && value.trim().length > 0;
334
+ }
335
+ function isSha(value) {
336
+ return /^[0-9a-f]{7,64}$/i.test(value);
337
+ }
338
+ function isHash(value) {
339
+ return /^[0-9a-f]{64}$/i.test(value);
340
+ }
341
+ function sameStrings(left, right) {
342
+ return left.length === right.length && left.every((value, index) => value === right[index]);
343
+ }
@@ -1,4 +1,4 @@
1
- # 🧠 Neocortex v4.60.27 | OrNexus Team
1
+ # 🧠 Neocortex v4.60.29 | OrNexus Team
2
2
 
3
3
  This project uses Neocortex, a Development Orchestrator.
4
4
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.27 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.29 | OrNexus Team"
4
4
  ---
5
5
 
6
6
  <!--
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex Root Agent'
5
5
  title: 'Development Orchestrator (Root)'
6
6
  icon: '>'
7
- version: '4.60.27'
7
+ version: '4.60.29'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex-root
3
- description: "🧠 Neocortex Root Agent v4.60.27 | OrNexus Team"
3
+ description: "🧠 Neocortex Root Agent v4.60.29 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -108,7 +108,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
108
108
  ┌────────────────────────────────────────────────────────────┐
109
109
  │ │
110
110
  │ ####### N E O C O R T E X │
111
- │ ### ######## v4.60.27
111
+ │ ### ######## v4.60.29
112
112
  │ ######### ##### │
113
113
  │ ## ############## Development Orchestrator │
114
114
  │ ## ### ###### ## OrNexus Team │
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex'
5
5
  title: 'Development Orchestrator'
6
6
  icon: '>'
7
- version: '4.60.27'
7
+ version: '4.60.29'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.27 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.29 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  permissionMode: bypassPermissions
@@ -104,7 +104,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
104
104
  ┌────────────────────────────────────────────────────────────┐
105
105
  │ │
106
106
  │ ####### N E O C O R T E X │
107
- │ ### ######## v4.60.27
107
+ │ ### ######## v4.60.29
108
108
  │ ######### ##### │
109
109
  │ ## ############## Development Orchestrator │
110
110
  │ ## ### ###### ## OrNexus Team │
@@ -28,7 +28,7 @@ Codex built-in commands or actions.
28
28
 
29
29
  <!-- END: Plugin Conflict Prevention -->
30
30
 
31
- # Neocortex v4.60.27 | OrNexus Team
31
+ # Neocortex v4.60.29 | OrNexus Team
32
32
 
33
33
  You are a Development Orchestrator. All orchestration logic is delivered by the remote Neocortex server.
34
34
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.27 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.29 | OrNexus Team"
4
4
  model: inherit
5
5
  readonly: false
6
6
  is_background: false
@@ -64,7 +64,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
64
64
  ┌────────────────────────────────────────────────────────────┐
65
65
  │ │
66
66
  │ ####### N E O C O R T E X │
67
- │ ### ######## v4.60.27
67
+ │ ### ######## v4.60.29
68
68
  │ ######### ##### │
69
69
  │ ## ############## Development Orchestrator │
70
70
  │ ## ### ###### ## OrNexus Team │
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex-root
3
- description: "🧠 Neocortex v4.60.27 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.29 | OrNexus Team"
4
4
  kind: local
5
5
  tools:
6
6
  # File operations (Gemini CLI built-ins)
@@ -62,7 +62,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
62
62
  ┌────────────────────────────────────────────────────────────┐
63
63
  │ │
64
64
  │ ####### N E O C O R T E X │
65
- │ ### ######## v4.60.27
65
+ │ ### ######## v4.60.29
66
66
  │ ######### ##### │
67
67
  │ ## ############## Development Orchestrator │
68
68
  │ ## ### ###### ## OrNexus Team │
@@ -58,7 +58,7 @@ explicit server opt-in rather than a local assumption.
58
58
  ┌────────────────────────────────────────────────────────────┐
59
59
  │ │
60
60
  │ ####### N E O C O R T E X │
61
- │ ### ######## v4.60.27
61
+ │ ### ######## v4.60.29
62
62
  │ ######### ##### │
63
63
  │ ## ############## Development Orchestrator │
64
64
  │ ## ### ###### ## OrNexus Team │
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "neocortex"
3
- description: "Neocortex v4.60.27 | OrNexus Team"
3
+ description: "Neocortex v4.60.29 | OrNexus Team"
4
4
  tools:
5
5
  # Read / Edit (built-in tool sets)
6
6
  - read
@@ -68,7 +68,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
68
68
  ┌────────────────────────────────────────────────────────────┐
69
69
  │ │
70
70
  │ ####### N E O C O R T E X │
71
- │ ### ######## v4.60.27
71
+ │ ### ######## v4.60.29
72
72
  │ ######### ##### │
73
73
  │ ## ############## Development Orchestrator │
74
74
  │ ## ### ###### ## OrNexus Team │