@made-by-moonlight/athene-core 0.9.1 → 0.10.0

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.
Files changed (79) hide show
  1. package/dist/agent-workspace-hooks.d.ts +3 -3
  2. package/dist/agent-workspace-hooks.d.ts.map +1 -1
  3. package/dist/agent-workspace-hooks.js +22 -21
  4. package/dist/agent-workspace-hooks.js.map +1 -1
  5. package/dist/config.d.ts +19 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +116 -11
  8. package/dist/config.js.map +1 -1
  9. package/dist/env.d.ts +157 -0
  10. package/dist/env.d.ts.map +1 -0
  11. package/dist/env.js +187 -0
  12. package/dist/env.js.map +1 -0
  13. package/dist/events-db.d.ts.map +1 -1
  14. package/dist/events-db.js +2 -1
  15. package/dist/events-db.js.map +1 -1
  16. package/dist/feature-flags.d.ts.map +1 -1
  17. package/dist/feature-flags.js +3 -1
  18. package/dist/feature-flags.js.map +1 -1
  19. package/dist/gh-trace.d.ts.map +1 -1
  20. package/dist/gh-trace.js +4 -3
  21. package/dist/gh-trace.js.map +1 -1
  22. package/dist/global-config.d.ts +29 -8
  23. package/dist/global-config.d.ts.map +1 -1
  24. package/dist/global-config.js +13 -4
  25. package/dist/global-config.js.map +1 -1
  26. package/dist/index.d.ts +9 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +8 -2
  29. package/dist/index.js.map +1 -1
  30. package/dist/lifecycle-manager.d.ts.map +1 -1
  31. package/dist/lifecycle-manager.js +101 -1
  32. package/dist/lifecycle-manager.js.map +1 -1
  33. package/dist/meta-orchestrator-config-writer.d.ts +13 -0
  34. package/dist/meta-orchestrator-config-writer.d.ts.map +1 -0
  35. package/dist/meta-orchestrator-config-writer.js +22 -0
  36. package/dist/meta-orchestrator-config-writer.js.map +1 -0
  37. package/dist/meta-orchestrator-prompt.d.ts +16 -0
  38. package/dist/meta-orchestrator-prompt.d.ts.map +1 -0
  39. package/dist/meta-orchestrator-prompt.js +87 -0
  40. package/dist/meta-orchestrator-prompt.js.map +1 -0
  41. package/dist/meta-scope.d.ts +38 -0
  42. package/dist/meta-scope.d.ts.map +1 -0
  43. package/dist/meta-scope.js +47 -0
  44. package/dist/meta-scope.js.map +1 -0
  45. package/dist/observability.d.ts.map +1 -1
  46. package/dist/observability.js +3 -2
  47. package/dist/observability.js.map +1 -1
  48. package/dist/paths.d.ts +18 -0
  49. package/dist/paths.d.ts.map +1 -1
  50. package/dist/paths.js +37 -1
  51. package/dist/paths.js.map +1 -1
  52. package/dist/platform.d.ts.map +1 -1
  53. package/dist/platform.js +4 -3
  54. package/dist/platform.js.map +1 -1
  55. package/dist/prompt-builder.d.ts +2 -2
  56. package/dist/prompt-builder.d.ts.map +1 -1
  57. package/dist/prompt-builder.js +2 -2
  58. package/dist/prompts/meta-orchestrator.md.js +4 -0
  59. package/dist/prompts/meta-orchestrator.md.js.map +1 -0
  60. package/dist/prompts/orchestrator.md.js +1 -1
  61. package/dist/prompts/orchestrator.md.js.map +1 -1
  62. package/dist/runtime-orphans.d.ts +96 -0
  63. package/dist/runtime-orphans.d.ts.map +1 -0
  64. package/dist/runtime-orphans.js +158 -0
  65. package/dist/runtime-orphans.js.map +1 -0
  66. package/dist/session-manager.d.ts +16 -0
  67. package/dist/session-manager.d.ts.map +1 -1
  68. package/dist/session-manager.js +611 -46
  69. package/dist/session-manager.js.map +1 -1
  70. package/dist/spawn-collision.d.ts +23 -0
  71. package/dist/spawn-collision.d.ts.map +1 -0
  72. package/dist/spawn-collision.js +26 -0
  73. package/dist/spawn-collision.js.map +1 -0
  74. package/dist/types.d.ts +103 -1
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/types.js +22 -1
  77. package/dist/types.js.map +1 -1
  78. package/package.json +10 -9
  79. package/LICENSE +0 -22
@@ -15,16 +15,16 @@ export declare function buildAgentPath(basePath: string | undefined): string;
15
15
  * ao_cache_read <key> — print cached stdout
16
16
  * ao_cache_write <key> — write stdin to cache atomically
17
17
  */
18
- export declare const AO_METADATA_HELPER = "#!/usr/bin/env bash\n# ao-metadata-helper \u2014 shared by gh/git wrappers\n# Provides: update_ao_metadata, read_ao_metadata, ao_cache_*\n\n# \u2500\u2500 Shared validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n_ao_validate_env() {\n local ao_dir=\"${AO_DATA_DIR:-}\"\n local ao_session=\"${AO_SESSION:-}\"\n [[ -z \"$ao_dir\" || -z \"$ao_session\" ]] && return 1\n case \"$ao_session\" in */* | *..*) return 1 ;; esac\n case \"$ao_dir\" in\n \"$HOME\"/.ao/* | \"$HOME\"/.agent-orchestrator/* | /tmp/*) ;;\n *) return 1 ;;\n esac\n return 0\n}\n\n# \u2500\u2500 Metadata write \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nupdate_ao_metadata() {\n local key=\"$1\" value=\"$2\"\n local ao_dir=\"${AO_DATA_DIR:-}\"\n local ao_session=\"${AO_SESSION:-}\"\n\n [[ -z \"$ao_dir\" || -z \"$ao_session\" ]] && return 0\n\n # Validate: session name must not contain path separators or traversal\n case \"$ao_session\" in\n */* | *..*) return 0 ;;\n esac\n\n # Validate: ao_dir must be an absolute path under known ao directories or /tmp\n case \"$ao_dir\" in\n \"$HOME\"/.ao/* | \"$HOME\"/.agent-orchestrator/* | /tmp/*) ;;\n *) return 0 ;;\n esac\n\n # V2 storage uses .json extension; fallback to bare filename for pre-migration layouts\n local metadata_file=\"$ao_dir/${ao_session}.json\"\n if [[ ! -f \"$metadata_file\" ]]; then\n metadata_file=\"$ao_dir/$ao_session\"\n fi\n\n # Resolve symlinks and verify canonicalized paths are still within trusted roots\n local real_dir real_ao_dir\n real_ao_dir=\"$(cd \"$ao_dir\" 2>/dev/null && pwd -P)\" || return 0\n real_dir=\"$(cd \"$(dirname \"$metadata_file\")\" 2>/dev/null && pwd -P)\" || return 0\n\n # Re-validate real_ao_dir against trusted roots after canonicalization\n # (prevents /tmp/../../home/user from escaping the allowlist)\n case \"$real_ao_dir\" in\n \"$HOME\"/.ao/* | \"$HOME\"/.ao | \"$HOME\"/.agent-orchestrator/* | \"$HOME\"/.agent-orchestrator | /tmp/*) ;;\n *) return 0 ;;\n esac\n\n [[ \"$real_dir\" == \"$real_ao_dir\"* ]] || return 0\n\n [[ -f \"$metadata_file\" ]] || return 0\n\n # Validate key \u2014 only allow alphanumeric, underscore, hyphen (prevents sed/jq injection)\n [[ \"$key\" =~ ^[a-zA-Z0-9_-]+$ ]] || return 0\n\n local temp_file=\"${metadata_file}.tmp.$$\"\n\n # Strip newlines from value to prevent injection\n local clean_value=\"$(printf '%s' \"$value\" | tr -d '\\n')\"\n\n # Detect JSON vs key=value format\n local first_char\n first_char=\"$(head -c1 \"$metadata_file\" 2>/dev/null)\"\n\n if [[ \"$first_char\" == \"{\" ]]; then\n # JSON format\n if command -v jq &>/dev/null; then\n jq --arg k \"$key\" --arg v \"$clean_value\" '.[$k] = $v' \"$metadata_file\" > \"$temp_file\"\n mv \"$temp_file\" \"$metadata_file\"\n else\n # jq unavailable \u2014 use node (hard dep) for safe nested JSON update\n node -e \"\n const fs = require('fs');\n const d = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));\n d[process.argv[2]] = process.argv[3];\n fs.writeFileSync(process.argv[4], JSON.stringify(d, null, 2));\n \" \"$metadata_file\" \"$key\" \"$clean_value\" \"$temp_file\"\n mv \"$temp_file\" \"$metadata_file\"\n fi\n else\n # Key=value format (legacy)\n local escaped_value=\"$(printf '%s' \"$clean_value\" | sed 's/[&|\\\\]/\\\\&/g')\"\n if grep -q \"^${key}=\" \"$metadata_file\" 2>/dev/null; then\n sed \"s|^${key}=.*|${key}=${escaped_value}|\" \"$metadata_file\" > \"$temp_file\"\n else\n cp \"$metadata_file\" \"$temp_file\"\n printf '%s=%s\\n' \"$key\" \"$clean_value\" >> \"$temp_file\"\n fi\n mv \"$temp_file\" \"$metadata_file\"\n fi\n}\n\n# \u2500\u2500 Metadata read \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nread_ao_metadata() {\n local key=\"$1\"\n _ao_validate_env || return 1\n local metadata_file=\"${AO_DATA_DIR}/${AO_SESSION}\"\n [[ -f \"$metadata_file\" ]] || return 1\n [[ \"$key\" =~ ^[a-zA-Z0-9_-]+$ ]] || return 1\n local line\n line=$(grep \"^${key}=\" \"$metadata_file\" 2>/dev/null | head -1) || return 1\n printf '%s' \"${line#*=}\"\n}\n\n# \u2500\u2500 Cache helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nao_cache_dir() {\n _ao_validate_env || return 1\n local d=\"${AO_DATA_DIR}/.ghcache/${AO_SESSION}\"\n mkdir -p \"$d\" 2>/dev/null || return 1\n printf '%s' \"$d\"\n}\n\nao_cache_fresh() {\n local cache_key=\"$1\" max_age=\"$2\"\n [[ \"$cache_key\" =~ ^[a-zA-Z0-9_.-]+$ ]] || return 1\n local cache_dir\n cache_dir=\"$(ao_cache_dir)\" || return 1\n local ts_file=\"$cache_dir/${cache_key}.ts\"\n local stdout_file=\"$cache_dir/${cache_key}.stdout\"\n [[ -f \"$stdout_file\" && -f \"$ts_file\" ]] || return 1\n local cached_ts now\n cached_ts=$(cat \"$ts_file\" 2>/dev/null) || return 1\n # Sanity check: cached_ts must be a positive integer (epoch seconds)\n [[ \"$cached_ts\" =~ ^[0-9]+$ && \"$cached_ts\" -gt 0 ]] || return 1\n # max_age=0 means infinite TTL\n [[ \"$max_age\" -eq 0 ]] 2>/dev/null && return 0\n now=$(date +%s)\n (( now - cached_ts < max_age ))\n}\n\nao_cache_read() {\n local cache_key=\"$1\"\n [[ \"$cache_key\" =~ ^[a-zA-Z0-9_.-]+$ ]] || return 1\n local cache_dir\n cache_dir=\"$(ao_cache_dir)\" || return 1\n cat \"$cache_dir/${cache_key}.stdout\"\n}\n\nao_cache_write() {\n local cache_key=\"$1\"\n [[ \"$cache_key\" =~ ^[a-zA-Z0-9_.-]+$ ]] || return 1\n local cache_dir\n cache_dir=\"$(ao_cache_dir)\" || return 1\n local tmp=\"$cache_dir/${cache_key}.stdout.tmp.$$\"\n cat > \"$tmp\" && mv \"$tmp\" \"$cache_dir/${cache_key}.stdout\"\n date +%s > \"$cache_dir/${cache_key}.ts\"\n}\n";
18
+ export declare const AO_METADATA_HELPER: string;
19
19
  /**
20
20
  * gh wrapper — intercepts agent-side gh calls for:
21
21
  * 1. Caching repeated read-only commands (PR discovery, issue context)
22
22
  * 2. Auto-updating session metadata on PR creation
23
23
  *
24
- * Cache storage: $AO_DATA_DIR/.ghcache/$AO_SESSION/{key}.stdout + {key}.ts
24
+ * Cache storage: $ATHENE_DATA_DIR/.ghcache/$ATHENE_SESSION/{key}.stdout + {key}.ts
25
25
  * See D4-wrapper-cache-plan.md for full design rationale.
26
26
  */
27
- export declare const GH_WRAPPER = "#!/usr/bin/env bash\n# ao gh wrapper \u2014 caches reads + auto-updates metadata on writes\n\n# Find real gh by removing our wrapper directory from PATH\nao_bin_dir=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\nclean_path=\"$(echo \"$PATH\" | tr ':' '\\n' | grep -Fxv \"$ao_bin_dir\" | grep . | tr '\\n' ':')\"\nclean_path=\"${clean_path%:}\"\nreal_gh=\"\"\n\n# Prefer explicit gh path when provided by AO environment.\n# Guard against recursive self-reference to the wrapper in ~/.ao/bin.\nif [[ -n \"${GH_PATH:-}\" && -x \"$GH_PATH\" ]]; then\n gh_dir=\"$(cd \"$(dirname \"$GH_PATH\")\" 2>/dev/null && pwd)\"\n if [[ \"$gh_dir\" != \"$ao_bin_dir\" ]]; then\n real_gh=\"$GH_PATH\"\n fi\nfi\n\nif [[ -z \"$real_gh\" ]]; then\n real_gh=\"$(PATH=\"$clean_path\" command -v gh 2>/dev/null)\"\nfi\n\nif [[ -z \"$real_gh\" ]]; then\n echo \"ao-wrapper: gh not found in PATH\" >&2\n exit 127\nfi\n\n# Source the metadata helper (provides update/read_ao_metadata, ao_cache_*)\nsource \"$ao_bin_dir/ao-metadata-helper.sh\" 2>/dev/null || true\n\n# Redact sensitive values from args before tracing.\n# Handles: -H \"Authorization: ...\", token=..., password=..., secret=...\n_ao_redact_args() {\n local prev=\"\"\n local out=()\n for arg in \"$@\"; do\n if [[ \"$prev\" == \"-H\" || \"$prev\" == \"--header\" ]] && [[ \"$arg\" =~ ^[Aa]uthorization: ]]; then\n out+=(\"Authorization: [REDACTED]\")\n elif [[ \"$arg\" =~ ^-H[Aa]uthorization: ]]; then\n out+=(\"-HAuthorization: [REDACTED]\")\n elif [[ \"$arg\" =~ ^[Tt]oken= ]]; then\n out+=(\"token=[REDACTED]\")\n elif [[ \"$arg\" =~ ^[Pp]assword= ]]; then\n out+=(\"password=[REDACTED]\")\n elif [[ \"$arg\" =~ ^[Ss]ecret= ]]; then\n out+=(\"secret=[REDACTED]\")\n else\n out+=(\"$arg\")\n fi\n prev=\"$arg\"\n done\n printf '%s\n' \"${out[@]}\"\n}\n\n# Best-effort JSONL tracing for agent-side gh invocations.\nlog_gh_invocation() {\n local trace_file=\"${AO_AGENT_GH_TRACE:-}\"\n [[ -z \"$trace_file\" ]] && return 0\n command -v jq >/dev/null 2>&1 || return 0\n\n mkdir -p \"$(dirname \"$trace_file\")\" 2>/dev/null || return 0\n\n local args_json\n args_json=\"$(_ao_redact_args \"$@\" | jq -Rsc 'split(\"\n\")[:-1]')\" || return 0\n\n # Compute operation: gh.{arg1}.{arg2} (mirrors AO-side extractOperation)\n local _ao_op=\"gh\"\n [[ $# -ge 1 ]] && _ao_op=\"gh.$1\"\n [[ $# -ge 2 && \"$2\" != -* ]] && _ao_op=\"gh.$1.$2\"\n\n jq -nc --arg timestamp \"$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")\" --arg cwd \"$PWD\" --arg operation \"$_ao_op\" --arg aoSession \"${AO_SESSION:-}\" --arg aoSessionName \"${AO_SESSION_NAME:-}\" --arg aoProjectId \"${AO_PROJECT_ID:-}\" --arg aoIssueId \"${AO_ISSUE_ID:-}\" --arg aoCallerType \"${AO_CALLER_TYPE:-}\" --arg pid \"$$\" --arg wrapperVersion \"0.8.0\" --argjson args \"$args_json\" '{\n timestamp: $timestamp,\n cwd: $cwd,\n args: $args,\n operation: $operation,\n aoSession: (if $aoSession == \"\" then null else $aoSession end),\n aoSessionName: (if $aoSessionName == \"\" then null else $aoSessionName end),\n aoProjectId: (if $aoProjectId == \"\" then null else $aoProjectId end),\n aoIssueId: (if $aoIssueId == \"\" then null else $aoIssueId end),\n aoCallerType: (if $aoCallerType == \"\" then null else $aoCallerType end),\n pid: ($pid | tonumber),\n wrapperVersion: $wrapperVersion\n }' >> \"$trace_file\" 2>/dev/null || true\n}\n\nlog_gh_invocation \"$@\"\n\n# Best-effort cache-outcome tracing (appends to same JSONL trace file).\n# result: hit | miss-stored | miss-write-failed | miss-negative | miss-error | passthrough\nlog_ao_cache() {\n local result=\"$1\" cache_key=\"$2\" duration_ms=\"${3:-0}\" exit_code=\"${4:-0}\" ok=\"${5:-true}\"\n local trace_file=\"${AO_AGENT_GH_TRACE:-}\"\n [[ -z \"$trace_file\" ]] && return 0\n printf '{\"timestamp\":\"%s\",\"cacheResult\":\"%s\",\"cacheKey\":\"%s\",\"pid\":%s,\"durationMs\":%s,\"exitCode\":%s,\"ok\":%s}\\n' \"$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")\" \"$result\" \"$cache_key\" \"$$\" \"$duration_ms\" \"$exit_code\" \"$ok\" >> \"$trace_file\" 2>/dev/null || true\n}\n\n# =============================================================================\n# Cacheable reads\n# =============================================================================\n\n# \u2500\u2500 1. PR discovery: gh pr list --head <B> --limit 1 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# 120s TTL for positive results (non-empty array). Never caches [].\nif [[ \"$1\" == \"pr\" && \"$2\" == \"list\" ]]; then\n _ao_head=\"\" _ao_limit=\"\" _ao_json=\"\" _ao_repo=\"\" _ao_cacheable=true\n _ao_saved_args=(\"$@\")\n shift 2\n while [[ $# -gt 0 ]]; do\n case \"$1\" in\n --head) _ao_head=\"$2\"; shift 2 ;;\n --head=*) _ao_head=\"${1#--head=}\"; shift ;;\n --limit) _ao_limit=\"$2\"; shift 2 ;;\n --limit=*) _ao_limit=\"${1#--limit=}\"; shift ;;\n --json) _ao_json=\"$2\"; shift 2 ;;\n --json=*) _ao_json=\"${1#--json=}\"; shift ;;\n --repo) _ao_repo=\"$2\"; shift 2 ;;\n --repo=*) _ao_repo=\"${1#--repo=}\"; shift ;;\n --search|--state|--assignee|--label|--jq|--template)\n _ao_cacheable=false; break ;;\n --search=*|--state=*|--assignee=*|--label=*|--jq=*|--template=*)\n _ao_cacheable=false; break ;;\n -*) shift ;; # skip unknown flags\n *) shift ;; # skip positional\n esac\n done\n set -- \"${_ao_saved_args[@]}\"\n\n if [[ \"$_ao_cacheable\" == true && \"$_ao_limit\" == \"1\" && -n \"$_ao_head\" ]]; then\n # Use sha256 hash suffix to avoid collisions from tr-based sanitization\n # (e.g. feat/foo, feat-foo, feat_foo would otherwise map to the same key)\n _ao_raw_key=\"pr-discovery-${_ao_repo}-${_ao_head}\"\n if [[ -n \"$_ao_json\" ]]; then\n _ao_raw_key=\"${_ao_raw_key}-j-${_ao_json}\"\n fi\n _ao_cache_key=$(printf '%s' \"$_ao_raw_key\" | shasum -a 256 | cut -c1-16)\n _ao_cache_key=\"pr-disc-${_ao_cache_key}\"\n\n if ao_cache_fresh \"$_ao_cache_key\" 120 2>/dev/null; then\n log_ao_cache \"hit\" \"$_ao_cache_key\" 0 0 true\n ao_cache_read \"$_ao_cache_key\"\n exit 0\n fi\n\n # Cache miss \u2014 call real gh, cache positive results (stderr passes through)\n _ao_tmpout=\"$(mktemp)\"\n trap 'rm -f \"$_ao_tmpout\"' EXIT\n _ao_start_s=$(date +%s)\n \"$real_gh\" \"$@\" > \"$_ao_tmpout\"\n _ao_exit=$?\n _ao_duration_ms=$(( ($(date +%s) - _ao_start_s) * 1000 ))\n _ao_ok=true; [[ $_ao_exit -ne 0 ]] && _ao_ok=false\n cat \"$_ao_tmpout\"\n if [[ $_ao_exit -eq 0 ]]; then\n _ao_trimmed=$(tr -d '[:space:]' < \"$_ao_tmpout\")\n # Only cache non-empty positive results\n if [[ -n \"$_ao_trimmed\" && \"$_ao_trimmed\" != \"[]\" ]]; then\n if ao_cache_write \"$_ao_cache_key\" < \"$_ao_tmpout\" 2>/dev/null; then\n log_ao_cache \"miss-stored\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n else\n log_ao_cache \"miss-write-failed\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n fi\n else\n log_ao_cache \"miss-negative\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n fi\n else\n log_ao_cache \"miss-error\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n fi\n exit $_ao_exit\n fi\nfi\n\n# \u2500\u2500 2. Issue context: gh issue view <N> \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# 300-second TTL. Caches any successful response.\nif [[ \"$1\" == \"issue\" && \"$2\" == \"view\" ]]; then\n _ao_issue_id=\"\" _ao_json=\"\" _ao_repo=\"\" _ao_cacheable=true\n _ao_saved_args=(\"$@\")\n shift 2\n # First non-flag arg is the issue identifier\n while [[ $# -gt 0 ]]; do\n case \"$1\" in\n --web|--comments|--jq|--template)\n _ao_cacheable=false; break ;;\n --jq=*|--template=*)\n _ao_cacheable=false; break ;;\n --json) _ao_json=\"$2\"; shift 2 ;;\n --json=*) _ao_json=\"${1#--json=}\"; shift ;;\n --repo) _ao_repo=\"$2\"; shift 2 ;;\n --repo=*) _ao_repo=\"${1#--repo=}\"; shift ;;\n -*) shift ;;\n *)\n if [[ -z \"$_ao_issue_id\" && \"$1\" =~ ^[0-9]+$ ]]; then\n _ao_issue_id=\"$1\"\n fi\n shift ;;\n esac\n done\n set -- \"${_ao_saved_args[@]}\"\n\n if [[ \"$_ao_cacheable\" == true && -n \"$_ao_issue_id\" ]]; then\n _ao_raw_key=\"issue-ctx-${_ao_repo}-${_ao_issue_id}\"\n if [[ -n \"$_ao_json\" ]]; then\n _ao_raw_key=\"${_ao_raw_key}-j-${_ao_json}\"\n fi\n _ao_cache_key=$(printf '%s' \"$_ao_raw_key\" | shasum -a 256 | cut -c1-16)\n _ao_cache_key=\"issue-${_ao_cache_key}\"\n\n if ao_cache_fresh \"$_ao_cache_key\" 300 2>/dev/null; then\n log_ao_cache \"hit\" \"$_ao_cache_key\" 0 0 true\n ao_cache_read \"$_ao_cache_key\"\n exit 0\n fi\n\n _ao_tmpout=\"$(mktemp)\"\n trap 'rm -f \"$_ao_tmpout\"' EXIT\n _ao_start_s=$(date +%s)\n \"$real_gh\" \"$@\" > \"$_ao_tmpout\"\n _ao_exit=$?\n _ao_duration_ms=$(( ($(date +%s) - _ao_start_s) * 1000 ))\n _ao_ok=true; [[ $_ao_exit -ne 0 ]] && _ao_ok=false\n cat \"$_ao_tmpout\"\n if [[ $_ao_exit -eq 0 ]]; then\n if ao_cache_write \"$_ao_cache_key\" < \"$_ao_tmpout\" 2>/dev/null; then\n log_ao_cache \"miss-stored\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n else\n log_ao_cache \"miss-write-failed\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n fi\n else\n log_ao_cache \"miss-error\" \"$_ao_cache_key\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n fi\n exit $_ao_exit\n fi\nfi\n\n# =============================================================================\n# Write intercepts\n# =============================================================================\n\ncase \"$1/$2\" in\n pr/create)\n tmpout=\"$(mktemp)\"\n trap 'rm -f \"$tmpout\"' EXIT\n\n _ao_start_s=$(date +%s)\n \"$real_gh\" \"$@\" 2>&1 | tee \"$tmpout\"\n exit_code=${PIPESTATUS[0]}\n _ao_duration_ms=$(( ($(date +%s) - _ao_start_s) * 1000 ))\n _ao_ok=true; [[ $exit_code -ne 0 ]] && _ao_ok=false\n\n if [[ $exit_code -eq 0 ]]; then\n output=\"$(cat \"$tmpout\")\"\n pr_url=\"$(echo \"$output\" | grep -Eo 'https?://[^/]+/[^/]+/[^/]+/pull/[0-9]+' | head -1)\"\n report_state=\"pr_created\"\n report_draft=\"false\"\n for arg in \"$@\"; do\n if [[ \"$arg\" == \"--draft\" || \"$arg\" == \"-d\" ]]; then\n report_state=\"draft_pr_created\"\n report_draft=\"true\"\n break\n fi\n done\n if [[ -n \"$pr_url\" ]]; then\n update_ao_metadata pr \"$pr_url\"\n update_ao_metadata agentReportedPrUrl \"$pr_url\"\n # Append to prs field (comma-separated list of all PR URLs for this session).\n # Supports multiple PRs per session \u2014 same repo or different repos.\n _ao_meta_f=\"${AO_DATA_DIR}/${AO_SESSION}.json\"\n [[ -f \"$_ao_meta_f\" ]] || _ao_meta_f=\"${AO_DATA_DIR}/${AO_SESSION}\"\n if head -c1 \"$_ao_meta_f\" 2>/dev/null | grep -q '{'; then\n existing_prs=\"$(jq -r '.prs // empty' \"$_ao_meta_f\" 2>/dev/null || echo \"\")\"\n else\n existing_prs=\"$(grep '^prs=' \"$_ao_meta_f\" 2>/dev/null | cut -d'=' -f2- || echo \"\")\"\n fi\n if [[ -z \"$existing_prs\" ]]; then\n new_prs=\"$pr_url\"\n else\n if ! echo \",$existing_prs,\" | grep -qF \",$pr_url,\"; then\n new_prs=\"$existing_prs,$pr_url\"\n else\n new_prs=\"$existing_prs\"\n fi\n fi\n update_ao_metadata prs \"$new_prs\"\n fi\n pr_number=\"$(printf '%s' \"$pr_url\" | grep -Eo '[0-9]+$' | head -1)\"\n if [[ -n \"$pr_number\" ]]; then\n update_ao_metadata agentReportedPrNumber \"$pr_number\"\n fi\n update_ao_metadata agentReportedState \"$report_state\"\n update_ao_metadata agentReportedAt \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n update_ao_metadata agentReportedPrIsDraft \"$report_draft\"\n fi\n\n log_ao_cache \"passthrough\" \"\" \"$_ao_duration_ms\" \"$exit_code\" \"$_ao_ok\"\n exit $exit_code\n ;;\n *)\n _ao_start_s=$(date +%s)\n \"$real_gh\" \"$@\"\n _ao_exit=$?\n _ao_duration_ms=$(( ($(date +%s) - _ao_start_s) * 1000 ))\n _ao_ok=true; [[ $_ao_exit -ne 0 ]] && _ao_ok=false\n log_ao_cache \"passthrough\" \"\" \"$_ao_duration_ms\" \"$_ao_exit\" \"$_ao_ok\"\n exit $_ao_exit\n ;;\nesac\n";
27
+ export declare const GH_WRAPPER: string;
28
28
  /**
29
29
  * git wrapper — intercepts branch operations to auto-update metadata.
30
30
  * All other commands pass through transparently.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-workspace-hooks.d.ts","sourceRoot":"","sources":["../src/agent-workspace-hooks.ts"],"names":[],"mappings":"AAwBA,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,sBAA+B,CAAC;AAkB9D;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAsBnE;AAQD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,+vNA6J9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,wrZA+TtB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,o6CA4CvB,CAAC;AAMF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAKnF;AAkQD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,4UAWhC,CAAC;AAkBF;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDpF"}
1
+ {"version":3,"file":"agent-workspace-hooks.d.ts","sourceRoot":"","sources":["../src/agent-workspace-hooks.ts"],"names":[],"mappings":"AAyBA,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,sBAA+B,CAAC;AAkB9D;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAsBnE;AAQD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,QA6J9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,QA+TtB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,o6CA4CvB,CAAC;AAMF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAKnF;AAkQD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,4UAWhC,CAAC;AAkBF;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDpF"}
@@ -3,6 +3,7 @@ import { join } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { randomBytes } from 'node:crypto';
5
5
  import { isWindows } from './platform.js';
6
+ import { bashEnvRead, nodeEnvRead, ENV } from './env.js';
6
7
 
7
8
  /**
8
9
  * Shared PATH-based workspace hooks for all agent plugins.
@@ -81,8 +82,8 @@ const AO_METADATA_HELPER = `#!/usr/bin/env bash
81
82
  # ── Shared validation ────────────────────────────────────────────────────────
82
83
 
83
84
  _ao_validate_env() {
84
- local ao_dir="\${AO_DATA_DIR:-}"
85
- local ao_session="\${AO_SESSION:-}"
85
+ local ao_dir="${bashEnvRead(ENV.DATA_DIR)}"
86
+ local ao_session="${bashEnvRead(ENV.SESSION)}"
86
87
  [[ -z "\$ao_dir" || -z "\$ao_session" ]] && return 1
87
88
  case "\$ao_session" in */* | *..*) return 1 ;; esac
88
89
  case "\$ao_dir" in
@@ -96,8 +97,8 @@ _ao_validate_env() {
96
97
 
97
98
  update_ao_metadata() {
98
99
  local key="\$1" value="\$2"
99
- local ao_dir="\${AO_DATA_DIR:-}"
100
- local ao_session="\${AO_SESSION:-}"
100
+ local ao_dir="${bashEnvRead(ENV.DATA_DIR)}"
101
+ local ao_session="${bashEnvRead(ENV.SESSION)}"
101
102
 
102
103
  [[ -z "\$ao_dir" || -z "\$ao_session" ]] && return 0
103
104
 
@@ -179,7 +180,7 @@ update_ao_metadata() {
179
180
  read_ao_metadata() {
180
181
  local key="\$1"
181
182
  _ao_validate_env || return 1
182
- local metadata_file="\${AO_DATA_DIR}/\${AO_SESSION}"
183
+ local metadata_file="${bashEnvRead(ENV.DATA_DIR)}/${bashEnvRead(ENV.SESSION)}"
183
184
  [[ -f "\$metadata_file" ]] || return 1
184
185
  [[ "\$key" =~ ^[a-zA-Z0-9_-]+$ ]] || return 1
185
186
  local line
@@ -191,7 +192,7 @@ read_ao_metadata() {
191
192
 
192
193
  ao_cache_dir() {
193
194
  _ao_validate_env || return 1
194
- local d="\${AO_DATA_DIR}/.ghcache/\${AO_SESSION}"
195
+ local d="${bashEnvRead(ENV.DATA_DIR)}/.ghcache/${bashEnvRead(ENV.SESSION)}"
195
196
  mkdir -p "\$d" 2>/dev/null || return 1
196
197
  printf '%s' "\$d"
197
198
  }
@@ -237,7 +238,7 @@ ao_cache_write() {
237
238
  * 1. Caching repeated read-only commands (PR discovery, issue context)
238
239
  * 2. Auto-updating session metadata on PR creation
239
240
  *
240
- * Cache storage: $AO_DATA_DIR/.ghcache/$AO_SESSION/{key}.stdout + {key}.ts
241
+ * Cache storage: $ATHENE_DATA_DIR/.ghcache/$ATHENE_SESSION/{key}.stdout + {key}.ts
241
242
  * See D4-wrapper-cache-plan.md for full design rationale.
242
243
  */
243
244
  const GH_WRAPPER = `#!/usr/bin/env bash
@@ -296,7 +297,7 @@ _ao_redact_args() {
296
297
 
297
298
  # Best-effort JSONL tracing for agent-side gh invocations.
298
299
  log_gh_invocation() {
299
- local trace_file="\${AO_AGENT_GH_TRACE:-}"
300
+ local trace_file="${bashEnvRead(ENV.AGENT_GH_TRACE)}"
300
301
  [[ -z "\$trace_file" ]] && return 0
301
302
  command -v jq >/dev/null 2>&1 || return 0
302
303
 
@@ -314,11 +315,11 @@ log_gh_invocation() {
314
315
  --arg timestamp "\$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
315
316
  --arg cwd "\$PWD" \
316
317
  --arg operation "\$_ao_op" \
317
- --arg aoSession "\${AO_SESSION:-}" \
318
- --arg aoSessionName "\${AO_SESSION_NAME:-}" \
319
- --arg aoProjectId "\${AO_PROJECT_ID:-}" \
320
- --arg aoIssueId "\${AO_ISSUE_ID:-}" \
321
- --arg aoCallerType "\${AO_CALLER_TYPE:-}" \
318
+ --arg aoSession "${bashEnvRead(ENV.SESSION)}" \
319
+ --arg aoSessionName "${bashEnvRead(ENV.SESSION_NAME)}" \
320
+ --arg aoProjectId "${bashEnvRead(ENV.PROJECT_ID)}" \
321
+ --arg aoIssueId "${bashEnvRead(ENV.ISSUE_ID)}" \
322
+ --arg aoCallerType "${bashEnvRead(ENV.CALLER_TYPE)}" \
322
323
  --arg pid "\$\$" \
323
324
  --arg wrapperVersion "${WRAPPER_VERSION}" \
324
325
  --argjson args "\$args_json" \
@@ -343,7 +344,7 @@ log_gh_invocation "\$@"
343
344
  # result: hit | miss-stored | miss-write-failed | miss-negative | miss-error | passthrough
344
345
  log_ao_cache() {
345
346
  local result="\$1" cache_key="\$2" duration_ms="\${3:-0}" exit_code="\${4:-0}" ok="\${5:-true}"
346
- local trace_file="\${AO_AGENT_GH_TRACE:-}"
347
+ local trace_file="${bashEnvRead(ENV.AGENT_GH_TRACE)}"
347
348
  [[ -z "\$trace_file" ]] && return 0
348
349
  printf '{"timestamp":"%s","cacheResult":"%s","cacheKey":"%s","pid":%s,"durationMs":%s,"exitCode":%s,"ok":%s}\\n' \
349
350
  "\$(date -u +"%Y-%m-%dT%H:%M:%SZ")" "\$result" "\$cache_key" "\$\$" \
@@ -519,8 +520,8 @@ case "\$1/\$2" in
519
520
  update_ao_metadata agentReportedPrUrl "\$pr_url"
520
521
  # Append to prs field (comma-separated list of all PR URLs for this session).
521
522
  # Supports multiple PRs per session — same repo or different repos.
522
- _ao_meta_f="\${AO_DATA_DIR}/\${AO_SESSION}.json"
523
- [[ -f "\$_ao_meta_f" ]] || _ao_meta_f="\${AO_DATA_DIR}/\${AO_SESSION}"
523
+ _ao_meta_f="${bashEnvRead(ENV.DATA_DIR)}/${bashEnvRead(ENV.SESSION)}.json"
524
+ [[ -f "\$_ao_meta_f" ]] || _ao_meta_f="${bashEnvRead(ENV.DATA_DIR)}/${bashEnvRead(ENV.SESSION)}"
524
525
  if head -c1 "\$_ao_meta_f" 2>/dev/null | grep -q '{'; then
525
526
  existing_prs="\$(jq -r '.prs // empty' "\$_ao_meta_f" 2>/dev/null || echo "")"
526
527
  else
@@ -643,15 +644,15 @@ function buildNodeWrapper(name, realBinaryPath) {
643
644
  }
644
645
  /**
645
646
  * Shared Node.js snippet: updateAoMetadata function used by both gh and git wrappers.
646
- * Validates session, key, and AO_DATA_DIR before writing metadata.
647
+ * Validates session, key, and ATHENE_DATA_DIR before writing metadata.
647
648
  */
648
649
  const NODE_UPDATE_AO_METADATA = `\
649
650
  // ---------------------------------------------------------------------------
650
651
  // Metadata update (shared by gh/git wrappers)
651
652
  // ---------------------------------------------------------------------------
652
653
  function updateAoMetadata(key, value) {
653
- const aoDir = process.env["AO_DATA_DIR"] || "";
654
- const aoSession = process.env["AO_SESSION"] || "";
654
+ const aoDir = ${nodeEnvRead(ENV.DATA_DIR)} || "";
655
+ const aoSession = ${nodeEnvRead(ENV.SESSION)} || "";
655
656
  if (!aoDir || !aoSession) return;
656
657
 
657
658
  // Validate session — no path separators or traversal
@@ -785,8 +786,8 @@ if (key === "pr/create" || key === "pr/merge") {
785
786
  // Append to prs field — supports multiple PRs per session
786
787
  let existingPrs = "";
787
788
  try {
788
- const aoDir = process.env["AO_DATA_DIR"] || "";
789
- const aoSession = process.env["AO_SESSION"] || "";
789
+ const aoDir = ${nodeEnvRead(ENV.DATA_DIR)} || "";
790
+ const aoSession = ${nodeEnvRead(ENV.SESSION)} || "";
790
791
  if (aoDir && aoSession && /^[a-zA-Z0-9_-]+$/.test(aoSession)) {
791
792
  let metaFile = path.join(aoDir, aoSession + ".json");
792
793
  if (!fs.existsSync(metaFile)) metaFile = path.join(aoDir, aoSession);
@@ -1 +1 @@
1
- {"version":3,"file":"agent-workspace-hooks.js","sources":["../src/agent-workspace-hooks.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-workspace-hooks.js","sources":["../src/agent-workspace-hooks.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -10,6 +10,15 @@
10
10
  * Everything else has sensible defaults.
11
11
  */
12
12
  import { type ExternalPluginEntryRef, type LoadedConfig, type OrchestratorConfig } from "./types.js";
13
+ /**
14
+ * Fail loudly when a meta orchestrator's explicit scope references a project ID
15
+ * that is not in the registered set. Evaluated against the FULL global project
16
+ * registry (not a partial effective projection), so valid multi-project scopes
17
+ * load while genuine typos are rejected. Throws on the first unknown reference.
18
+ */
19
+ export declare function assertMetaScopeProjectsExist(metaOrchestrators: Record<string, {
20
+ scope?: unknown;
21
+ }> | undefined, knownProjectIds: string[]): void;
13
22
  /**
14
23
  * Collect external plugin configs from tracker, scm, and notifier inline configs.
15
24
  * These will be auto-added to config.plugins for loading.
@@ -33,7 +42,7 @@ export declare const DEFAULT_BUGBOT_COMMENTS_MESSAGE = "Automated review comment
33
42
  * Search for config file in standard locations.
34
43
  *
35
44
  * Search order:
36
- * 1. AO_CONFIG_PATH environment variable (if set)
45
+ * 1. ATHENE_CONFIG_PATH environment variable (if set)
37
46
  * 2. Search up directory tree from CWD (like git)
38
47
  * 3. Explicit startDir (if provided)
39
48
  * 4. Home directory locations
@@ -41,6 +50,15 @@ export declare const DEFAULT_BUGBOT_COMMENTS_MESSAGE = "Automated review comment
41
50
  export declare function findConfigFile(startDir?: string): string | null;
42
51
  /** Find config file path (exported for use in hash generation) */
43
52
  export declare function findConfig(startDir?: string): string | null;
53
+ /**
54
+ * Validate a WRAPPED config (one that carries its full `projects` map inline).
55
+ * Mirrors the global/flat-local builders by failing loud on a meta scope that
56
+ * references an unregistered project — validated against this config's own
57
+ * complete projects set. NOT folded into the shared `validateConfig`, because the
58
+ * flat-local builder calls validateConfig with a SINGLE-PROJECT projection where
59
+ * such a check would spuriously reject valid multi-project scopes (round-15).
60
+ */
61
+ export declare function validateWrappedConfig(raw: unknown): OrchestratorConfig;
44
62
  /** Load and validate config from a YAML file */
45
63
  export declare function loadConfig(configPath?: string): LoadedConfig;
46
64
  /** Load config and return both config and resolved path */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AA6cpB;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,kBAAkB,GAAG,sBAAsB,EAAE,CAwCjG;AA2HD;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,mFACsC,CAAC;AAiFnF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkE/D;AAoGD,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CA+B5D;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG;IACvD,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CA6BA;AAED,mCAAmC;AACnC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAqB/D;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,IAAI,kBAAkB,CAIrD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AA2ZpB;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,SAAS,EAClE,eAAe,EAAE,MAAM,EAAE,GACxB,IAAI,CAgBN;AA0GD;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,kBAAkB,GAAG,sBAAsB,EAAE,CAwCjG;AA2HD;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,mFACsC,CAAC;AAiFnF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmE/D;AAgHD,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAItE;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAmC5D;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG;IACvD,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAiCA;AAED,mCAAmC;AACnC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAqB/D;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,IAAI,kBAAkB,CAIrD"}
package/dist/config.js CHANGED
@@ -4,6 +4,7 @@ import { resolve, dirname, basename, join } from 'node:path';
4
4
  import { homedir } from 'node:os';
5
5
  import { parse } from 'yaml';
6
6
  import { z } from 'zod';
7
+ import { getEnvString, ENV } from './env.js';
7
8
  import { ConfigNotFoundError, ProjectResolveError } from './types.js';
8
9
  import { generateSessionPrefix } from './paths.js';
9
10
  import { getDefaultRuntime } from './platform.js';
@@ -197,6 +198,8 @@ const RoleAgentConfigSchema = z
197
198
  const ProjectConfigSchema = z.object({
198
199
  name: z.string().optional(),
199
200
  repo: z.string().optional(),
201
+ /** Short routing hint surfaced in the meta orchestrator catalog. */
202
+ description: z.string().optional(),
200
203
  path: z.string(),
201
204
  defaultBranch: z.string().default("main"),
202
205
  sessionPrefix: z
@@ -296,7 +299,26 @@ const LifecycleConfigSchema = z
296
299
  .default(300_000),
297
300
  })
298
301
  .default({});
299
- const OrchestratorConfigSchema = z.object({
302
+ const MetaScopeSchema = z.union([
303
+ z.literal("all"),
304
+ z.object({ projects: z.array(z.string()).min(1) }),
305
+ ]);
306
+ const MetaOrchestratorConfigSchema = z.object({
307
+ scope: MetaScopeSchema,
308
+ // Include newly-registered projects in this meta orchestrator's scope.
309
+ // NOTE (current behavior): scope is resolved live by `meta-status` and the
310
+ // dashboard, so new projects show there immediately; the running orchestrator's
311
+ // prompt catalog is a snapshot from `meta-start`, so it only refreshes on
312
+ // restart. (`reconcileMetaScopeIds` is the building block for future live
313
+ // prompt-refresh wiring.) With scope:'all' new projects are naturally in scope.
314
+ discover: z.boolean().default(false),
315
+ // Optional agent plugin override; defaults to the global default agent.
316
+ agent: z.string().optional(),
317
+ // Optional extra instructions appended to the meta orchestrator prompt.
318
+ rules: z.string().optional(),
319
+ });
320
+ const OrchestratorConfigSchema = z
321
+ .object({
300
322
  $schema: z.string().optional(),
301
323
  port: z.number().int().default(3000),
302
324
  terminalPort: z.number().int().optional(),
@@ -314,7 +336,58 @@ const OrchestratorConfigSchema = z.object({
314
336
  notifiers: z.record(NotifierConfigSchema).default({}),
315
337
  notificationRouting: z.record(z.array(z.string())).default({}),
316
338
  reactions: z.record(ReactionConfigSchema).default({}),
339
+ metaOrchestrators: z
340
+ .record(z
341
+ .string()
342
+ .regex(/^[a-zA-Z0-9_-]+$/, "meta orchestrator name must match [a-zA-Z0-9_-]+"), MetaOrchestratorConfigSchema)
343
+ .optional(),
344
+ })
345
+ .superRefine((value, ctx) => {
346
+ // `_meta` is the reserved on-disk parent for meta orchestrator sessions
347
+ // (projects/_meta/<name>/sessions/<name>.json). A real project keyed `_meta`
348
+ // would collide with that storage scope. `projects` is required but Zod runs
349
+ // object refinements even when a required key is absent, so guard against
350
+ // `undefined` — otherwise an omitted `projects:` would crash with a TypeError
351
+ // instead of surfacing Zod's clean "Required" error.
352
+ const projects = value.projects ?? {};
353
+ if (Object.prototype.hasOwnProperty.call(projects, "_meta")) {
354
+ ctx.addIssue({
355
+ code: z.ZodIssueCode.custom,
356
+ path: ["projects", "_meta"],
357
+ message: "'_meta' is a reserved project ID used for meta orchestrator storage; rename this project.",
358
+ });
359
+ }
360
+ // NOTE: meta-orchestrator explicit-scope project existence is intentionally
361
+ // NOT checked here — `value.projects` may be a partial projection (the
362
+ // flat-local path narrows to the single cwd project; the global path drops
363
+ // degraded projects), which would spuriously reject valid multi-project
364
+ // scopes. That check runs against the FULL registered project set via
365
+ // `assertMetaScopeProjectsExist` in the global-config load path.
317
366
  });
367
+ /**
368
+ * Fail loudly when a meta orchestrator's explicit scope references a project ID
369
+ * that is not in the registered set. Evaluated against the FULL global project
370
+ * registry (not a partial effective projection), so valid multi-project scopes
371
+ * load while genuine typos are rejected. Throws on the first unknown reference.
372
+ */
373
+ function assertMetaScopeProjectsExist(metaOrchestrators, knownProjectIds) {
374
+ if (!metaOrchestrators)
375
+ return;
376
+ const known = new Set(knownProjectIds);
377
+ for (const [metaName, meta] of Object.entries(metaOrchestrators)) {
378
+ const scope = meta?.scope;
379
+ if (!scope || scope === "all" || typeof scope !== "object")
380
+ continue;
381
+ const scoped = scope.projects;
382
+ if (!Array.isArray(scoped))
383
+ continue;
384
+ for (const projectId of scoped) {
385
+ if (typeof projectId === "string" && !known.has(projectId)) {
386
+ throw new Error(`Meta orchestrator '${metaName}' references unknown project '${projectId}'. Known projects: ${knownProjectIds.join(", ") || "(none)"}.`);
387
+ }
388
+ }
389
+ }
390
+ }
318
391
  // =============================================================================
319
392
  // CONFIG LOADING
320
393
  // =============================================================================
@@ -606,15 +679,16 @@ function applyDefaultReactions(config) {
606
679
  * Search for config file in standard locations.
607
680
  *
608
681
  * Search order:
609
- * 1. AO_CONFIG_PATH environment variable (if set)
682
+ * 1. ATHENE_CONFIG_PATH environment variable (if set)
610
683
  * 2. Search up directory tree from CWD (like git)
611
684
  * 3. Explicit startDir (if provided)
612
685
  * 4. Home directory locations
613
686
  */
614
687
  function findConfigFile(startDir) {
615
688
  // 1. Check environment variable override
616
- if (process.env["AO_CONFIG_PATH"]) {
617
- const envPath = resolve(process.env["AO_CONFIG_PATH"]);
689
+ const configPathOverride = getEnvString(ENV.CONFIG_PATH);
690
+ if (configPathOverride) {
691
+ const envPath = resolve(configPathOverride);
618
692
  if (existsSync(envPath)) {
619
693
  return envPath;
620
694
  }
@@ -675,6 +749,10 @@ function buildEffectiveConfigFromFlatLocalPath(configPath, _localParsed) {
675
749
  const globalConfig = loadGlobalConfig(globalConfigPath);
676
750
  if (!globalConfig)
677
751
  return null;
752
+ // Validate meta scopes against the FULL registry before projecting down to the
753
+ // single cwd project below (otherwise valid multi-project scopes would be
754
+ // rejected by validateConfig against the partial projects map).
755
+ assertMetaScopeProjectsExist(globalConfig.metaOrchestrators, Object.keys(globalConfig.projects));
678
756
  const canonicalProjectDir = (() => {
679
757
  try {
680
758
  return realpathSync(resolve(dirname(configPath)));
@@ -707,6 +785,7 @@ function buildEffectiveConfigFromFlatLocalPath(configPath, _localParsed) {
707
785
  notifiers: globalConfig.notifiers,
708
786
  notificationRouting: globalConfig.notificationRouting,
709
787
  reactions: globalConfig.reactions,
788
+ metaOrchestrators: globalConfig.metaOrchestrators,
710
789
  projects: {
711
790
  [projectId]: {
712
791
  ...project,
@@ -719,6 +798,10 @@ function buildEffectiveConfigFromGlobalConfigPath(configPath) {
719
798
  const globalConfig = loadGlobalConfig(configPath);
720
799
  if (!globalConfig)
721
800
  return null;
801
+ // Validate meta scopes against the FULL registry — including projects that may
802
+ // degrade (and thus be excluded from the effective `projects` map below) — so a
803
+ // scope referencing a temporarily-degraded but registered project still loads.
804
+ assertMetaScopeProjectsExist(globalConfig.metaOrchestrators, Object.keys(globalConfig.projects));
722
805
  const projects = {};
723
806
  const degradedProjects = {};
724
807
  for (const [projectId, entry] of Object.entries(globalConfig.projects)) {
@@ -757,6 +840,7 @@ function buildEffectiveConfigFromGlobalConfigPath(configPath) {
757
840
  notifiers: globalConfig.notifiers,
758
841
  notificationRouting: globalConfig.notificationRouting,
759
842
  reactions: globalConfig.reactions,
843
+ metaOrchestrators: globalConfig.metaOrchestrators,
760
844
  projects,
761
845
  });
762
846
  return { ...config, degradedProjects };
@@ -768,10 +852,23 @@ function buildEffectiveConfigFromGlobalConfigPath(configPath) {
768
852
  function findConfig(startDir) {
769
853
  return findConfigFile(startDir);
770
854
  }
855
+ /**
856
+ * Validate a WRAPPED config (one that carries its full `projects` map inline).
857
+ * Mirrors the global/flat-local builders by failing loud on a meta scope that
858
+ * references an unregistered project — validated against this config's own
859
+ * complete projects set. NOT folded into the shared `validateConfig`, because the
860
+ * flat-local builder calls validateConfig with a SINGLE-PROJECT projection where
861
+ * such a check would spuriously reject valid multi-project scopes (round-15).
862
+ */
863
+ function validateWrappedConfig(raw) {
864
+ const config = validateConfig(raw);
865
+ assertMetaScopeProjectsExist(config.metaOrchestrators, Object.keys(config.projects));
866
+ return config;
867
+ }
771
868
  /** Load and validate config from a YAML file */
772
869
  function loadConfig(configPath) {
773
- // Priority: 1. Explicit param, 2. Search (including AO_CONFIG_PATH env var)
774
- // findConfigFile treats AO_CONFIG_PATH as authoritative when present.
870
+ // Priority: 1. Explicit param, 2. Search (including ATHENE_CONFIG_PATH env var)
871
+ // findConfigFile treats ATHENE_CONFIG_PATH as authoritative when present.
775
872
  const path = configPath ?? findConfigFile();
776
873
  if (!path) {
777
874
  throw new ConfigNotFoundError();
@@ -784,9 +881,13 @@ function loadConfig(configPath) {
784
881
  ? applyWrappedLocalStorageKeys(path, parsed)
785
882
  : parsed;
786
883
  const config = isCanonicalGlobalConfig
787
- ? (buildEffectiveConfigFromGlobalConfigPath(path) ?? validateConfig(normalizedParsed))
884
+ ? // The canonical-global `normalizedParsed` carries the full registry, so the
885
+ // fallback must mirror the builder's "fail loudly on unknown meta scope"
886
+ // rule (validateConfig alone skips it). validateWrappedConfig validates
887
+ // scopes against the complete `projects` map — no flat-local projection.
888
+ (buildEffectiveConfigFromGlobalConfigPath(path) ?? validateWrappedConfig(normalizedParsed))
788
889
  : shape === "wrapped"
789
- ? validateConfig(normalizedParsed)
890
+ ? validateWrappedConfig(normalizedParsed)
790
891
  : (buildEffectiveConfigFromFlatLocalPath(path) ??
791
892
  validateConfig(normalizedParsed));
792
893
  // Set the config path in the config object for hash generation
@@ -810,9 +911,13 @@ function loadConfigWithPath(configPath) {
810
911
  ? applyWrappedLocalStorageKeys(path, parsed)
811
912
  : parsed;
812
913
  const config = isCanonicalGlobalConfig
813
- ? (buildEffectiveConfigFromGlobalConfigPath(path) ?? validateConfig(normalizedParsed))
914
+ ? // The canonical-global `normalizedParsed` carries the full registry, so the
915
+ // fallback must mirror the builder's "fail loudly on unknown meta scope"
916
+ // rule (validateConfig alone skips it). validateWrappedConfig validates
917
+ // scopes against the complete `projects` map — no flat-local projection.
918
+ (buildEffectiveConfigFromGlobalConfigPath(path) ?? validateWrappedConfig(normalizedParsed))
814
919
  : shape === "wrapped"
815
- ? validateConfig(normalizedParsed)
920
+ ? validateWrappedConfig(normalizedParsed)
816
921
  : (buildEffectiveConfigFromFlatLocalPath(path) ??
817
922
  validateConfig(normalizedParsed));
818
923
  // Set the config path in the config object for hash generation
@@ -848,5 +953,5 @@ function getDefaultConfig() {
848
953
  });
849
954
  }
850
955
 
851
- export { collectExternalPluginConfigs, findConfig, findConfigFile, getDefaultConfig, loadConfig, loadConfigWithPath, validateConfig };
956
+ export { assertMetaScopeProjectsExist, collectExternalPluginConfigs, findConfig, findConfigFile, getDefaultConfig, loadConfig, loadConfigWithPath, validateConfig, validateWrappedConfig };
852
957
  //# sourceMappingURL=config.js.map