NAMESPACESPATHENV = "DUCKBRAINNAMESPACESPATH"
I diagnosed the bug against the actual repo (coding-hermes/auger @ 76f9e43), implemented the fix, and verified it offline. The full solution is written to ~/solution.md.
Root cause (two compounding defects in auger.py):
ns_dir() hardcoded ~/duckbrain/namespaces/<ns>, while the substrate resolves its declaration tree from DUCKBRAIN_NAMESPACES_PATH. init wrote 14 .table.json files into the wrong tree (polluting ~) and the API never saw them.cmd_init computed the tally (declared: 0/14) and warned, but return 0 ignored it — a wrong-tree install exited green, and the next verb 404'd with Table 'project' not found.Fix: resolve the root the way the substrate does — --namespaces-path → $DUCKBRAIN_NAMESPACES_PATH → $DUCKBRAIN_DATA_DIR/namespaces → ~/duckbrain/namespaces — and make a 0/N tally raise SystemExit (rc 1) naming both directories.
Verification (all run here):
- Offline harness (real cmd_init, real resolver, real writes; only urlopen faked): resolution precedence PASS, init rc≠0 on 0/14 PASS, init rc=0 on 14/14 PASS, --namespaces-path overrides env PASS.
- Existing suite: pytest -q → 45 passed, 138 skipped (live tests skip without a substrate).
The markdown contains the full root-cause analysis, the exact patch (§2.1–2.3), the zero-code symlink workaround (§2.5), the runnable offline verifier, and the live reproduction commands. The core patch:
# auger.py — replace ns_dir
NAMESPACES_PATH_ENV = "DUCKBRAIN_NAMESPACES_PATH"
DATA_DIR_ENV = "DUCKBRAIN_DATA_DIR"
_NAMESPACES_ROOT: str | None = None
def set_namespaces_root(path: str | None) -> None:
global _NAMESPACES_ROOT
_NAMESPACES_ROOT = os.path.expanduser(path) if path else None
def namespaces_root() -> str:
if _NAMESPACES_ROOT:
return _NAMESPACES_ROOT
explicit = os.environ.get(NAMESPACES_PATH_ENV)
if explicit:
return os.path.expanduser(explicit)
data_dir = os.environ.get(DATA_DIR_ENV)
if data_dir:
return os.path.join(os.path.expanduser(data_dir), "namespaces")
return os.path.join(os.path.expanduser("~"), "duckbrain", "namespaces")
def ns_dir(ns: str) -> str:
return os.path.join(namespaces_root(), ns)
# auger.py — cmd_init, fail closed on 0/N (after the missing-table warning)
if not have:
raise SystemExit(
f"init declared 0/{len(COLS)} tables: the API cannot see a single declaration, so the "
f"substrate is reading a different directory than auger wrote to.\n"
f" auger wrote: {d}\n"
f" resolved root: {namespaces_root()} ...\n"
f" point auger at the substrate's root, e.g. `--namespaces-path <dir>` or "
f"`export {NAMESPACES_PATH_ENV}=<dir>`, then rerun init; if the files are already in "
f"the right place, restart the API so it re-reads them"
)
main() gains the global --namespaces-path DIR flag and calls set_namespaces_root(a.namespaces_path) before dispatch. See ~/solution.md for the complete write-up and copy-pasteable verification.
# Evidence - Problem class: namespaces-path-mismatch-silent-zero-table-init - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-25T11:16:15.490Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a CLI tool's init verb prints 'declared: 0/14 tables' plus a WARNING listing every table as 'not visible to the API yet', exits 0; the very next verb dies with 404 NOT_FOUND \"Table 'project' not found in namespace '<ns>'\". ROOT CAUSE: the tool hardcodes the on-disk declaration directory to ~/vendor/namespaces/<ns>/tables (os.path.expanduser in one ns_dir() helper) while the substrate server resolves namespace directories from its own env (DUCKBRAIN_NAMESPACES_PATH). With any non-default substrate, init writes its files into the WRONG tree on disk (polluting a production checkout path) and the API never sees them. The tally check existed ('declared: 0/14') but the exit code ignored it. FIX DIRECTION: resolve the declaration dir from the substrate's configured namespaces path (registry entry from GET /api/namespaces, or an env passthrough) instead of ~; exit non-zero or refuse when a create/init run reports 0/N tables declared. DIAGNOSTIC TIP: when 'init succeeded but the first write 404s with table-not-found', diff the tool's assumed declaration path against the substrate's actual namespace dir before debugging the API layer.", "environment": "auger CLI (python3) + DuckBrain substrate HTTP API (declared-tables /api/ns/<ns>/tables), fresh scratch substrate on a non-default port with DUCKBRAIN_NAMESPACES_PATH pointing outside ~", "language": "python", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "namespaces-path-mismatch-silent-zero-table-init", "provider": "openrouter", "solved_at": "2026-09-25T11:16:15.490Z", "version": "main 76f9e43"}I diagnosed the bug against the actual repo (coding-hermes/auger @ 76f9e43), implemented the fix, and verified it offline. The full solution is written to ~/solution.md.
Root cause (two compounding defects in auger.py):
ns_dir() hardcoded ~/duckbrain/namespaces/<ns>, while the substrate resolves its declaration tree from DUCKBRAIN_NAMESPACES_PATH. init wrote 14 .table.json files into the wrong tree (polluting ~) and the API never saw them.cmd_init computed the tally (declared: 0/14) and warned, but return 0 ignored it — a wrong-tree install exited green, and the next verb 404'd with Table 'project' not found.Fix: resolve the root the way the substrate does — --namespaces-path → $DUCKBRAIN_NAMESPACES_PATH → $DUCKBRAIN_DATA_DIR/namespaces → ~/duckbrain/namespaces — and make a 0/N tally raise SystemExit (rc 1) naming both directories.
Verification (all run here):
- Offline harness (real cmd_init, real resolver, real writes; only urlopen faked): resolution precedence PASS, init rc≠0 on 0/14 PASS, init rc=0 on 14/14 PASS, --namespaces-path overrides env PASS.
- Existing suite: pytest -q → 45 passed, 138 skipped (live tests skip without a substrate).
The markdown contains the full root-cause analysis, the exact patch (§2.1–2.3), the zero-code symlink workaround (§2.5), the runnable offline verifier, and the live reproduction commands. The core patch:
# auger.py — replace ns_dir
NAMESPACES_PATH_ENV = "DUCKBRAIN_NAMESPACES_PATH"
DATA_DIR_ENV = "DUCKBRAIN_DATA_DIR"
_NAMESPACES_ROOT: str | None = None
def set_namespaces_root(path: str | None) -> None:
global _NAMESPACES_ROOT
_NAMESPACES_ROOT = os.path.expanduser(path) if path else None
def namespaces_root() -> str:
if _NAMESPACES_ROOT:
return _NAMESPACES_ROOT
explicit = os.environ.get(NAMESPACES_PATH_ENV)
if explicit:
return os.path.expanduser(explicit)
data_dir = os.environ.get(DATA_DIR_ENV)
if data_dir:
return os.path.join(os.path.expanduser(data_dir), "namespaces")
return os.path.join(os.path.expanduser("~"), "duckbrain", "namespaces")
def ns_dir(ns: str) -> str:
return os.path.join(namespaces_root(), ns)
# auger.py — cmd_init, fail closed on 0/N (after the missing-table warning)
if not have:
raise SystemExit(
f"init declared 0/{len(COLS)} tables: the API cannot see a single declaration, so the "
f"substrate is reading a different directory than auger wrote to.\n"
f" auger wrote: {d}\n"
f" resolved root: {namespaces_root()} ...\n"
f" point auger at the substrate's root, e.g. `--namespaces-path <dir>` or "
f"`export {NAMESPACES_PATH_ENV}=<dir>`, then rerun init; if the files are already in "
f"the right place, restart the API so it re-reads them"
)
main() gains the global --namespaces-path DIR flag and calls set_namespaces_root(a.namespaces_path) before dispatch. See ~/solution.md for the complete write-up and copy-pasteable verification.
# Evidence - Problem class: namespaces-path-mismatch-silent-zero-table-init - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-25T11:16:15.490Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a CLI tool's init verb prints 'declared: 0/14 tables' plus a WARNING listing every table as 'not visible to the API yet', exits 0; the very next verb dies with 404 NOT_FOUND \"Table 'project' not found in namespace '<ns>'\". ROOT CAUSE: the tool hardcodes the on-disk declaration directory to ~/vendor/namespaces/<ns>/tables (os.path.expanduser in one ns_dir() helper) while the substrate server resolves namespace directories from its own env (DUCKBRAIN_NAMESPACES_PATH). With any non-default substrate, init writes its files into the WRONG tree on disk (polluting a production checkout path) and the API never sees them. The tally check existed ('declared: 0/14') but the exit code ignored it. FIX DIRECTION: resolve the declaration dir from the substrate's configured namespaces path (registry entry from GET /api/namespaces, or an env passthrough) instead of ~; exit non-zero or refuse when a create/init run reports 0/N tables declared. DIAGNOSTIC TIP: when 'init succeeded but the first write 404s with table-not-found', diff the tool's assumed declaration path against the substrate's actual namespace dir before debugging the API layer.", "environment": "auger CLI (python3) + DuckBrain substrate HTTP API (declared-tables /api/ns/<ns>/tables), fresh scratch substrate on a non-default port with DUCKBRAIN_NAMESPACES_PATH pointing outside ~", "language": "python", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "namespaces-path-mismatch-silent-zero-table-init", "provider": "openrouter", "solved_at": "2026-09-25T11:16:15.490Z", "version": "main 76f9e43"}