@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.
- package/dist/agent-workspace-hooks.d.ts +3 -3
- package/dist/agent-workspace-hooks.d.ts.map +1 -1
- package/dist/agent-workspace-hooks.js +22 -21
- package/dist/agent-workspace-hooks.js.map +1 -1
- package/dist/config.d.ts +19 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +116 -11
- package/dist/config.js.map +1 -1
- package/dist/env.d.ts +157 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +187 -0
- package/dist/env.js.map +1 -0
- package/dist/events-db.d.ts.map +1 -1
- package/dist/events-db.js +2 -1
- package/dist/events-db.js.map +1 -1
- package/dist/feature-flags.d.ts.map +1 -1
- package/dist/feature-flags.js +3 -1
- package/dist/feature-flags.js.map +1 -1
- package/dist/gh-trace.d.ts.map +1 -1
- package/dist/gh-trace.js +4 -3
- package/dist/gh-trace.js.map +1 -1
- package/dist/global-config.d.ts +29 -8
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +13 -4
- package/dist/global-config.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/lifecycle-manager.d.ts.map +1 -1
- package/dist/lifecycle-manager.js +101 -1
- package/dist/lifecycle-manager.js.map +1 -1
- package/dist/meta-orchestrator-config-writer.d.ts +13 -0
- package/dist/meta-orchestrator-config-writer.d.ts.map +1 -0
- package/dist/meta-orchestrator-config-writer.js +22 -0
- package/dist/meta-orchestrator-config-writer.js.map +1 -0
- package/dist/meta-orchestrator-prompt.d.ts +16 -0
- package/dist/meta-orchestrator-prompt.d.ts.map +1 -0
- package/dist/meta-orchestrator-prompt.js +87 -0
- package/dist/meta-orchestrator-prompt.js.map +1 -0
- package/dist/meta-scope.d.ts +38 -0
- package/dist/meta-scope.d.ts.map +1 -0
- package/dist/meta-scope.js +47 -0
- package/dist/meta-scope.js.map +1 -0
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +3 -2
- package/dist/observability.js.map +1 -1
- package/dist/paths.d.ts +18 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +37 -1
- package/dist/paths.js.map +1 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +4 -3
- package/dist/platform.js.map +1 -1
- package/dist/prompt-builder.d.ts +2 -2
- package/dist/prompt-builder.d.ts.map +1 -1
- package/dist/prompt-builder.js +2 -2
- package/dist/prompts/meta-orchestrator.md.js +4 -0
- package/dist/prompts/meta-orchestrator.md.js.map +1 -0
- package/dist/prompts/orchestrator.md.js +1 -1
- package/dist/prompts/orchestrator.md.js.map +1 -1
- package/dist/runtime-orphans.d.ts +96 -0
- package/dist/runtime-orphans.d.ts.map +1 -0
- package/dist/runtime-orphans.js +158 -0
- package/dist/runtime-orphans.js.map +1 -0
- package/dist/session-manager.d.ts +16 -0
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +611 -46
- package/dist/session-manager.js.map +1 -1
- package/dist/spawn-collision.d.ts +23 -0
- package/dist/spawn-collision.d.ts.map +1 -0
- package/dist/spawn-collision.js +26 -0
- package/dist/spawn-collision.js.map +1 -0
- package/dist/types.d.ts +103 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +22 -1
- package/dist/types.js.map +1 -1
- package/package.json +10 -9
- 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
|
|
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: $
|
|
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":"
|
|
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="
|
|
85
|
-
local 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="
|
|
100
|
-
local 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="
|
|
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="
|
|
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: $
|
|
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="
|
|
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 "
|
|
318
|
-
--arg aoSessionName "
|
|
319
|
-
--arg aoProjectId "
|
|
320
|
-
--arg aoIssueId "
|
|
321
|
-
--arg aoCallerType "
|
|
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="
|
|
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="
|
|
523
|
-
[[ -f "\$_ao_meta_f" ]] || _ao_meta_f="
|
|
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
|
|
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 =
|
|
654
|
-
const aoSession =
|
|
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 =
|
|
789
|
-
const aoSession =
|
|
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":"
|
|
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.
|
|
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 */
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
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
|
|
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.
|
|
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
|
-
|
|
617
|
-
|
|
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
|
|
774
|
-
// findConfigFile treats
|
|
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
|
-
?
|
|
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
|
-
?
|
|
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
|
-
?
|
|
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
|
-
?
|
|
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
|