Commit Graph

4 Commits

Author SHA1 Message Date
marfrit 34b465d6dc main: project-overlay loader (Phase 9 commit #2)
Wires the project-overlay step around the existing load_config.
Activates only when a trusted .aish.lua is found in/above cwd.

Changes:

- _find_project_config() walks libc.getcwd() up to $HOME, returning
  first .aish.lua found. R1 fix folded: proper-prefix check (`dir ==
  home OR dir starts with home .. "/"`) avoids the false positive
  where /home/user2 matches HOME=/home/user via byte prefix.

- _trust_file_path() resolves via $AISH_TRUST_FILE env override,
  else ~/.aish/trusted-projects. Plan-time decision per N3.

- _check_and_maybe_prompt(project_path, history) — calls
  history._sha256_file ONCE; routes through history.is_trusted; on
  miss prompts via rl.readline; on accept persists via
  history.add_trusted. A8 mitigation: if rl.readline fails to load,
  decline silently (no io.read fallback that would consume stdin).

- load_config_with_overlay(opts):
    * Calls existing load_config; seeds sources={k="user", ...}
    * Walks for .aish.lua; if found:
      - In opts.prompt mode (-p, R2): skip the prompt entirely;
        only PRE-TRUSTED overlays load. Avoids io consuming the
        piped stdin that -p will read for context.
      - Else: interactive trust check + prompt.
    * On accept + successful dofile: shallow-merge top-level keys
      ONTO user config; update sources[k]="project" for overlapping.
    * R3: embeds sources on cfg._sources for repl.lua's :config
      show meta to read. No global.
    * Returns (cfg, user_path, project_path | nil).

- main() now calls load_config_with_overlay; on project layer
  active, emits the "[aish] project config: <path> (overlaid on
  <user>)" status line per A4 (AFTER the user-config status).

E2E verified across 4 scenarios with AISH_TRUST_FILE + isolated HOME:
  1. Decline -> overlay skipped; user config active.
  2. Accept -> overlay loaded; project_model active; status line
     "[aish] project config: ... (overlaid on ...)" visible.
  3. Re-startup -> NO prompt (cached via sha); overlay loaded
     transparently. R4 single-sha-call confirmed.
  4. -p mode with untrusted overlay -> skipped silently; piped
     stdin preserved for run_one_shot.

Regression: test_safety 87/87, test_router_model 31/31, repl loads.

Commit #3 lands :config show + HELP next; commit #4 the config
template comment + status -> Implement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 23:48:22 +00:00
marfrit 81c3b1b44a main: non-interactive -p/--prompt one-shot mode (closes #4)
Adds `aish -p "<text>"` for Unix-pipeline composability:

  tail app.log | aish -p "any anomalies?"
  aish -p "summarize: $(curl -sS https://...)"

The flag bypasses repl.lua entirely. On invocation:

  1. Stdin: when not a TTY, read to EOF and prepend to the prompt as a
     fenced block. ffi.libc.isatty(0) gates the read so interactive
     `aish -p "..."` (no pipe) doesn't hang.
  2. Resolve config.models[config.default_model].
  3. Stream broker.chat_stream replies to stdout; finalize with newline.
  4. Exit 0 on success, 1 on broker error, 2 on arg / config error.

Behavior NOT in -p mode (kept simple per the issue's "no repl.lua
involvement"):
  - No MCP, no tool loop, no Norris, no routing, no memory injection.
  - "CMD:" lines in the reply are printed verbatim, NOT executed —
    callers can grep / pipe them as they wish.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 21:06:27 +00:00
marfrit a18e530c03 main: --config/--help arg parsing, vendor on package.path, REPL start
Phase 0 entry point per PHASE0.md §4, §10.

Resolves the §10 config search:
  --config <path>          (explicit; failure if not openable, no fallback)
  $AISH_CONFIG
  ~/.config/aish/config.lua
  ./config.lua

The explicit form now hard-fails instead of silently falling through to
the next candidate — caught in smoke (`--config /nonexistent` was loading
./config.lua).

Pre-pends `./?.lua;./vendor/?.lua` to package.path so `require("dkjson")`
finds vendor/dkjson.lua and project requires resolve from the repo root.
Run from the repo root; cwd-independent resolution lands later.

`--help` prints the usage block. Unrecognized arg exits 2 with a
diagnostic on stderr.

Phase 0 done-criteria (PHASE0.md §2):
  ✓ shell command execution with framed output
  ✓ :meta commands (full §5.2 set)
  ✓ in-memory conversation history with sliding-window eviction
  ✓ codebase layout matches §4 — every module name stable for Phase 1+
   live AI exchange — structurally wired; live test deferred per
     issue #12 (broker endpoint hostname not resolvable from noether)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:12:25 +00:00
claude-noether 4310207738 Phase 0: scaffold tree + manifest
- README, .gitignore, CLAUDE.md (project conventions)
- docs/PHASE0.md — full Phase 0 manifest (locked substrate)
- 10 root .lua modules + 4 ffi/ bindings, all stubs raising NotImplemented
  with module-scoped responsibilities matching the manifest
- config.lua wired to current dirac/hossenfelder endpoints (qwen-coder-7b
  snappy/32k + cloud via OpenRouter through hossenfelder)

File names match docs/PHASE0.md §4 exactly. Module bodies fill in across
later phases; the tree shape is locked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 23:16:07 +00:00