Skip to content

I2760 — A scope entry is one path, and a path context would refuse is refused at start

Refuse at `start` every scope entry that the task record cannot hold as one path or that `context` would refuse, and stop a recorded entry that `context` cannot resolve from breaking `context` and every commit hook.

DONE wave 0 · p1 · implementation profile · parallel safe

Part of development-runtime — The runtime has a development surface.

Objective

Refuse at `start` every scope entry that the task record cannot hold as one path or that `context` would refuse, and stop a recorded entry that `context` cannot resolve from breaking `context` and every commit hook.

Why

On 2026-10-15 a task in the worktree of #1170 was started with a pasted prompt as its scope. `start` normalised the comma-separated entry as one path, because it held no `..` and did not start with `/`, then joined the normalised paths with spaces. The record wrote each word as a scope path, about 270 of them, and three of them were a lone `/`. From then on `majordomus context` died with `refused-path '/'` at the first of them, and the pre-commit hook, which runs `context`, refused every commit in that worktree. On 2026-10-16 the repair lane found it only by reading the record, and had to close the task to commit.

Current state

`start` refuses an entry that is empty, absolute or escapes the repository, but accepts one holding whitespace and then splits it into words. `context` calls mj_ctxd_target for each recorded scope path, and mj_ctxd_target exits the process on a path it refuses.

Desired state

`start` refuses, before writing anything, an entry holding whitespace and any entry `context` would refuse (absolute, escaping, or resolving outside the repository through a link), naming the entry and the remedy. mj_ctxd_refusal answers why a path is refused without exiting; mj_ctxd_target dies on that answer exactly as before; `context` prints a recorded entry it refuses as refused and goes on with the rest, so an old or hand-edited record degrades one line rather than the whole briefing.

Scope

  • lib/start.sh
  • lib/context.sh
  • lib/context_docs.sh
  • test/cases/3160_a_scope_entry_is_one_path.sh
  • .ai/repo/project/issues/I2760.yaml

Dependencies

None. This issue is a root of the graph.

Acceptance criteria

  • majordomus start refuses a scope entry holding whitespace with exit 2, writes no task record, and names the entry
  • majordomus start refuses a scope entry that resolves outside the repository through a symbolic link
  • majordomus context, over a recorded scope that names `/`, prints that entry as refused, still prints the other scope paths' documents, and exits 0
  • majordomus context resolve <outside path> still refuses with the same message and exit code
  • case 3160 fails against master without the change

Validation

  • bash test/run.sh 3160_a_scope_entry_is_one_path 04_start_check
  • bin/majordomus plan validate

Evidence required

  • scope_entry_case

Evidence

coverstypecommandresultat commit
scope_entry_casetestbash test/run.sh --no-skips 3160_a_scope_entry_is_one_path 04_start_check3160 and 04 ok, 0 skipped (code since 71474ebacc3, an ancestor of 4a4573690f8; re-run at 4a4573690f8)4a45736

Timeline

started
2026-10-17T18:25:28Z
verified
2026-10-17T18:25:39Z
completed
2026-10-17T18:25:46Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I2760.yaml. Read it back with majordomus plan show I2760.

Searches the titles and descriptions of every page this site publishes.