@nexus-cortex/server 4.124.31 → 4.124.33
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/.cortex/inventory +409 -0
- package/.cortex/orient +60 -13
- package/package.json +3 -3
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Canonical workspace inventory (CORTEX_INVENTORY=1, dark, 2026-09-29). Vendored by prepack to <pkg>/.cortex/inventory beside the orient
|
|
3
|
+
# scaffold. ONE mechanical, read-only picture of the task workspace that feeds BOTH the action model (orient prints it) and the steering models
|
|
4
|
+
# (the lift planner / EndTurn judge environment report). Evidence (r-orient-deficiencies-2026-09-29, r-steering-input-truncation-2026-09-29):
|
|
5
|
+
# flaky MiMo / TB4.0 / TB2.1 pairs diverge in the first 30 actions on workspace knowledge — the checker or contract not surfaced, a deep or
|
|
6
|
+
# out-of-workdir asset never shown (the lift plan names an asset only when orient showed it: TB4 0/6 vs 4/4), a listed file whose ROLE was not
|
|
7
|
+
# understood (a raw weights blob, a comma-decimal data file, a .dat that is a ZIP), the site-packages copy shadowing the workspace copy, a
|
|
8
|
+
# declared dependency silently missing.
|
|
9
|
+
# RULES: read-only (writes nothing, anywhere); no secrets (the task's own env comes from /proc/1/environ, harness vars and anything named
|
|
10
|
+
# *KEY*/*TOKEN*/*SECRET*/*PASSWORD* are dropped/redacted — transcripts are banked); priority sections are never capped; every capped section
|
|
11
|
+
# ends with "… N more … — <exact command>" so nothing is silently truncated. Always exits 0.
|
|
12
|
+
W="${1:-$(pwd)}"
|
|
13
|
+
cd "$W" 2>/dev/null || { echo "== WORKSPACE INVENTORY: $W (not accessible) =="; exit 0; }
|
|
14
|
+
PY=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
|
|
15
|
+
if [ -z "$PY" ]; then
|
|
16
|
+
# No interpreter: the shell-only inventory (structure + roles by name + env + services). Still no silent truncation.
|
|
17
|
+
echo "== WORKSPACE INVENTORY: $W (shell-only: no python on this box) =="
|
|
18
|
+
PRUNE='( -name .git -o -name node_modules -o -name __pycache__ -o -name .venv -o -name venv -o -name .cortex -o -name .cache ) -prune -o'
|
|
19
|
+
# shellcheck disable=SC2086
|
|
20
|
+
N=$(find . $PRUNE -type f -print 2>/dev/null | wc -l | tr -d ' ')
|
|
21
|
+
echo "files: $N (excluding .git node_modules __pycache__ venvs .cortex .cache)"
|
|
22
|
+
echo "-- directories (file counts) --"
|
|
23
|
+
# shellcheck disable=SC2086
|
|
24
|
+
find . -maxdepth 3 $PRUNE -type d -print 2>/dev/null | sed 's#^\./##' | grep -v '^\.$' | sort | head -60 | while read -r d; do
|
|
25
|
+
printf ' %s/ (%s)\n' "$d" "$(find "$d" -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ')"; done
|
|
26
|
+
echo "-- files at depth <= 3 --"
|
|
27
|
+
# shellcheck disable=SC2086
|
|
28
|
+
L=$(find . -maxdepth 3 $PRUNE -type f -print 2>/dev/null | sed 's#^\./##' | sort)
|
|
29
|
+
C=$(printf '%s\n' "$L" | grep -c . )
|
|
30
|
+
printf '%s\n' "$L" | head -150 | sed 's/^/ /'
|
|
31
|
+
[ "$C" -gt 150 ] && echo " … $((C-150)) more files at depth <= 3 not shown — list all: find . -type f -not -path './.git/*'"
|
|
32
|
+
for d in /shared /data /mnt /srv /workspace /input /inputs /output /outputs; do
|
|
33
|
+
[ -d "$d" ] && [ "$d" != "$W" ] && [ -n "$(ls -A "$d" 2>/dev/null)" ] && echo "-- outside the workdir: $d ($(find "$d" -maxdepth 4 -type f 2>/dev/null | head -2000 | wc -l | tr -d ' ') files, first 2000 / depth 4 counted) — list: find $d -type f"
|
|
34
|
+
done
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
exec "$PY" - "$W" <<'PYINV'
|
|
38
|
+
import ast, json, os, re, subprocess, sys
|
|
39
|
+
|
|
40
|
+
W = os.path.abspath(sys.argv[1])
|
|
41
|
+
SKIP_DIRS = {'.git', 'node_modules', '__pycache__', '.venv', 'venv', '.cortex', '.cache', '.pytest_cache', '.mypy_cache', '.tox', '.npm',
|
|
42
|
+
'.gradle', '.m2', 'site-packages', 'dist-packages', '.idea', '.vscode', '.addon-tools'}
|
|
43
|
+
MAX_WALK = 60000
|
|
44
|
+
# Output is bucketed per section and emitted DECISIVE-FIRST (2026-09-29): the model reads orient through `| head -50/-100` in ~93% of sessions
|
|
45
|
+
# (504/541, .bench/mimo/boot-prompt-audit.py) and cut the inventory in 8/17 cw sessions — so what decides a task (how it is checked, which
|
|
46
|
+
# copy of the code runs, missing deps, services, data outside the workdir) comes before the long per-file listing. Computation order is unchanged.
|
|
47
|
+
SECTIONS, CUR = {}, ['header']
|
|
48
|
+
EMIT = ['header', 'checked', 'python', 'node', 'services', 'outside', 'structure', 'files', 'env']
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def sec(name):
|
|
52
|
+
CUR[0] = name
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def p(line):
|
|
56
|
+
SECTIONS.setdefault(CUR[0], []).append(line)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def rel(x):
|
|
60
|
+
return os.path.relpath(x, W)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def more(n, what, cmd):
|
|
64
|
+
return f' … {n} more {what} not shown — {cmd}'
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------- walk (bounded; never follows symlinked dirs)
|
|
68
|
+
files, dirs = [], {}
|
|
69
|
+
walked = 0
|
|
70
|
+
truncated_walk = False
|
|
71
|
+
for dp, dns, fns in os.walk(W, topdown=True, followlinks=False):
|
|
72
|
+
dns[:] = sorted(d for d in dns if d not in SKIP_DIRS and not d.endswith('.egg-info'))
|
|
73
|
+
r = rel(dp)
|
|
74
|
+
dirs[r] = len(fns)
|
|
75
|
+
for f in sorted(fns):
|
|
76
|
+
fp = os.path.join(dp, f)
|
|
77
|
+
try:
|
|
78
|
+
st = os.lstat(fp)
|
|
79
|
+
except OSError:
|
|
80
|
+
continue
|
|
81
|
+
files.append((rel(fp), st.st_size))
|
|
82
|
+
walked += 1
|
|
83
|
+
if walked >= MAX_WALK:
|
|
84
|
+
truncated_walk = True
|
|
85
|
+
break
|
|
86
|
+
if truncated_walk:
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
# ---------------------------------------------------------------- role classification + peeks
|
|
90
|
+
SCRIPT = re.compile(r'\.(py|sh|bash|js|mjs|cjs|ts|tsx|rb|pl|go|rs|c|cc|cpp|h|hpp|java|kt|r|jl|lua|php|swift|scala|m)$', re.I)
|
|
91
|
+
DOC = re.compile(r'\.(md|rst|txt|adoc|pdf|html?|docx?|odt)$', re.I)
|
|
92
|
+
DATA = re.compile(r'\.(csv|tsv|jsonl|ndjson|json|parquet|feather|arrow|npy|npz|pkl|pickle|h5|hdf5|db|sqlite3?|xlsx?|xml|ya?ml|toml|ini|cfg|'
|
|
93
|
+
r'dat|bin|raw|gz|zip|tar|tgz|bz2|xz|7z|fa|fasta|fastq|bam|sam|vcf|bed|gff3?|pdb|cif|wav|mp3|flac|png|jpe?g|gif|bmp|tiff?|svg|'
|
|
94
|
+
r'stl|step|stp|obj|ply|glb|gltf|ckpt|pt|pth|safetensors|onnx|gguf|mat|nc|log|ttf|otf|woff2?)$', re.I)
|
|
95
|
+
CHECKER = re.compile(r'(check|verif|validat|grade|grader|probe|evaluat|eval|scor|judge|assert|audit|regression|smoke|harness|contract_runner|'
|
|
96
|
+
r'run_tests?|run_[a-z0-9_-]+|workflow|diagnos|benchmark|bench)[^/]*\.(py|sh|js|ts|mjs)$', re.I)
|
|
97
|
+
CONTRACT = re.compile(r'(contract|schema|spec|expected|golden|reference|cases|fixture|sample_output|example_output|output_format|interface|'
|
|
98
|
+
r'requirements?_spec|acceptance)[^/]*\.(json|ya?ml|toml|md|txt|csv|jsonl)$|(^|/)(CONTRACT|SPEC|REPAIR_CONTRACT|'
|
|
99
|
+
r'ACCEPTANCE)[^/]*$', re.I)
|
|
100
|
+
TESTF = re.compile(r'(^|/)(tests?|spec|__tests__)/|(^|/)test_[^/]+$|_test\.[a-z]+$|\.test\.[a-z]+$|\.spec\.[a-z]+$', re.I)
|
|
101
|
+
MANIFEST = re.compile(r'(^|/)(requirements[^/]*\.txt|pyproject\.toml|setup\.py|setup\.cfg|Pipfile|environment\.ya?ml|package\.json|Cargo\.toml|'
|
|
102
|
+
r'go\.mod|Gemfile|pom\.xml|build\.gradle|CMakeLists\.txt|Makefile|Dockerfile|docker-compose[^/]*\.ya?ml|tox\.ini|pytest\.ini|'
|
|
103
|
+
r'conftest\.py|\.env\.example)$', re.I)
|
|
104
|
+
VENDOR = re.compile(r'(^|/)(vendor|third_party|external|deps|_offline_deps|offline_deps|runtime_compat|wheels)/', re.I)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def role(path):
|
|
108
|
+
if CHECKER.search(path) and not TESTF.search(path): return 'checker/runner'
|
|
109
|
+
if CONTRACT.search(path): return 'contract/spec'
|
|
110
|
+
if MANIFEST.search(path): return 'manifest/config'
|
|
111
|
+
if TESTF.search(path): return 'test'
|
|
112
|
+
if SCRIPT.search(path): return 'source'
|
|
113
|
+
if DOC.search(path) or re.search(r'(^|/)(README|NOTES|INSTRUCTIONS|TODO|CHANGELOG|LICENSE)[^/]*$', path, re.I): return 'doc'
|
|
114
|
+
if DATA.search(path): return 'data'
|
|
115
|
+
return 'other'
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def head_bytes(path, n=4096):
|
|
119
|
+
try:
|
|
120
|
+
with open(os.path.join(W, path), 'rb') as fh:
|
|
121
|
+
return fh.read(n)
|
|
122
|
+
except OSError:
|
|
123
|
+
return b''
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
MAGIC = [(b'PK\x03\x04', 'zip archive'), (b'\x1f\x8b', 'gzip'), (b'BZh', 'bzip2'), (b'\xfd7zXZ', 'xz'), (b'7z\xbc\xaf', '7z'),
|
|
127
|
+
(b'\x89PNG', 'png image'), (b'\xff\xd8\xff', 'jpeg image'), (b'GIF8', 'gif image'), (b'%PDF', 'pdf'), (b'SQLite format 3', 'sqlite db'),
|
|
128
|
+
(b'\x7fELF', 'ELF binary'), (b'\x93NUMPY', 'numpy array'), (b'\x80\x02', 'pickle'), (b'\x80\x04', 'pickle'), (b'\x80\x05', 'pickle'),
|
|
129
|
+
(b'RIFF', 'riff (wav/avi)'), (b'ustar', 'tar')]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def human(n):
|
|
133
|
+
for u in ('B', 'KB', 'MB', 'GB'):
|
|
134
|
+
if n < 1024 or u == 'GB':
|
|
135
|
+
return f'{n:.0f}{u}' if u == 'B' else f'{n:.1f}{u}'
|
|
136
|
+
n /= 1024
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def peek(path, size, rl):
|
|
140
|
+
b = head_bytes(path)
|
|
141
|
+
if not b:
|
|
142
|
+
return 'empty' if size == 0 else ''
|
|
143
|
+
for sig, name in MAGIC:
|
|
144
|
+
if b.startswith(sig) or (sig == b'ustar' and b[257:262] == b'ustar'):
|
|
145
|
+
ext = os.path.splitext(path)[1].lower()
|
|
146
|
+
expect = {'.zip': 'zip', '.gz': 'gzip', '.png': 'png', '.jpg': 'jpeg', '.jpeg': 'jpeg', '.pdf': 'pdf', '.db': 'sqlite',
|
|
147
|
+
'.sqlite': 'sqlite', '.npy': 'numpy', '.pkl': 'pickle', '.tar': 'tar', '.xz': 'xz', '.bz2': 'bzip2', '.wav': 'riff'}
|
|
148
|
+
mism = ext and ext in expect and expect[ext] not in name
|
|
149
|
+
unexpected = ext and ext not in expect and name not in ('ELF binary',)
|
|
150
|
+
tag = name + (f' (NOTE: content is {name}, not what "{ext}" suggests)' if (mism or unexpected) else '')
|
|
151
|
+
return tag
|
|
152
|
+
try:
|
|
153
|
+
t = b.decode('utf-8')
|
|
154
|
+
except UnicodeDecodeError:
|
|
155
|
+
nz = sum(1 for c in b[:512] if c == 0)
|
|
156
|
+
return f'binary ({nz} NUL bytes in first 512; e.g. raw array / weights / packed data)'
|
|
157
|
+
lines = t.splitlines()
|
|
158
|
+
if rl == 'data' or re.search(r'\.(csv|tsv|dat|txt)$', path, re.I):
|
|
159
|
+
first = next((l for l in lines if l.strip()), '')[:160]
|
|
160
|
+
body = [l for l in lines[:12] if l.strip()][1:6]
|
|
161
|
+
note = ''
|
|
162
|
+
if any(re.search(r'\d,\d', l) and ';' in l for l in body): note = ' (NOTE: ";"-separated with comma decimals, e.g. ' + body[0][:40] + ')'
|
|
163
|
+
elif any(re.match(r'^\s*-?\d+,\d+[\s\t]+-?\d+,\d+', l) for l in body): note = ' (NOTE: comma decimals, e.g. ' + body[0][:40] + ')'
|
|
164
|
+
if path.lower().endswith(('.json',)) or first.lstrip().startswith(('{', '[')):
|
|
165
|
+
try:
|
|
166
|
+
with open(os.path.join(W, path), encoding='utf-8') as fh:
|
|
167
|
+
obj = json.load(fh) if size < 2_000_000 else None
|
|
168
|
+
if isinstance(obj, dict): return 'json object, keys: ' + ', '.join(list(obj)[:14]) + (' …' if len(obj) > 14 else '')
|
|
169
|
+
if isinstance(obj, list): return f'json array[{len(obj)}]' + (', item keys: ' + ', '.join(list(obj[0])[:12]) if obj and isinstance(obj[0], dict) else '')
|
|
170
|
+
except Exception:
|
|
171
|
+
pass
|
|
172
|
+
return f'first line: {first}{note}' if first else 'text'
|
|
173
|
+
if rl in ('source', 'checker/runner', 'test'):
|
|
174
|
+
if path.endswith('.py'):
|
|
175
|
+
try:
|
|
176
|
+
src = open(os.path.join(W, path), encoding='utf-8', errors='replace').read() if size < 2_000_000 else t
|
|
177
|
+
tree = ast.parse(src)
|
|
178
|
+
defs = [n.name for n in tree.body if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef))]
|
|
179
|
+
main = '__main__' in src
|
|
180
|
+
return (('defines: ' + ', '.join(defs[:10]) + (' …' if len(defs) > 10 else '')) if defs else 'no top-level defs') + \
|
|
181
|
+
(' | runnable (__main__)' if main else '') + f' | {src.count(chr(10))} lines'
|
|
182
|
+
except Exception:
|
|
183
|
+
pass
|
|
184
|
+
defs = re.findall(r'^(?:export\s+)?(?:async\s+)?(?:function|class|def|fn|func|interface|struct)\s+([A-Za-z_][\w]*)', t, re.M)
|
|
185
|
+
return ('defines: ' + ', '.join(defs[:10]) if defs else f'{len(lines)}+ lines')
|
|
186
|
+
if rl == 'doc':
|
|
187
|
+
first = next((l.strip('# ').strip() for l in lines if l.strip()), '')
|
|
188
|
+
return f'"{first[:120]}"'
|
|
189
|
+
return ''
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
classified = [(f, s, role(f)) for f, s in files]
|
|
193
|
+
by_role = {}
|
|
194
|
+
for f, s, r in classified:
|
|
195
|
+
by_role.setdefault(r, []).append((f, s))
|
|
196
|
+
|
|
197
|
+
# ---------------------------------------------------------------- header
|
|
198
|
+
p(f'== WORKSPACE INVENTORY: {W} ==')
|
|
199
|
+
p(f'{len(files)} files in {len(dirs)} dirs (excluded: ' + ', '.join(sorted(SKIP_DIRS)[:8]) + ' …)' +
|
|
200
|
+
(f' — WALK STOPPED at {MAX_WALK} files; the rest is not listed — find . -type f | wc -l' if truncated_walk else ''))
|
|
201
|
+
counts = ', '.join(f'{r} {len(v)}' for r, v in sorted(by_role.items(), key=lambda kv: -len(kv[1])))
|
|
202
|
+
p('by role: ' + counts)
|
|
203
|
+
|
|
204
|
+
# ---------------------------------------------------------------- 1. verification + contracts (PRIORITY — never capped)
|
|
205
|
+
sec('checked')
|
|
206
|
+
chk = by_role.get('checker/runner', []); con = by_role.get('contract/spec', [])
|
|
207
|
+
if chk or con:
|
|
208
|
+
p('-- HOW THIS TASK IS CHECKED (task-shipped checkers/runners and contracts — read these before building) --')
|
|
209
|
+
for f, s in chk:
|
|
210
|
+
src = head_bytes(f, 200_000).decode('utf-8', 'replace')
|
|
211
|
+
usage = next((l.strip() for l in src.splitlines() if re.search(r'usage|^ *Run:|add_argument|sys\.argv|getopts', l, re.I)), '')
|
|
212
|
+
writes = sorted(set(re.findall(r'["\']([\w./-]+\.(?:json|jsonl|csv|txt|md|yaml|yml|html|png))["\']', src)))[:6]
|
|
213
|
+
consts = sorted(set(re.findall(r'["\']?(schema[_-]?version|SCHEMA[_A-Z]*|output_schema[_a-z]*)["\']?\s*[:=]\s*["\']?([\w.:-]+)', src)))[:4]
|
|
214
|
+
line = f' [checker] {f} ({human(s)})'
|
|
215
|
+
if VENDOR.search(f): line += ' — inside a vendored project'
|
|
216
|
+
p(line)
|
|
217
|
+
if usage: p(f' usage: {usage[:160]}')
|
|
218
|
+
if writes: p(' references: ' + ', '.join(writes))
|
|
219
|
+
if consts: p(' constants: ' + ', '.join(f'{a}={b}' for a, b in consts))
|
|
220
|
+
for f, s in con:
|
|
221
|
+
p(f' [contract] {f} ({human(s)}) — {peek(f, s, "data" if not f.lower().endswith(".md") else "doc")}'[:260])
|
|
222
|
+
tests = sorted({os.path.dirname(f) for f, _ in by_role.get('test', []) if os.path.dirname(f)})
|
|
223
|
+
if tests:
|
|
224
|
+
shown = tests[:12]
|
|
225
|
+
p(' test dirs: ' + ', '.join(shown) + (f' (+{len(tests)-12} more — find . -type d -name "test*")' if len(tests) > 12 else ''))
|
|
226
|
+
|
|
227
|
+
# ---------------------------------------------------------------- 2. structure: every dir with counts (capped with marker)
|
|
228
|
+
sec('structure')
|
|
229
|
+
p('-- STRUCTURE (dir: files directly inside) --')
|
|
230
|
+
dl = sorted(d for d in dirs if d != '.')
|
|
231
|
+
top = [d for d in dl if d.count('/') <= 1]
|
|
232
|
+
for d in top[:60]:
|
|
233
|
+
sub = sum(1 for x in dl if x.startswith(d + '/'))
|
|
234
|
+
p(f' {d}/ ({dirs[d]} files' + (f', {sub} subdirs' if sub else '') + ')')
|
|
235
|
+
if len(top) > 60:
|
|
236
|
+
p(more(len(top) - 60, 'directories at depth <= 2', 'find . -maxdepth 2 -type d'))
|
|
237
|
+
deep = [d for d in dl if d.count('/') > 1]
|
|
238
|
+
if deep:
|
|
239
|
+
p(f' ({len(deep)} deeper directories — find . -mindepth 3 -type d)')
|
|
240
|
+
|
|
241
|
+
# ---------------------------------------------------------------- 3. files by role with a peek (priority roles in full, bulk capped)
|
|
242
|
+
sec('files')
|
|
243
|
+
CAPS = {'source': 40, 'doc': 30, 'data': 40, 'manifest/config': 30, 'test': 20, 'other': 20}
|
|
244
|
+
ORDER = ['doc', 'manifest/config', 'source', 'data', 'test', 'other']
|
|
245
|
+
for r in ORDER:
|
|
246
|
+
items = by_role.get(r, [])
|
|
247
|
+
if not items: continue
|
|
248
|
+
# task files before vendored ones; shallow before deep
|
|
249
|
+
items = sorted(items, key=lambda x: (bool(VENDOR.search(x[0])), x[0].count('/'), x[0]))
|
|
250
|
+
cap = CAPS[r]
|
|
251
|
+
p(f'-- {r.upper()} ({len(items)}) --')
|
|
252
|
+
for f, s in items[:cap]:
|
|
253
|
+
pk = peek(f, s, r) if r in ('doc', 'data', 'source', 'other', 'manifest/config') else ''
|
|
254
|
+
p(f' {f} ({human(s)})' + (f' — {pk}' if pk else ''))
|
|
255
|
+
if len(items) > cap:
|
|
256
|
+
vend = sum(1 for f, _ in items[cap:] if VENDOR.search(f))
|
|
257
|
+
p(more(len(items) - cap, f'{r} files' + (f' ({vend} in vendored trees)' if vend else ''),
|
|
258
|
+
f'list: find . -type f | grep -v -e .git/ -e node_modules (role here = {r})'))
|
|
259
|
+
|
|
260
|
+
# ---------------------------------------------------------------- 4. python: which interpreter, which copy of the code runs, missing deps
|
|
261
|
+
sec('python')
|
|
262
|
+
def run(cmd, timeout=20):
|
|
263
|
+
try:
|
|
264
|
+
r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, cwd=W)
|
|
265
|
+
return (r.stdout or '') + (r.stderr or '')
|
|
266
|
+
except Exception as e:
|
|
267
|
+
return ''
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
p('-- PYTHON --')
|
|
271
|
+
p(f' interpreter: {sys.executable} ({sys.version.split()[0]})' + (f' | VIRTUAL_ENV={os.environ.get("VIRTUAL_ENV")}' if os.environ.get('VIRTUAL_ENV') else ''))
|
|
272
|
+
pkgs = []
|
|
273
|
+
for d in sorted(dirs):
|
|
274
|
+
parts = d.split('/')
|
|
275
|
+
if d == '.' or len(parts) > 4: continue
|
|
276
|
+
if os.path.isfile(os.path.join(W, d, '__init__.py')) and not os.path.isfile(os.path.join(W, os.path.dirname(d) or '.', '__init__.py')):
|
|
277
|
+
pkgs.append(d)
|
|
278
|
+
pkgs = [x for x in pkgs if not TESTF.search(x + '/')][:12]
|
|
279
|
+
for d in pkgs:
|
|
280
|
+
name = os.path.basename(d); parent = os.path.dirname(d) or '.'
|
|
281
|
+
res = run([sys.executable, '-c', f'import {name},os;print(os.path.abspath({name}.__file__))'], 20).strip().splitlines()
|
|
282
|
+
where = res[-1] if res else ''
|
|
283
|
+
ws_copy = os.path.join(W, d)
|
|
284
|
+
if where.startswith(ws_copy):
|
|
285
|
+
p(f' import {name} → the workspace copy ({d}/)')
|
|
286
|
+
elif where.startswith('/'):
|
|
287
|
+
p(f' import {name} → {where} ⚠ NOT the workspace copy ({d}/) — run with PYTHONPATH={os.path.join(W, parent)} to use/test the workspace code')
|
|
288
|
+
else:
|
|
289
|
+
err = next((l for l in res if 'Error' in l), 'fails')
|
|
290
|
+
p(f' import {name} (workspace {d}/) → {err[:120]} from {W}; with PYTHONPATH={os.path.join(W, parent)} it resolves to the workspace copy')
|
|
291
|
+
extra = sorted(d for d in dirs if re.search(r'(^|/)(_?offline_deps|runtime_compat|wheels|vendor_deps)$', d, re.I))[:6]
|
|
292
|
+
if extra:
|
|
293
|
+
p(' dependency dirs shipped with the task: ' + ', '.join(extra) + ' (add to PYTHONPATH / pip install --no-index --find-links as appropriate)')
|
|
294
|
+
# declared vs installed
|
|
295
|
+
declared = []
|
|
296
|
+
for f, _ in by_role.get('manifest/config', []):
|
|
297
|
+
if VENDOR.search(f) and f.count('/') > 2: continue
|
|
298
|
+
b = os.path.basename(f).lower()
|
|
299
|
+
try:
|
|
300
|
+
txt = open(os.path.join(W, f), encoding='utf-8', errors='replace').read()
|
|
301
|
+
except OSError:
|
|
302
|
+
continue
|
|
303
|
+
if b.startswith('requirements') and b.endswith('.txt'):
|
|
304
|
+
declared += [(re.split(r'[<>=!~\[; ]', l.strip())[0], f) for l in txt.splitlines() if l.strip() and not l.strip().startswith(('#', '-'))]
|
|
305
|
+
elif b == 'pyproject.toml':
|
|
306
|
+
m = re.search(r'dependencies\s*=\s*\[(.*?)\]', txt, re.S)
|
|
307
|
+
if m: declared += [(re.split(r'[<>=!~\[; ]', x.strip().strip('"\''))[0], f) for x in m.group(1).split(',') if x.strip().strip('"\'')]
|
|
308
|
+
missing = []
|
|
309
|
+
if declared:
|
|
310
|
+
try:
|
|
311
|
+
from importlib import metadata as md
|
|
312
|
+
have = {re.sub(r'[-_.]+', '-', (d.metadata['Name'] or '').lower()) for d in md.distributions()}
|
|
313
|
+
except Exception:
|
|
314
|
+
have = set()
|
|
315
|
+
for name, src in declared:
|
|
316
|
+
if name and re.sub(r'[-_.]+', '-', name.lower()) not in have:
|
|
317
|
+
missing.append(f'{name} ({src})')
|
|
318
|
+
missing = sorted(set(missing))
|
|
319
|
+
if missing:
|
|
320
|
+
p(' declared but NOT installed: ' + ', '.join(missing[:30]) + (f' … +{len(missing)-30} more' if len(missing) > 30 else ''))
|
|
321
|
+
else:
|
|
322
|
+
p(f' all {len(declared)} declared python dependencies are installed')
|
|
323
|
+
|
|
324
|
+
# ---------------------------------------------------------------- 5. node
|
|
325
|
+
sec('node')
|
|
326
|
+
pj = [f for f, _ in by_role.get('manifest/config', []) if os.path.basename(f) == 'package.json' and f.count('/') <= 2 and 'node_modules' not in f]
|
|
327
|
+
for f in pj[:3]:
|
|
328
|
+
try:
|
|
329
|
+
o = json.load(open(os.path.join(W, f)))
|
|
330
|
+
except Exception:
|
|
331
|
+
continue
|
|
332
|
+
deps = list((o.get('dependencies') or {})) + list((o.get('devDependencies') or {}))
|
|
333
|
+
nm = os.path.join(W, os.path.dirname(f), 'node_modules')
|
|
334
|
+
miss = [d for d in deps if not os.path.isdir(os.path.join(nm, d))]
|
|
335
|
+
scripts = list((o.get('scripts') or {}))
|
|
336
|
+
p(f'-- NODE {f}: scripts: ' + (', '.join(scripts[:12]) or 'none') + f' | {len(deps)} deps' +
|
|
337
|
+
(f', NOT installed: {", ".join(miss[:20])}' + (' …' if len(miss) > 20 else '') if miss else (', node_modules present' if os.path.isdir(nm) else ', no node_modules')))
|
|
338
|
+
|
|
339
|
+
# ---------------------------------------------------------------- 6. task environment (from the container's own init env; secrets redacted)
|
|
340
|
+
sec('env')
|
|
341
|
+
BOILER = {'PATH', 'HOME', 'HOSTNAME', 'TERM', 'SHLVL', 'PWD', 'OLDPWD', '_', 'LANG', 'LC_ALL', 'DEBIAN_FRONTEND', 'container', 'GPG_KEY',
|
|
342
|
+
'PYTHON_VERSION', 'PYTHON_SHA256', 'PYTHON_PIP_VERSION', 'PYTHON_GET_PIP_URL', 'PYTHON_GET_PIP_SHA256', 'PYTHON_SETUPTOOLS_VERSION',
|
|
343
|
+
'NODE_VERSION', 'YARN_VERSION', 'LS_COLORS', 'SSL_CERT_DIR', 'SSL_CERT_FILE', 'NVIDIA_VISIBLE_DEVICES', 'NVIDIA_DRIVER_CAPABILITIES'}
|
|
344
|
+
HARNESS = re.compile(r'^(CORTEX_|TB2_|MENTORSHIP_|HELPER_|VISION_|NEXUS_|OMNI|ANTHROPIC|OPENAI|DEEPSEEK|XAI|GROQ|GEMINI|GOOGLE_API|MISTRAL|'
|
|
345
|
+
r'TYPESAFE|HF_|HUGGING|MODEL_|DEFAULT_MODEL|MAX_TOOL|TOOL_TIMEOUT|ENABLE_WEBTOOLS|CANON_|NODE_OPTIONS|NPM_|BENCH_|HARBOR)')
|
|
346
|
+
SECRET = re.compile(r'(KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH|COOKIE|SESSION)', re.I)
|
|
347
|
+
env = {}
|
|
348
|
+
try:
|
|
349
|
+
raw = open('/proc/1/environ', 'rb').read().split(b'\0')
|
|
350
|
+
for kv in raw:
|
|
351
|
+
if b'=' in kv:
|
|
352
|
+
k, v = kv.split(b'=', 1); env[k.decode('utf-8', 'replace')] = v.decode('utf-8', 'replace')
|
|
353
|
+
src_note = 'from the container init process'
|
|
354
|
+
except Exception:
|
|
355
|
+
src_note = None
|
|
356
|
+
if src_note is not None:
|
|
357
|
+
keep = []
|
|
358
|
+
for k in sorted(env):
|
|
359
|
+
if k in BOILER or HARNESS.search(k): continue
|
|
360
|
+
v = env[k]
|
|
361
|
+
if SECRET.search(k): v = '<redacted>'
|
|
362
|
+
keep.append(f'{k}={v[:120]}')
|
|
363
|
+
if keep:
|
|
364
|
+
p(f'-- TASK ENVIRONMENT ({src_note}; boilerplate and harness variables omitted, secrets redacted) --')
|
|
365
|
+
for kv in keep[:40]: p(' ' + kv)
|
|
366
|
+
if len(keep) > 40: p(more(len(keep) - 40, 'variables', 'cat /proc/1/environ | tr "\\0" "\\n"'))
|
|
367
|
+
|
|
368
|
+
# ---------------------------------------------------------------- 7. services + paths outside the workdir
|
|
369
|
+
sec('services')
|
|
370
|
+
hosts = []
|
|
371
|
+
try:
|
|
372
|
+
for l in open('/etc/hosts'):
|
|
373
|
+
parts = l.split()
|
|
374
|
+
if len(parts) >= 2 and not parts[0].startswith(('#', '127.', '::1', 'fe00', 'ff0')):
|
|
375
|
+
hosts += [h for h in parts[1:] if not re.match(r'^[0-9a-f]{12}$', h) and h not in ('localhost',)]
|
|
376
|
+
except OSError:
|
|
377
|
+
pass
|
|
378
|
+
ports = []
|
|
379
|
+
for f in ('/proc/net/tcp', '/proc/net/tcp6'):
|
|
380
|
+
try:
|
|
381
|
+
for l in open(f).read().splitlines()[1:]:
|
|
382
|
+
x = l.split()
|
|
383
|
+
if len(x) > 3 and x[3] == '0A':
|
|
384
|
+
ports.append(int(x[1].split(':')[1], 16))
|
|
385
|
+
except OSError:
|
|
386
|
+
pass
|
|
387
|
+
urlvars = [f'{k}={env[k][:80]}' for k in sorted(env) if re.search(r'(HOST|PORT|URL|URI|ENDPOINT|ADDR)', k) and not HARNESS.search(k) and not SECRET.search(k)]
|
|
388
|
+
if hosts or ports or urlvars:
|
|
389
|
+
p('-- SERVICES --')
|
|
390
|
+
if hosts: p(' other hosts on this network: ' + ', '.join(sorted(set(hosts))[:20]))
|
|
391
|
+
if ports: p(' listening locally: ' + ', '.join(str(x) for x in sorted(set(ports))[:20]))
|
|
392
|
+
for u in urlvars[:12]: p(' ' + u)
|
|
393
|
+
sec('outside')
|
|
394
|
+
outside = []
|
|
395
|
+
for d in ('/shared', '/data', '/mnt', '/srv', '/workspace', '/input', '/inputs', '/output', '/outputs', '/reference', '/resources', '/task', '/opt/task'):
|
|
396
|
+
if os.path.isdir(d) and not W.startswith(d) and not d.startswith(W):
|
|
397
|
+
n, capped = 0, False
|
|
398
|
+
try:
|
|
399
|
+
for dp, dns, fs in os.walk(d, followlinks=False): # bounded: a large mount must never stall the inventory
|
|
400
|
+
n += len(fs)
|
|
401
|
+
if n >= 2000 or dp.count('/') - d.count('/') >= 4:
|
|
402
|
+
capped = True; break
|
|
403
|
+
except Exception:
|
|
404
|
+
pass
|
|
405
|
+
if n: outside.append(f'{d} ({n}{"+" if capped else ""} files)')
|
|
406
|
+
if outside:
|
|
407
|
+
p('-- OUTSIDE THE WORKDIR (task data may live here) -- ' + ', '.join(outside) + ' — list: find <dir> -type f | head -100')
|
|
408
|
+
print('\n'.join(line for name in EMIT for line in SECTIONS.get(name, [])))
|
|
409
|
+
PYINV
|
package/.cortex/orient
CHANGED
|
@@ -5,13 +5,37 @@
|
|
|
5
5
|
# has no .cortex/orient of its own. Deterministic, read-only except for one
|
|
6
6
|
# mechanical .cortex/CORTEX.md render (never overwrites), always exits 0.
|
|
7
7
|
W="$(pwd)"
|
|
8
|
+
# Clean workspace (CORTEX_WORKSPACE_CLEAN=1, dark, 2026-09-29): orient writes nothing into the task's tree. The mechanical CORTEX.md and the
|
|
9
|
+
# baseline go to the harness state dir ($CORTEX_STATE_DIR, else ~/.cortex/projects/<sha1(path)[:12]>, else /tmp/nexus-cortex/<same>, the
|
|
10
|
+
# same order and key as the harness's resolveCortexStateDir). Graders that list the directory or diff the repo (TB2.1 sanitize-git-repo,
|
|
11
|
+
# polyglot listdir == [one file]) see only the model's work. Unset = unchanged.
|
|
12
|
+
CX="$W/.cortex"; CLEAN=0
|
|
13
|
+
case "${CORTEX_WORKSPACE_CLEAN:-0}" in 1|true|TRUE|True|on|ON) CLEAN=1;; esac
|
|
14
|
+
if [ "$CLEAN" = "1" ]; then
|
|
15
|
+
if [ -n "${CORTEX_STATE_DIR:-}" ] && mkdir -p "$CORTEX_STATE_DIR" 2>/dev/null && [ -w "$CORTEX_STATE_DIR" ]; then CX="$CORTEX_STATE_DIR"
|
|
16
|
+
else
|
|
17
|
+
H=$(printf %s "$W" | sha1sum 2>/dev/null | cut -c1-12); [ -n "$H" ] || H=$(printf %s "$W" | cksum | cut -d' ' -f1)
|
|
18
|
+
CX="${HOME:-/tmp}/.cortex/projects/$H"; mkdir -p "$CX" 2>/dev/null && [ -w "$CX" ] || { CX="${TMPDIR:-/tmp}/nexus-cortex/$H"; mkdir -p "$CX" 2>/dev/null; }
|
|
19
|
+
fi
|
|
20
|
+
fi
|
|
21
|
+
# Canonical workspace inventory (CORTEX_INVENTORY=1, dark, 2026-09-29): the full role-labelled inventory (checkers + contracts, every dir,
|
|
22
|
+
# files with a content peek, which copy of the code imports, missing deps, task env, services, data outside the workdir) replaces the
|
|
23
|
+
# workspace map and the v2 verification section; the tooling / git / baseline / setup lines below still print. Unset = unchanged output.
|
|
24
|
+
INV=""; if [ "${CORTEX_INVENTORY:-0}" = "1" ]; then for c in "$(dirname "$0")/inventory" "${CORTEX_ROOT:-/nonexistent}/.cortex/inventory"; do [ -f "$c" ] && { INV="$c"; break; }; done; fi
|
|
25
|
+
INV_OUT=""
|
|
26
|
+
if [ -n "$INV" ]; then
|
|
27
|
+
# Captured here, PRINTED after the setup line below (2026-09-29): the model reads orient through `| head -50/-100` in ~93% of sessions,
|
|
28
|
+
# and with the inventory first 8/17 cw sessions lost orient's own short lines (git, the `-- baseline:` revert instruction, setup).
|
|
29
|
+
INV_OUT=$(sh "$INV" "$W" 2>/dev/null)
|
|
30
|
+
else
|
|
8
31
|
echo "== WORKSPACE MAP: $W =="
|
|
9
32
|
ls -1A "$W" 2>/dev/null | head -40
|
|
33
|
+
fi
|
|
10
34
|
# orient v2 ships DARK (2026-09-27): every v2 section runs only with CORTEX_ORIENT_V2=1; unset = the v1 output byte-for-byte.
|
|
11
35
|
V2="${CORTEX_ORIENT_V2:-0}"
|
|
12
36
|
# orient v2 (2026-09-27, MiMo: the whole library lived under vendor/ and the map showed one level): one more level for the top
|
|
13
37
|
# directories (skipping caches/vendored deps of the toolchain), capped so the map stays small.
|
|
14
|
-
[ "$V2" = "1" ] && for d in $(ls -1A "$W" 2>/dev/null | head -40); do
|
|
38
|
+
[ "$V2" = "1" ] && [ -z "$INV" ] && for d in $(ls -1A "$W" 2>/dev/null | head -40); do
|
|
15
39
|
[ -d "$W/$d" ] || continue
|
|
16
40
|
case "$d" in .git|node_modules|__pycache__|.venv|venv|.cache|.cortex|.addon-tools|dist|build|target) continue;; esac
|
|
17
41
|
n=$(ls -1A "$W/$d" 2>/dev/null | wc -l | tr -d ' ')
|
|
@@ -64,7 +88,7 @@ fi
|
|
|
64
88
|
# protected-file guard (a file outside the task's repair set was modified, usually vendored library code) and the workspaces are not git
|
|
65
89
|
# repos, so nothing could show the agent what it had changed. Record a checksum list ONCE (never overwritten, so a re-run of orient keeps
|
|
66
90
|
# the start state) and ship `.cortex/changed`, which lists modified / added / deleted files against it. POSIX cksum; capped.
|
|
67
|
-
if [ "${CORTEX_ORIENT_BASELINE:-0}" = "1" ]; then
|
|
91
|
+
if [ "${CORTEX_ORIENT_BASELINE:-0}" = "1" ] && [ "$CLEAN" != "1" ]; then
|
|
68
92
|
mkdir -p "$W/.cortex" 2>/dev/null
|
|
69
93
|
cat > "$W/.cortex/changed" 2>/dev/null <<'CHANGED'
|
|
70
94
|
#!/bin/sh
|
|
@@ -85,12 +109,13 @@ CHANGED
|
|
|
85
109
|
fi
|
|
86
110
|
BN=$(wc -l < "$W/.cortex/baseline.cksum" 2>/dev/null | tr -d ' ')
|
|
87
111
|
echo "-- baseline: ${BN:-0} files recorded at start; \`sh .cortex/changed\` lists files you modified/added/deleted. Before finishing, run it and revert every change the task did not require."
|
|
88
|
-
elif [ "${CORTEX_ORIENT_BASELINE:-0}" = "auto" ] && ! { command -v git >/dev/null 2>&1 && git -C "$W" rev-parse --is-inside-work-tree >/dev/null 2>&1; }; then
|
|
112
|
+
elif { [ "${CORTEX_ORIENT_BASELINE:-0}" = "1" ] && [ "$CLEAN" = "1" ]; } || { [ "${CORTEX_ORIENT_BASELINE:-0}" = "auto" ] && ! { command -v git >/dev/null 2>&1 && git -C "$W" rev-parse --is-inside-work-tree >/dev/null 2>&1; }; }; then
|
|
89
113
|
# auto (general work, 2026-09-27): a git repo already has `git status`, so skip it; otherwise keep the baseline OUTSIDE the project
|
|
90
114
|
# (the user's ~/.cortex, else /tmp), keyed by the workspace path, so nothing is written into the tree being worked on.
|
|
91
115
|
KEY=$(printf %s "$W" | cksum | cut -d' ' -f1)
|
|
92
116
|
BD="${HOME:-/tmp}/.cortex/baselines/$KEY"
|
|
93
117
|
mkdir -p "$BD" 2>/dev/null && [ -w "$BD" ] || { BD="${TMPDIR:-/tmp}/cortex-baselines/$KEY"; mkdir -p "$BD" 2>/dev/null; }
|
|
118
|
+
[ "$CLEAN" = "1" ] && { BD="$CX/baseline"; mkdir -p "$BD" 2>/dev/null; }
|
|
94
119
|
{ printf '#!/bin/sh\n# Lists files modified / added / deleted in %s since orient recorded its start state.\nW=%s\nB=%s\n' "$W" "'$W'" "'$BD/baseline.cksum'"
|
|
95
120
|
cat <<'CHANGED'
|
|
96
121
|
cd "$W" || exit 0
|
|
@@ -108,7 +133,11 @@ CHANGED
|
|
|
108
133
|
( cd "$W" && find . \( -path ./.git -o -path ./.cortex -o -name node_modules -o -name __pycache__ -o -name .venv -o -name venv -o -name .cache -o -name .pytest_cache -o -name .mypy_cache \) -prune -o -type f -size -20M -print 2>/dev/null | head -20000 | tr '\n' '\0' | xargs -0 cksum 2>/dev/null > "$BD/baseline.cksum" )
|
|
109
134
|
fi
|
|
110
135
|
BN=$(wc -l < "$BD/baseline.cksum" 2>/dev/null | tr -d ' ')
|
|
136
|
+
if [ "$CLEAN" = "1" ] && [ "${CORTEX_ORIENT_BASELINE:-0}" = "1" ]; then
|
|
137
|
+
echo "-- baseline: ${BN:-0} files recorded at start; \`sh $BD/changed\` lists files you modified/added/deleted. Before finishing, run it and revert every change the task did not require."
|
|
138
|
+
else
|
|
111
139
|
echo "-- baseline: ${BN:-0} files recorded at start (not a git repo); \`sh $BD/changed\` lists files you modified/added/deleted. Before finishing, run it and revert changes to existing files the task did not require."
|
|
140
|
+
fi
|
|
112
141
|
fi
|
|
113
142
|
# Bare-box hint (2026-09-03, operator-simplified): a task container may ship WITHOUT the language, compiler,
|
|
114
143
|
# package or library the objective needs — on purpose (the agent phase is bare; internet is usually allowed).
|
|
@@ -122,7 +151,22 @@ if [ "${CORTEX_ORIENT_BOOTSTRAP:-0}" = "1" ] && { ! command -v python3 >/dev/nul
|
|
|
122
151
|
PM=""; for m in apt-get apk dnf yum pacman zypper brew; do command -v "$m" >/dev/null 2>&1 && { PM="$m"; break; }; done
|
|
123
152
|
ROOT=$([ "$(id -u 2>/dev/null)" = "0" ] && echo yes || echo no)
|
|
124
153
|
GUARD=""; [ "$V2" = "1" ] && GUARD=" Install into the system or a venv, never into the task's own source or vendored tree."
|
|
154
|
+
# With the inventory on and a python interpreter present, the inventory has already checked the workspace manifests (requirements/
|
|
155
|
+
# pyproject/package.json) against what is installed. Replace the speculative "may be missing" paragraph with those facts
|
|
156
|
+
# (r-orient-deficiencies-2026-09-29 §3.3: "print only the MISSING ones … keep the generic line otherwise"); keep the install discipline
|
|
157
|
+
# (once, cached, never into the task's source/vendored tree). No manifest, no python, or no inventory = the generic line below, unchanged.
|
|
158
|
+
INV_MF=""; INV_MISS=""
|
|
159
|
+
if [ -n "$INV_OUT" ] && { command -v python3 >/dev/null 2>&1 || command -v python >/dev/null 2>&1; }; then
|
|
160
|
+
printf '%s\n' "$INV_OUT" | grep -qE "declared but NOT installed|declared python dependencies are installed|^-- NODE " && INV_MF=1
|
|
161
|
+
printf '%s\n' "$INV_OUT" | grep -qE "declared but NOT installed|^-- NODE .*NOT installed:" && INV_MISS=1
|
|
162
|
+
fi
|
|
163
|
+
if [ -n "$INV_MF" ] && [ -n "$INV_MISS" ]; then
|
|
164
|
+
echo "-- setup: the workspace manifests declare dependencies that are NOT installed (listed in the inventory below; pkg-mgr=${PM:-none}, root=$ROOT). Install what the task needs ONCE and reuse it, with a fast cached installer for the language (uv for Python, bun for JS) — do not re-download a large dependency twice.$GUARD Pin versions, then verify with a real run before finishing."
|
|
165
|
+
elif [ -n "$INV_MF" ]; then
|
|
166
|
+
echo "-- setup: the declared dependencies are installed (see the inventory below). If you still need a package, install it once$( [ "$V2" = "1" ] && echo " into the system or a venv, never into the task's own source or vendored tree" )."
|
|
167
|
+
else
|
|
125
168
|
echo "-- setup: this box may be missing a tool/language/library the task needs (pkg-mgr=${PM:-none}, root=$ROOT). If so, INSTALL what you need yourself following standard practice (the system package manager, or the language's own installer); install ONCE and reuse it, and prefer a fast cached installer for the language (uv for Python, bun for JS) — do not re-download a large dependency twice.$GUARD Pin versions, then verify with a real run before finishing. An empty box is part of the task, not an error."
|
|
169
|
+
fi
|
|
126
170
|
fi
|
|
127
171
|
# orient v2 — VERIFICATION ENTRY POINTS: how this task's correctness is checked, so work is built and verified against the real
|
|
128
172
|
# criteria, not the agent's own guess (MiMo K=3: in 57/79 failures the agent's own test passed on a wrong solution). Same usage-line
|
|
@@ -143,7 +187,9 @@ for f in pytest.ini tox.ini setup.cfg pyproject.toml Makefile package.json; do
|
|
|
143
187
|
done
|
|
144
188
|
TD=$(find . -maxdepth 3 -type d \( -name tests -o -name test \) 2>/dev/null | grep -vE "node_modules|/\.|site-packages" | head -4 | tr '\n' ' ')
|
|
145
189
|
fi
|
|
146
|
-
|
|
190
|
+
# The inventory (captured above) prints AFTER orient's short facts — tooling, git, baseline, setup — so a `| head -N` read keeps them.
|
|
191
|
+
[ -n "$INV" ] && printf '%s\n' "$INV_OUT"
|
|
192
|
+
if [ -n "$VE$TC$TD" ] && [ -z "$INV" ]; then
|
|
147
193
|
echo "== VERIFICATION ENTRY POINTS (build to and verify against these — not a test you invent) =="
|
|
148
194
|
for f in $VE; do
|
|
149
195
|
echo " $f"
|
|
@@ -196,28 +242,29 @@ machine_block() {
|
|
|
196
242
|
ls -1A "$W" 2>/dev/null | head -25 | sed 's/^/- /'
|
|
197
243
|
echo "$MB_END"
|
|
198
244
|
}
|
|
199
|
-
DOC=.cortex/CORTEX.md
|
|
245
|
+
DOC=.cortex/CORTEX.md; CD=.cortex
|
|
246
|
+
[ "$CLEAN" = "1" ] && { DOC="$CX/CORTEX.md"; CD="$CX"; }
|
|
200
247
|
if [ ! -f "$DOC" ]; then
|
|
201
|
-
mkdir -p
|
|
248
|
+
mkdir -p "$CD" 2>/dev/null
|
|
202
249
|
{
|
|
203
250
|
echo "# CORTEX.md (mechanical orient scan — refine with init_cortex_context)"
|
|
204
251
|
echo
|
|
205
252
|
machine_block
|
|
206
|
-
} > "$DOC" 2>/dev/null && echo "(wrote mechanical
|
|
253
|
+
} > "$DOC" 2>/dev/null && echo "(wrote mechanical $DOC)"
|
|
207
254
|
elif grep -q "orient:auto:begin" "$DOC" 2>/dev/null; then
|
|
208
|
-
machine_block >
|
|
209
|
-
awk '/orient:auto:begin/{f=1} f{print} /orient:auto:end/{f=0}' "$DOC" >
|
|
210
|
-
if cmp -s
|
|
211
|
-
rm -f
|
|
255
|
+
machine_block > "$CD"/.orient-fresh-block 2>/dev/null
|
|
256
|
+
awk '/orient:auto:begin/{f=1} f{print} /orient:auto:end/{f=0}' "$DOC" > "$CD"/.orient-cur-block 2>/dev/null
|
|
257
|
+
if cmp -s "$CD"/.orient-cur-block "$CD"/.orient-fresh-block; then
|
|
258
|
+
rm -f "$CD"/.orient-fresh-block "$CD"/.orient-cur-block
|
|
212
259
|
rm -f "$DOC.next" "$DOC.diff"
|
|
213
260
|
echo "(CORTEX.md current)"
|
|
214
261
|
else
|
|
215
|
-
awk -v fresh
|
|
262
|
+
awk -v fresh="$CD/.orient-fresh-block" '
|
|
216
263
|
/orient:auto:begin/ {skip=1; while ((getline line < fresh) > 0) print line; close(fresh); next}
|
|
217
264
|
/orient:auto:end/ {skip=0; next}
|
|
218
265
|
skip!=1 {print}' "$DOC" > "$DOC.next" 2>/dev/null
|
|
219
266
|
diff -u "$DOC" "$DOC.next" > "$DOC.diff" 2>/dev/null
|
|
220
|
-
rm -f
|
|
267
|
+
rm -f "$CD"/.orient-fresh-block "$CD"/.orient-cur-block
|
|
221
268
|
echo "(doctrine refresh staged for curation: machine sections drifted)"
|
|
222
269
|
fi
|
|
223
270
|
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexus-cortex/server",
|
|
3
|
-
"version": "4.124.
|
|
3
|
+
"version": "4.124.33",
|
|
4
4
|
"description": "Thin Express server wrapper for Nexus Cortex core library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"prepack": "node ../../scripts/copy-pkg-cortex-scaffold.mjs"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@nexus-cortex/core": "4.124.
|
|
24
|
-
"@nexus-cortex/executors": "4.124.
|
|
23
|
+
"@nexus-cortex/core": "4.124.33",
|
|
24
|
+
"@nexus-cortex/executors": "4.124.33",
|
|
25
25
|
"chalk": "^5.3.0",
|
|
26
26
|
"cors": "^2.8.5",
|
|
27
27
|
"dotenv": "^16.4.5",
|