The guided installer asks how ECC hooks should run, but that consent
lived only in the wizard path. Running install-apply directly with a
profile that includes hooks-runtime still materialized the hook runtime
with no disclosure and no decision.
Gate the apply layer instead, so every entry point is covered:
- disclose the six hook capability groups when a plan would materialize
the hook runtime, and refuse to apply until the caller decides
- --enable-hooks confirms the hook runtime; --no-hooks installs the rest
of the selection without it and records the reduced module closure in
install-state
- surface the pending decision as a dry-run warning
- show the same capability disclosure in the guided installer's plan
preview, so the wizard's hook question states what it is asking about
Plans that never materialize hooks (Kimi, --profile minimal,
--without baseline:hooks) are unaffected and need no flag. Repair and
uninstall operate on already-recorded state and stay unchanged.
The capability taxonomy and the held-materialization behavior come from
Samarjeet Singh Tomar's PR #2634, reworked to fit the single-decision
consent model that shipped with the guided installer in #2649.
Co-Authored-By: Samarjeet Singh Tomar <samar_tomar@hotmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The context signal always rendered "N% of <window> window", including when
the window size was the assumed 200k default rather than a detected value.
On a 1M session whose transcript carries no [1m] marker, that produced
lines like:
[StrategicCompact] Context ~194k tokens (97% of 200k window)
while actual usage was ~19%. The user compacts on a false alarm, loses
context, and the resulting quality drop reads as a model regression.
The gap is structural: the context threshold defaults to 80% of the
window (160k on 200k), so the signal fires precisely in the 160k-200k
band where the size cannot be determined — above 200k the observed-tokens
fallback correctly infers 1M, and below 160k nothing fires.
Model id alone cannot close this. A tier may ship both a 200k and a 1M
variant under one id, so neither the known-family table nor a new entry
can distinguish them, and the transcript records no window field.
So stop asserting what isn't known: resolveContextWindow() now reports
whether the size was detected (env override, [1m] marker, known family,
or observed tokens > 200k) or assumed, and the hook omits the percentage
and window label when it was assumed. The token count, threshold, and
firing behaviour are unchanged.
resolveContextWindowTokens() keeps its existing signature and semantics.
Note: 3 pre-existing failures in tests/hooks/suggest-compact.test.js
reproduce identically on unmodified main and are untouched here.
Following the hermes/openclaw (#2433) and kimi (#2441) adapter recipe.
What's included (adal-project adapter, project kind, ./.adal root, same
shape as kimi-project/joycode-project):
- scripts/lib/install-targets/adal-project.js — 10-line project-kind
adapter targeting ./.adal
- Registry + helpers platform-ownership wiring
- adal target on the 5 shared modules (rules-core, agents-core,
commands-core, platform-configs, workflow-quality) +
SUPPORTED_INSTALL_TARGETS + legacy-compat module
- .adal in platform-configs paths
- Both schema enums (install-modules, ecc-install-config), npm files
allowlist, installer help text, .adal/README.md stub
AdaL (adalagent.ai) is a terminal-based AI coding agent (by SylphAI)
built on AdalFlow, with native MCP support and project-scoped config
under ./.adal/ (skills, custom tools, memory) plus a root-level
AGENTS.md instructions file — matching the shape ECC already installs
into other AGENTS.md-based harnesses (Codex, OpenCode, Kimi).
Verified: full suite matches main's baseline (3334 passed, same
pre-existing failures unrelated to this change — OpenCode build/npm-pack
surface tests requiring build tooling not present in this sandbox);
catalog check passes (67 agents / 94 commands / 281 skills); dry-run
resolves Target: adal / Adapter: adal-project / root ./.adal with all 5
modules planned; doctor reports OK after a real install; uninstall
cleanly reverses all 458 operations.
Co-Authored-By: AdaL <adal@sylph.ai>
cost-estimate.js carries its own copy of the stale Opus/Haiku/Sonnet rate
table already reported in #2574, but grepping every .js/.json/.md file
outside node_modules turns up zero callers besides its own test. It was
added in 940135e alongside the statusline observability hooks and never
wired into any of them.
The maintainer's comment on #2656 named two acceptable outcomes: remove
the unused duplicate, or share one rate source with the live tracker.
cost-tracker.js's own fix (#2574) has not landed yet, so sharing its
table now would import numbers that are still wrong. Removing the dead
file is the smaller, immediately-correct step.
Fixes#2656
hasMarkerBlock previously swallowed every read/open error and returned
false, so an unreadable AGENTS.md (EACCES, EMFILE, EISDIR, ...) made
detectLegacyCodexSync report a clean Codex home instead of an
indeterminate inspection result. The fallback path could then skip
legacy cleanup and exit 0 with legacy artifacts still in place.
Restrict the catch to ENOENT (a missing file legitimately means no
marker block) and rethrow everything else. detectLegacyCodexSync
already propagates from hasMarkerBlock, so callers now see the actual
inspection error instead of a misleading 'no marker'.
Regression test in tests/lib/codex-legacy-sync.test.js makes a
detectLegacyCodexSync call against an unreadable AGENTS.md and asserts
that it throws something other than ENOENT, plus a sanity check that
a missing AGENTS.md still reads as no-marker.
Restrict the automatic `uninstall` legacy Codex sync fallback to homes
that have a legacy ownership manifest (`~/.codex/ecc/legacy-sync-state.json`).
Marker-only AGENTS.md files are no longer auto-detected as legacy installs,
so a normal `uninstall` will not silently modify user-owned instructions.
The explicit `--legacy-codex-sync` flag still handles marker-only and
manifest-backed cleanup.
Also:
- Track the AGENTS.md path in removedPaths when a marker block is removed.
- Refactor codex home resolution into a helper.
- Add regression tests for marker-only auto vs. explicit behavior.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Tighten uninstall auto-detection so it only falls back to the legacy
sync-ecc-to-codex.sh path when there is an ownership manifest
(~/.codex/ecc/legacy-sync-state.json) or an ECC marker block in
~/.codex/AGENTS.md. Previously a clean Codex home with unrelated prompt
files could be misclassified as a legacy install, causing uninstall to
skip normal install-state reconciliation and exit with a partial warning.
Also make the no-state fallback return 'not-found' when there is no
marker to remove and no candidate files to clean, and make explicit
--legacy-codex-sync report the same on a clean home.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
OpenCode natively uses ~/.config/opencode per XDG conventions. The
install target was writing to ~/.opencode, which only worked on systems
where that path happened to be symlinked to ~/.config/opencode. The MCP
inventory reader already looked in ~/.config/opencode, so the installer
and reader were inconsistent.
Use no-follow file descriptors for legacy Codex snapshots, verification, restoration, and marker cleanup. Quarantine candidate removals and verify inode identity before deletion.
Carry the lifecycle runner as a verified artifact so privileged release workflows never dynamically check out and execute an output-selected revision.