Skip to content

Added intelligence source to own the project's sources entries - #29

Merged
dzykovic merged 3 commits into
mainfrom
feature/source-command
Sep 8, 2026
Merged

dzykovic merged 3 commits into
mainfrom
feature/source-command

Conversation

@dzykovic

@dzykovic dzykovic commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

sources: was the one engine-readable block with no command behind it. package add / package remove own its .intelligence/ entries; every other entry — a monorepo's per-component directories, a pack developed inside the repository that ships it — was added by editing the manifest by hand, and the engine's own unsynced-directory warning asked for exactly that edit.

That hand edit has no gate, and four spellings fail silently after a sync that still reports IS_STATUS=ok: an absolute path (the engine resolves every entry as $REPO_ROOT/<entry>, so it matches nothing and is skipped), a path leaving the repository (it renders, but repo_rel_link_var returns nothing outside the root, so AGENTS.md carries bare names instead of links), a path under the CLI-managed store, and a path a double-quoted YAML scalar cannot carry verbatim.

This adds intelligence source add|remove|list as the editor of the project's own entries, and closes two defects in the primitives it exposes.

Placement is the command's work. Adapters copy sources in order and the last write wins, so an entry's position decides which artifact survives. add appends by default — the end of a section is the project's own territory, where a directory the project added wins over every installed package. --first / --last / --before <entry> / --after <entry> place an entry explicitly; the anchored forms are how content that should behave like a package lands after the store entries and ahead of the project's own. Adding a listed entry is a no-op; adding it with a position moves it. Every mutation prints the resulting order.

One definition, both directions. source_entry_problem classifies an entry; source add refuses through it before writing, and status --check now reports through it what a hand edit already placed — previously such an entry was accepted as "an optional directory that does not exist yet".

Defects closed in the exposed primitives. Presence was a substring search over the whole manifest, correct only for its single caller's .intelligence/packages/@scope/name/<section> shape: the same directory could not serve two sections (shared/prompts under both rules: and agents:), and a bare - docs/api entry blocked adding docs. It is now exact and section-scoped, read through the engine's own list parser so the CLI sees exactly what the engine will render. Separately, _qmap_stage now drops the staged file and refuses when its editor exits non-zero, instead of aborting mid-command and leaving a .cli.tmp behind.

Design record: decisions/0009-add-source-as-the-manifest-sources-editor.md.

Type of change

  • CLI lifecycle or package behavior
  • Sync engine or adapter
  • Rule, agent, or skill content
  • Documentation
  • Refactor with no behavior change

Public CLI check

  • Uses only the established groups: init, sync, update, upgrade, package, source, adapter, status, registry
  • Keeps preview/apply behavior explicit for planned writes
  • Covers automatic project alignment and CI refusal when project schema/content can change
  • Keeps fresh-clone package restoration behind intelligence sync

Verification

  • bash cli/tests/verify.sh reports verify ok and skipped nothing this change needed
  • intelligence status --check succeeds in the relevant fixture/project
  • A second intelligence sync produces no unexpected diff
  • Adapter changes were checked against the real tool format and preserve hand-authored sibling files
  • User-facing docs and examples use the current public command groups

Versioned artifacts

  • The PR records its change under one concrete CHANGELOG.md version; there is no [Unreleased] section or duplicated release date
  • The current engine/VERSION release state was checked: append while pending, or select the next SemVer after publication
  • If a new version was selected, every example's schema_version and exact @ainova-systems/sync pin changed with it
  • No stable release is implied or published without owner approval

Notes for reviewers

source is a new group, added deliberately. The first box above is checked against the surface this PR establishes: decisions/0009 records why the sources: block needs an owner for its project entries, and intelligence/rules/cli.md, CONTRIBUTING.md and this template were updated in the same change. package, adapter and registry each already own their block; sources: was the exception.

Why add appends rather than inserting ahead of project entries. Inserting before the project's own entries is right for exactly one case — a pack dogfooded in its own repository, which must override the installed package without overriding the project — and wrong for the other case the command exists for. examples/dotnet-api-with-react-frontend fixes the monorepo order as intelligence/rules then backend/intelligence/rules: component sources come after the root and deliberately override it. Nothing distinguishes the two automatically — both paths sit outside .intelligence/, and a package is an ordinary directory with no manifest of its own. The dogfooding case is one --before away.

No preview/apply mode. Like registry add and adapter enable, this is a single bounded manifest write with no plan to preview; it prints the resulting order so the effect is visible without a second command, and remove is the inverse.

No adapter changes. The engine edit is one line in warn_unsynced, which now names the command instead of asking for a hand edit; it falls back to the old wording when the engine runs without IS_CLI.

Test coverage. New cli/tests/e2e-sources.sh (registered in SUITES) covers placement, the move-on-explicit-position path, every refusal with a byte-identical manifest afterwards, the status --check report, and a render proving the wired directories reach AGENTS.md in list order. unit-manifest.sh gains the primitive-level cases; both presence defects were reproduced against the old semantics before the fix.

`sources:` was the only engine-readable block with no command behind it, so a
monorepo's per-component directories and a pack developed in its own repository
were wired by hand. That edit has no gate, and four spellings fail silently
after a sync that still reports ok: an absolute path, a path leaving the
repository, a path under the CLI-managed store, and one a double-quoted YAML
scalar cannot carry.

Placement is the work. `add` appends by default, because the end of a section is
the project's own territory; `--first`, `--last`, `--before` and `--after` place
an entry explicitly, which is how content that should behave like a package
lands after the store entries and ahead of the project's own.

The primitives it exposes are corrected with it. Presence was a substring search
over the whole manifest, exact enough for its single package-wiring caller and
wrong for an arbitrary path: one directory could not serve two sections, and a
bare `- docs/api` entry blocked adding `docs`. `status --check` now reports an
unrenderable entry through the same classifier `source add` refuses with, and a
manifest edit that cannot be placed leaves the file untouched.
Copilot AI lite review requested due to automatic review settings September 8, 2026 20:00
@dzykovic dzykovic added the ai:ready-to-merge CI green, reviews resolved, awaiting owner approval label Sep 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

source_entry_problem currently allows . as a sources entry, which can unintentionally treat the repository root as an artifact directory and pull unrelated top-level markdown into sync outputs.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a first-class CLI owner for project-managed sources: entries so monorepo/component directories and in-repo “dogfooded” packs can be added/removed/positioned with validation and consistent engine-visible semantics, eliminating silent no-op configurations from hand-edited manifests.

Changes:

  • Introduces intelligence source add|remove|list with explicit placement controls (--first/--last/--before/--after) and section-scoped, exact presence checks.
  • Adds shared validation (source_entry_problem) and wires it into status --check to flag sources the engine cannot render (previously silent).
  • Updates docs/decision records/tests and bumps schema/engine version to 0.16.0 across the repo and examples.
File summaries
File Description
README.md Documents the new source command group in the CLI surface table.
packages/sync/skills/intelligence-update-context/SKILL.md Updates authoring workflow guidance to use intelligence source add instead of hand-editing sources:.
packages/sync/references/conventions.md Adds convention guidance that project-owned sources: entries are CLI-managed and ordered.
intelligence/rules/cli.md Updates the public CLI surface to include source and clarifies ownership/ordering semantics for sources: edits.
intelligence.yaml Bumps schema_version and the @ainova-systems/sync pin to 0.16.0.
intelligence.lock Bumps engine_version and locked sync package request/resolve to 0.16.0.
examples/with-remote-skills/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/platform-with-submodules/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/platform-with-submodules/intelligence.lock Bumps example lock engine/package to 0.16.0.
examples/go-api/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/go-api/intelligence.lock Bumps example lock engine/package to 0.16.0.
examples/go-api-with-pi-and-codex/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/go-api-with-pi-and-codex/intelligence.lock Bumps example lock engine/package to 0.16.0.
examples/go-api-with-opencode/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/go-api-with-opencode/intelligence.lock Bumps example lock engine/package to 0.16.0.
examples/go-api-with-antigravity/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/go-api-with-antigravity/intelligence.lock Bumps example lock engine/package to 0.16.0.
examples/dotnet-api-with-react-frontend/intelligence.yaml Bumps example schema/package pin to 0.16.0.
examples/dotnet-api-with-react-frontend/intelligence.lock Bumps example lock engine/package to 0.16.0.
examples/cli-project/intelligence.yaml Bumps example schema/package pin to 0.16.0.
engine/VERSION Bumps engine version to 0.16.0.
engine/lib/common.sh Updates unsynced-directory warning to name the new intelligence source add command when running under the CLI.
docs/cli.md Adds full documentation for intelligence source and clarifies sources: ownership semantics.
decisions/0009-add-source-as-the-manifest-sources-editor.md Adds design record for introducing source as the owner/editor of project sources: entries.
CONTRIBUTING.md Updates the “Public CLI contract” surface list to include source.
cli/tests/verify.sh Registers new e2e-sources suite in verification gates.
cli/tests/unit-manifest.sh Adds unit coverage for ordered insertion, idempotence, section-scoped exact presence, and refusal semantics in sources editing primitives.
cli/tests/e2e-sources.sh Adds hermetic e2e coverage for source add/remove/list, placement, refusal cases, and a render-order proof via AGENTS.md.
cli/lib/manifest.sh Adds section-scoped sources list/presence helpers and a generalized ordered insertion primitive with placement/refusal behavior; improves _qmap_stage cleanup on edit refusal.
cli/lib/cli-common.sh Adds source_entry_problem validator for sources entries (shared by source and status --check).
cli/internal/check.sh Integrates source_entry_problem into status --check to report unrenderable sources entries distinctly from missing-but-optional directories.
cli/intelligence Adds source to dispatcher help and improves singular/plural error guidance (sources → source).
cli/commands/source.sh Implements `intelligence source add
CHANGELOG.md Adds 0.16.0 release notes for the new command and validation/primitives fixes.
.github/PULL_REQUEST_TEMPLATE.md Updates the template’s CLI surface checklist to include source.
Review details
  • Files reviewed: 28/35 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cli/lib/cli-common.sh
`.` was already rejected, but for the wrong reason: repo_rel_dir returns an
empty relative path for the root itself, so the containment guard read it as
"resolves outside the repository root". The root is the opposite failure — it
IS a directory, so nothing is skipped and every top-level *.md beside it is
read as an artifact of that section.

Spellings now reduce to one before anything is stored, compared or judged, so
`./x/`, `x/.` and `x/./y` are that directory, and `.`, `./` and `sub/..` are
the root the classifier names.
macOS ships Bash 3.2 as /bin/bash and CI runs the suites there, where pattern
substitution keeps the backslash of an escaped separator in the replacement:
${p//\/.\//\/} produced `intelligence\/rules`, while Bash 5 consumed it and the
local run stayed green. The path is now rebuilt from its segments.

A leading slash is meaning, not an empty segment. Dropping it turned
/abs/rules into abs/rules, which the classifier then accepted as an ordinary
relative path — the suite caught it before the fix left the branch.

shell.md records the floor and the trap, since a Git Bash run cannot see this
class of bug at all.
@dzykovic
dzykovic merged commit 179b1e8 into main Sep 8, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:ready-to-merge CI green, reviews resolved, awaiting owner approval

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants