Commit Graph
1780 Commits
Author SHA1 Message Date
haelyra 6038e89904 Merge PR #3428: validate and sync every catalog project tree entry 2026-10-10 17:37:24 -04:00
haelyra 3b9fc44e14 Merge PR #3445: launch formatter shims safely on Windows 2026-10-10 17:37:18 -04:00
haelyra 27875bfd02 Merge PR #3444: track OpenCode skill runs and report measurement gaps 2026-10-10 17:37:11 -04:00
haelyra b40c9d5289 Merge PR #3470: detect Dart and structurally identify Flutter dependencies 2026-10-10 17:36:59 -04:00
haelyra 2a75aaa803 fix(orchestration): integrate supported Codex worker invocation (#3434) 2026-10-10 17:36:45 -04:00
haelyra 94ed702344 fix(commands): preserve string argument hints from PR 3472 2026-10-10 17:36:33 -04:00
haelyra a4bf7a45ca fix(sanitizer): integrate unreadable audit with portable filename quoting 2026-10-10 17:36:33 -04:00
haelyra dd527e3613 Merge PR #3443: match nested TypeScript diagnostics on Windows 2026-10-10 17:36:28 -04:00
haelyra 423edc1d46 Merge PR #3441: initialize OpenCode home hooks once 2026-10-10 17:36:05 -04:00
haelyra b3c3b77561 Merge PR #3440: observe active worktree changes 2026-10-10 17:35:52 -04:00
haelyra de39adfa9d Merge PR #3322: correct Kiro steering inclusion contract 2026-10-10 17:35:51 -04:00
haelyra 7753a55d08 Merge PR #3416: route hook state through Claude profiles
Preserve the explicit shared ~/.claude project root already shipped on main. Canonicalize macOS temporary workflow fixture paths.
2026-10-10 17:35:45 -04:00
haelyra b79346d16b feat(frontend): integrate rendered evidence contract from PR 2814 2026-10-10 17:35:32 -04:00
haelyra 82a3913da6 Merge PR #3414: isolate state-store CLI homes 2026-10-10 17:34:52 -04:00
haelyra df50d56146 Merge PR #3283: serialize session alias mutations 2026-10-10 17:34:44 -04:00
chenhz01 3af000e143 hooks: first operand after -- is still the sed script when no script option was given
Greptile P1: sedScriptParts stopped at -- and discarded the remaining
operands, so 'sed -- <script>' skipped script collection entirely. GNU sed
4.9 (verified): with no -e/--expression anywhere, the first operand after --
is the script and an s///e in it still executes.

The operands after -- are now collected as positionals, so the existing
first-positional-becomes-script rule applies. Operands after the script stay
file names (data). 2 regression tests pin both sides. Suite: 812/812.
2026-10-11 03:55:27 +08:00
chenhz01 95964ee623 hooks: block escaped sed exec fragments conservatively; decompose sed readers
Greptile P1 findings (both verified by running GNU sed against the hook):

1. Escaped replacements evade the check: GNU sed decodes \xHH, \oOOO, \dNNN,
   case operations and unknown escapes like \g before executing an s///e
   replacement or e operand. Scanning the raw text let \x67it decode to git.
   Decoding that surface faithfully is out of scope, so any backslash in an
   exec-bearing fragment now throws UnsupportedSedEscape and the hook blocks
   with an explicit reason — mirroring the existing env -S escape precedent
   instead of pretending to interpret sed. Escaped-newline continuations of an
   e operand are refused by the same check.

2. Continued commands went unchecked: the e operand reader stopped at every
   newline, but GNU sed joins escaped newlines into one operand. Now covered
   by the same conservative refusal.

Also decomposes the sed readers into sub-50-line helpers per the repository
function-size rule (AGENTS.md): readSedDelimited, readSedCommand,
readSedExecute, readSedLineOperand, assertSedLiteral.

5 regression tests pin the escape paths and the benign boundary (a backslash
in a non-executing script stays data). Suite: 810/810.
2026-10-11 03:52:06 +08:00
chenhz01 34a7f41539 hooks: parse sed options through the whole argv — later -e scripts still execute
CodeRabbit security review (Major, CWE-693) correctly identified that GNU sed
collects -e/--expression scripts from any argv position: a script option after
positional operands is still executed, so stopping the option walk at the first
positional let an e-flagged script hide behind it.

Verified against GNU sed 4.9 before fixing:
- 'sed -e s/x/y/ - -e s/y/X/e' runs X (the later -e executes)
- with any script option present, every positional is a file operand

sedScriptParts now walks the full argv, collects scripts from all -e/
--expression positions, and only promotes the first positional to the script
when no script option was given. Unknown options after positionals still fall
back to the opaque default.

4 regression tests pin the reported bypass paths (suite: 805/805).
2026-10-11 03:38:02 +08:00
chenhz01 ffe0e36d46 hooks: model GNU sed execution — script and file operands are data, e/s///e are shell receivers
Ported from the #3051 discussion (test intent, not the old scanner):

- A confidently-parsed sed invocation whose script contains no execution
  construct is a pure text transformation: the script operand and every file
  operand are data. This removes the specific false positives where file names
  or non-executing scripts merely containing 'git ...' were blocked.
- The GNU sed `e` command (bare or with operand) and the `s` command with the
  `e` flag run text through the shell. Their literal fragments (the s
  replacement, the e operand) and any piped/redirected source are scanned as
  real shell source, closing the `printf x | sed 's/x/git commit --no-verify/e'`
  gap reported on 2026-10-09.
- Anything the literal parser cannot confidently read (addresses it cannot
  consume, -f script files, -i suffix ambiguity, unknown options, expansion
  residue) falls back to today's opaque default. No behavior changes for
  unmodeled launchers.
- shell-scan.js is untouched and remains the canonical scanner.

Tests: 14 focused cases ported from the #3051 litmus set; full hook suite
801/801.
2026-10-11 03:15:36 +08:00
Dante 53afd058be Merge remote-tracking branch 'origin/main' into fix/3488-generation-pricing 2026-10-11 01:04:12 +08:00
Dante 27c3ce1c10 fix(hooks): price Claude 5.5 per deduplicated request 2026-10-11 01:04:11 +08:00
Tivonsico 1ad235fdfe fix: report explicitly disabled summaries as skipped 2026-10-11 00:36:27 +08:00
Tivonsico 71bf78796f fix: keep session summaries within the lifecycle deadline 2026-10-11 00:15:12 +08:00
Matt Van Horn 5ec23e8e3d fix: reconcile skill-host-compat with current main
Drop the duplicate ECC_PREPUSH_RUN_CHECKS key now that main sets it,
refresh the skill-triggers registry digest, classify skill-host-compat
for pi/core, and bump the Turkish AGENTS.md counts the catalog sync
does not cover.
2026-10-10 07:33:04 -07:00
Matt Van Horn e128f4398b Merge branch 'main' into cursor/skill-host-compat-ci-10d0 2026-10-10 07:09:43 -07:00
calm 2cb50cea63 test: isolate Qoder context limits 2026-10-10 21:02:19 +08:00
calm f124f339af test: honor Qoder hook timeout 2026-10-10 20:57:10 +08:00
calm 92728a07bc test: harden Qoder plugin verification 2026-10-10 20:42:11 +08:00
calm 2d9e6977dc feat: add native Qoder plugin support 2026-10-10 20:11:00 +08:00
Geronimo b40f0f33d7 fix: make concurrency test genuinely overlapping with continuous validity probes
Each writer performs 30 write rounds to widen the race window. Drop the vacuous exitCode liveness assert and the swallowing mid-flight read; instead every wait-loop poll reads and validates the state, so torn reads fail loudly.
2026-10-10 14:29:59 +05:30
Geronimo cd1a253d61 fix: review feedback on installer slice tests
Assert dry-run install writes nothing under projectRoot too (cursor target writes there, not home). Rewrite the concurrent writeInstallState test with genuinely overlapping writers via async spawn plus done-file rendezvous, including a mid-flight read; sanitize rendezvous filenames for Windows.
2026-10-10 14:12:37 +05:30
Geronimo e1546ed45d fix: installer slice from PR #3120 review (Haelyra)
Honor ECC_DRY_RUN=1 in install and repair arg parsing (previously only --dry-run flag worked, so ecc --dry-run install/repair silently performed real writes). Make writeInstallState atomic via writeFileAtomic (O_EXCL staging, fsync, cleanup on failure, atomic rename preserving previous state). Add writeInstallState failure/concurrency/symlink regression tests and disposable-home CLI dry-run regression tests for both global and subcommand forms.
2026-10-10 13:56:00 +05:30
Yann Roberto 310441dcc8 fix(context): honor current-task requests after examples
Track illustrative scopes and retain their connectors so a contrastive
request or rejection for the current task ends the preceding example.
Preserve complete skill aliases, outer discussion guards, quoted task
qualifiers, and indirect citation protection for scored admission.

Invalidate older routing receipts and add resolver/launcher regressions
for request ordering, scope boundaries, aliases, and the reported P1.
2026-10-10 14:15:37 +08:00
Yann Roberto a70b9795d1 fix(context): keep illustrative skill requests on the proposal path
Treat example-framing prefixes as indirect citations before checking
rejections, preserving genuine requests around illustrative instructions.
Keep e.g. together during clause splitting without rewriting e.g.js tokens.

Bump routing policy to v10 to invalidate v9 selections that loaded example
context. Cover resolver, launcher, instruction ordering, and receipt reuse.
2026-10-10 13:09:48 +08:00
Yann Roberto b5a8bf0603 fix(context): preserve skill requests after task preambles
Allow neutral imperative task preambles before an explicit skill request
without admitting final bare mentions, questions, or subject-led reports.
Keep rejection-list scoping intact and recognize must/ought questions.

Bump routing policy to v9 so an empty v8 receipt is reconsidered. Cover
resolver and launcher behavior and document the affected routing helpers.
2026-10-10 12:46:51 +08:00
Yann Roberto 763acfbce0 fix(context): require scoped evidence for automatic skill loading
Keep follow-up questions and reported instructions on the proposal path by
requiring recognized scopes and a direct request prefix for exact admission.
Preserve grouped rejections, personal negation, and genuine directives around
indirect discussion. Invalidate v7 receipts with routing policy v8.

Cover both Greptile reproductions and neighboring resolver/launcher cases,
including unlisted wording, nested reports, and grouped negative lists.
2026-10-10 11:57:53 +08:00
Yann Roberto edeb7b9e9a fix(context): scope compound directives and preserve imperative requests
Limit negation to each independent directive after comma, and, or but.
Accept imperative requests with question punctuation while preserving true
questions, reported speech, and ordered rejections. Bump routing policy to
v7 so prior empty selections are reconsidered.

Add resolver and launcher regressions for the individual cases and their
combinations, including cached selections and actual context injection.
2026-10-10 11:23:53 +08:00
34a97fa898 fix: reject unsupported env split-string escapes
Validate env -S and --split-string escape syntax before shell scanning or
opaque fallback. Preserve literal single-quoted data and charge each
validation character against the shared input-proportional work budget.

Verified 787 focused cases and 290 real Git/config, harmless native env
and registered-routing controls. Keeps the prior paid-copy protection.

Co-authored-by: Nguyen Thanh Dat <ntdat812.dev@gmail.com>
Co-authored-by: Davemaina1 <dmain7015@gmail.com>
2026-10-09 21:04:20 -04:00
993b5f230f fix: guard literal Git hook redirects and env split arguments
Carry forward bounded literal include/includeIf configuration capabilities
and env -S/--split-string words from PRs #2858 and #2897. Charge array
copy and expansion work before allocation to preserve the shared quota.

Verified 731 hook cases and 60 real Git/config and registered-route
controls. Dynamic remainder and original full source PRs remain held.

Co-authored-by: Nguyen Thanh Dat <ntdat812.dev@gmail.com>
Co-authored-by: Davemaina1 <dmain7015@gmail.com>
2026-10-09 20:41:09 -04:00
montjeffrey 92947a68df Merge upstream/main into feat/gateguard-fewer-round-trips
Resolve six conflicts:
- hooks/hooks.metadata.json: keep this branch's gateguard description and
  fingerprint, add upstream's hookify-runtime entries.
- package.json: keep both gateguard-report.js and github-coordination.js.
- scripts/hooks/gateguard-fact-force.js, tests/hooks/gateguard-fact-force.test.js,
  skills/gateguard/SKILL.md: upstream added a simpler session denial cap; this
  branch already has the fuller one (cap threaded through
  markCheckedAndCountDenial, malformed-value warning, miss and target notes),
  so keep it. Upstream's taskset and su wrapper handling, fail-closed
  recursion limit and soft-hyphen sanitising merged cleanly and their tests pass.
- manifests/context-packs/skill-triggers@1.json: take upstream's file and
  recompute registryDigest for the merged registry.
2026-10-09 20:38:25 -04:00
haelyra aac9b3d34b fix: preserve activity errors, asset bytes and runner summaries
Treat non-2xx activity responses as feed errors, preserve non-Markdown Copilot agent assets, and apply the reviewed reference escape parity correction with regenerated bindings. Allow the test runner to drain piped output on its existing success or failure exit status. Validate installed workflows and bounded real Node20/24 pipe regressions.
2026-10-09 19:33:37 -04:00
haelyra 984d4f0701 fix: preserve Hookify Windows missing-device identity
Match the Windows missing volume-serial exception while retaining strict reported-device, inode, ownership, permission, link and snapshot checks. Add loader warning/block and race regression controls with isolated platform metadata injection.
2026-10-09 19:10:06 -04:00
montjeffrey 335f329618 test(context): pin recovery from a partial index file and generation-bound content
- A build interrupted while writing the index leaves a partial file under
  its digest name before the pointer exists. The next build rejects those
  bytes ("content changed under its digest") and cannot repair the index.
- A skill edited after the entries are read leaves an index that still
  matches the stored generation, and the next build reports that
  generation stale. This pins the current behavior: the index is bound to
  the generation, not to live sources.
2026-10-09 18:57:52 -04:00
haelyra 5981dd7092 fix: complete reviewed integration workflows and safety checks 2026-10-09 18:54:39 -04:00
montjeffrey 8dc5fe3082 Merge feat/gateguard-fewer-round-trips into feat/gateguard-question-effectiveness
Bring in the #3248 gate change and its upstream/main merge so this
evaluation branch is based on current main and applies without conflicts.
2026-10-09 18:50:46 -04:00
haelyra 0cb1476f9d fix: pin and bound Hookify rule reads
Open with supported no-follow and nonblocking flags before relying on file metadata. Validate descriptor, pathname and rule-directory consistency before and after reading at most64KiB plus one overflow byte. Reject observed replacement, mutation, premature EOF and non-regular files, and close descriptors on every outcome.

Add12 race and I/O regressions. Keep the Hermes uppercase protected-file fixture real on case-sensitive filesystems and verify that the installed guard still permits first-time creation.

Validation: full6688 reported tests across347 files,12 race tests, full80% coverage gates, scoped Hookify coverage, installed Hookify and Hermes workflows, packed artifact lifecycle, lint, signatures and IOC.
2026-10-09 17:54:01 -04:00
montjeffrey 64ac61e6a3 test(carriers): pin member calls and deeply nested computed arguments
Two first-round review findings were never addressed, and both reproduce
on the current head:

- records.require('./label'), obj?.import('./x') and obj . require('./y')
  are method calls, but the call pattern's word boundary is satisfied by
  the dot, so a self-contained object method fails every projection for a
  file the script never loads.
- The dynamic-argument pattern allows one level of nested parentheses, so
  require(path.join(__dirname, getName())) produces no dynamic warning
  while require(getName()) does.

Control: a genuine require beside the member calls is still a dependency.
2026-10-09 17:50:38 -04:00
montjeffrey 253c051dbf test(carriers): pin CommonJS require candidates, regex after a block, and non-import from
Review on dd14493e found four more ways the closure gate misjudges a
carrier, each reproduced against that head:

- require('./helper') resolves when only helper.cjs or helper.mjs is
  planned, but Node's CommonJS search tries only .js, .json and .node.
- In `if (ok) {} /"/.test(text); require(...)` the regex after the block
  is read as division and its quote swallows the require.
- `obj.\nif(x) / 2` is a method call, but the condition check only saw
  the character immediately before `if`, so the division read as a regex
  and swallowed a later require. Introduced by the previous fix.
- A tagged template named `from` was recorded as an import; with exact
  import resolution it now fails a carrier that never loads that path.
  Introduced by the previous fix.

Controls: an extensionless require still resolves to a .json file, and a
template literal passed to import() is still a dependency.
2026-10-09 17:46:02 -04:00
haelyra ba0520340f fix: reconcile reviewed sources and generated integration surfaces 2026-10-09 17:27:37 -04:00
haelyra b6e2cfe5e4 merge: preserve tested installer extraction 3187 and Copilot ownership fixture 2026-10-09 17:05:03 -04:00