Added intelligence source to own the project's sources entries - #29
Merged
Merged
Conversation
`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.
There was a problem hiding this comment.
🟡 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|listwith explicit placement controls (--first/--last/--before/--after) and section-scoped, exact presence checks. - Adds shared validation (
source_entry_problem) and wires it intostatus --checkto flag sources the engine cannot render (previously silent). - Updates docs/decision records/tests and bumps schema/engine version to
0.16.0across 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.
`.` 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sources:was the one engine-readable block with no command behind it.package add/package removeown 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, butrepo_rel_link_varreturns nothing outside the root, soAGENTS.mdcarries 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|listas 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.
addappends 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_problemclassifies an entry;source addrefuses through it before writing, andstatus --checknow 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/promptsunder bothrules:andagents:), and a bare- docs/apientry blocked addingdocs. 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_stagenow drops the staged file and refuses when its editor exits non-zero, instead of aborting mid-command and leaving a.cli.tmpbehind.Design record:
decisions/0009-add-source-as-the-manifest-sources-editor.md.Type of change
Public CLI check
init,sync,update,upgrade,package,source,adapter,status,registryintelligence syncVerification
bash cli/tests/verify.shreportsverify okand skipped nothing this change neededintelligence status --checksucceeds in the relevant fixture/projectintelligence syncproduces no unexpected diffVersioned artifacts
CHANGELOG.mdversion; there is no[Unreleased]section or duplicated release dateengine/VERSIONrelease state was checked: append while pending, or select the next SemVer after publicationschema_versionand exact@ainova-systems/syncpin changed with itNotes for reviewers
sourceis a new group, added deliberately. The first box above is checked against the surface this PR establishes:decisions/0009records why thesources:block needs an owner for its project entries, andintelligence/rules/cli.md,CONTRIBUTING.mdand this template were updated in the same change.package,adapterandregistryeach already own their block;sources:was the exception.Why
addappends 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-frontendfixes the monorepo order asintelligence/rulesthenbackend/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--beforeaway.No preview/apply mode. Like
registry addandadapter 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, andremoveis 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 withoutIS_CLI.Test coverage. New
cli/tests/e2e-sources.sh(registered inSUITES) covers placement, the move-on-explicit-position path, every refusal with a byte-identical manifest afterwards, thestatus --checkreport, and a render proving the wired directories reachAGENTS.mdin list order.unit-manifest.shgains the primitive-level cases; both presence defects were reproduced against the old semantics before the fix.