Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "context",
"version": "0.7.37",
"version": "0.7.38",
"packageManager": "bun@1.3.9",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/context-cli/context-workflow/provider.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
schema: agent-graph.provider.v1
id: c4a/context
version: 0.7.37
version: 0.7.38
name: Context workflow
description: Internal work contract for Context knowledge workspaces.
graphs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ writing batches are declared in the temporary investigation plan.

After editing, run `context status --format json` and consume its current Route.

Read `context action prepare-current --schema --format json` for the complete
known-task input contract before creating a stage; no workspace or revision is required.

When article targets and source grouping are already clear, put the existing
plan fields (`capabilities`, `articles`, optional `indexer_usage`) in a file under
`.tmp/agent-work/`, omitting only `stage`, which does not exist yet. Each article
Expand All @@ -60,27 +63,17 @@ contains `path`, `question`, `sources` and `batch`, with optional `brief` and
command to prepare those tasks without a separate investigation-plan submission.
This does not approve the report or permit writing before its applicable scope
decision.
When targets are unclear, use normal preparation and investigate the skeletons.

## Configured coverage and the current request

`src/indexers.yaml` describes the workspace's standing coverage configuration.
Source registration or presence in that configuration does not, by itself, mean
that the source needs investigation again for this request. For a bounded document
addition or revision, identify its reader task and actual evidence dependencies;
reuse existing approved articles and applicable completed work. Do not broaden a
document task to unrelated code repositories merely because they are configured.

In planning and completion reports distinguish:
- work requested and completed in this task;
- specific content gaps established by reading, with their affected reader tasks;
- source/environment failures, and whether this task depends on those sources.
When targets are unclear, repeat `--source <source-ref>` on the preparation command
for the sources selected by this request. Without a selection, only a sole
configured target is inferred; multiple targets require the Agent to select
from the user's request, not to ask the user to understand CLI source IDs.
The CLI prepares only this scope. A source in `evidence_source_scope` remains
available without becoming an investigation assignment. A later article plan
can select it in `articles[].sources`; the CLI validates and prepares that
actual dependency before allowing writing. Missing required evidence still
blocks the dependent article.

A `pending_scopes` count is workflow state, not a count of missing topics,
repositories to rewrite, or articles to produce. A Git spawn/baseline-read error
means source availability could not be checked; it does not prove that existing
knowledge is absent or obsolete. If unrelated configured sources remain blocked,
say so as a workflow limitation rather than announcing new investigation work.
Do not delete configured sources, invent exclusions, clear stage files, or mark
unread material investigated to make the current task appear complete. Follow the
returned resolution action when the workflow still needs a decision.
Long-term configuration additions do not restart an unchanged stage. Plans and
refreshes track this request's selected investigation and actual article inputs.
Preserve genuinely unfinished work when extending a multi-stage request; do not
turn an incremental addition into a whole-workspace refresh.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ directories. Read relevant source text before writing; a skeleton is navigation,
not semantic evidence. Skill names guide work, not article ownership or versions.

Use the [reader organization guidance](knowledge-updates.md#reader-tasks-names-and-reading-order)
for article names, placement and manually arranged navigation. Check the draft's
for article names, placement and manually arranged navigation.
Use `context task adjust --inspect --format json` to obtain current categories,
reading order and the exact revision before preparing a navigation adjustment. Check the draft's
main reader task against its planned title and group; adjust through the existing
plan, revision or knowledge-map flow when needed. A navigation change alone does
not call for rewriting valid prose.
Expand Down Expand Up @@ -57,7 +59,7 @@ current task does not mean other authorized work is finished. New source or purp
authorization still follows the current Route.

Write results under the returned Agent directory. All submission paths are
relative to that stage directory, even when the manifest is in `submissions/`.
relative to `.tmp/agent-work/production-stages/<stage>/`, even when the manifest is in `submissions/`. They are never relative to `.tmp/context-runtime/` or to the manifest location. Each task lists the complete workspace-relative Markdown and reference output paths.
Copy the CLI's submission template, keep completed tasks only, and keep each
task's prefilled `input`. Submit the manifest using the returned command.
Do not edit submitted files until the command returns.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,32 +184,20 @@ a top-level navigation change already required by this procedure.

## Configured coverage and the current request

`src/indexers.yaml` describes the workspace's standing coverage configuration.
Source registration or presence in that configuration does not, by itself, mean
that the source needs investigation again for this request. For a bounded document
addition or revision, identify its reader task and actual evidence dependencies;
reuse existing approved articles and applicable completed work. Do not broaden a
document task to unrelated code repositories merely because they are configured.

In planning and completion reports distinguish:
- work requested and completed in this task;
- specific content gaps established by reading, with their affected reader tasks;
- source/environment failures, and whether this task depends on those sources.

A `pending_scopes` count is workflow state, not a count of missing topics,
repositories to rewrite, or articles to produce. A Git spawn/baseline-read error
means source availability could not be checked; it does not prove that existing
knowledge is absent or obsolete. If unrelated configured sources remain blocked,
say so as a workflow limitation rather than announcing new investigation work.
Do not delete configured sources, invent exclusions, clear stage files, or mark
unread material investigated to make the current task appear complete. Follow the
returned resolution action when the workflow still needs a decision.

For a bounded addition inside an existing production stage, completed articles can
enter Review with `context run --deliver --format json`. This retains pending
configured scopes and unfinished tasks; it does not authorize approval or publish.
Use this existing delivery path when remaining source failures are unrelated to
the requested articles. If the selected articles need the missing repository, use
`context source recovery-plan` and `context source restore` with an explicit local
checkout or clone decision. Do not ask users to investigate unrelated repositories
just to deliver saved notes, and do not clear gaps to imitate task completion.
Long-term source configuration is the authorized reading boundary, not the work
requested in every conversation. Prepare this request's selected investigation
sources or known article tasks. Keep unused supporting material available for
later article plans without treating it as unfinished work. For an addition to
an existing article, prefer the existing article-revision workflow with the
selected supporting sources rather than starting unrelated production.

Report this request's planned and completed work. Restore missing sources that
its investigation or articles actually require. Reference material not selected
for this work does not need restoration just to complete an independent note.
Never infer missing knowledge merely from unavailable source-code checkouts.

For an explicitly requested partial delivery, `context run --deliver --format json`
reviews completed articles while retaining genuine remaining tasks and selected
investigation. It does not approve or publish articles, and is unnecessary for
an otherwise completed bounded request. Do not clear unfinished work to force
completion; ordinary source authorization and citation checks still apply.
2 changes: 1 addition & 1 deletion packages/context-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@c4a/context-cli",
"description": "Local runtime and Agent integration for traceable knowledge production",
"version": "0.7.37",
"version": "0.7.38",
"type": "module",
"license": "MIT",
"engines": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ test("the existing task adjustment updates only organization and rejects stale c
const next = { expected_revision: first.revision, upsert: [{ ...first.entries[0]!, title: "New reader label" }], remove: [] };
expect(await adjustCurrentTaskSources(root, { knowledge_map: next })).toMatchObject({ outcome: "knowledge-map-updated" });
expect(await readFile(join(root, "knowledge/entry.md"), "utf8")).toBe(content);
await expect(adjustCurrentTaskSources(root, { knowledge_map: next })).rejects.toThrow("reread");
await expect(adjustCurrentTaskSources(root, { knowledge_map: next })).rejects.toMatchObject({ detail: {
reason_code: "knowledge-map-stale-revision", expected_revision: first.revision,
current_revision: (await readKnowledgeMap(root))!.revision,
next_action: { command: "context task adjust --inspect --format json" },
} });
expect((await readKnowledgeMap(root))?.entries[0]?.title).toBe("New reader label");
} finally { await rm(root, { recursive: true, force: true }); }
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test("navigation binds a local revision's new draft before approval and rejects
expect((await readKnowledgeMap(root))!.entries.find(entry => entry.key === "new-task")!.target)
.toEqual({ artifact_ref: candidate.article_id, section_key: "usage" });
const afterReport = await writeReviewHtml({ projectRoot: root, all: true });
expect(afterReport.navigation).toEqual({ ready: true, unplaced_count: 0, unplaced: [] });
expect(afterReport.navigation).toMatchObject({ ready: true, unplaced_count: 0, unplaced: [] });
expect(afterReport.next_action).toBeUndefined();
expect(await readCandidateRecords(root)).toEqual(candidates);
await expect(readFile(join(root, "knowledge", path))).rejects.toThrow();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function produceFixtureArticles(root: string, articles: FixtureProd
} = {}) {
const request = await productionPlanningRequest(root);
if (!request) throw new Error("Fixture needs canonical production requirements");
await prepareCurrentProductionStage({ projectRoot: root, revision: request.revision });
await prepareCurrentProductionStage({ projectRoot: root, revision: request.revision, sources: [...new Set(articles.flatMap(article => article.sources))] });
const initial = (await readProductionStage(root))!;
const agent = join(root, productionAgentDirectory(initial.id));
await mkdir(join(agent, "submissions"), { recursive: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ test("confirmed exclusion settles unfinished scope, retains accepted work and su
expect(dispatchProductionStage((await readProductionStage(root))!, productionCapabilitiesSchema.parse({})).state).toBe("ended");
expect(await readCandidateRecords(root)).toEqual(accepted);
await rm(join(root, ".tmp"), { recursive: true, force: true });
await prepareCurrentProductionStage({ projectRoot: root, revision: (await productionPlanningRequest(root))!.revision });
await prepareCurrentProductionStage({ projectRoot: root, revision: (await productionPlanningRequest(root))!.revision, sources: targets.map(target => target.source_ref) });
const fresh = (await readProductionStage(root))!;
expect(fresh.scopes.map(source => source.scope)).toEqual([first.source_ref]);
expect(fresh.tasks).toEqual([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ test("known tasks retain source authorization and reject unsafe files before cre
await writeFile(join(f.root, f.path), YAML.stringify({ ...f.plan,
articles: [{ ...f.plan.articles[0], sources: ["repo:not-authorized"] }] }));
await expect(prepareKnownProductionTasks({ projectRoot: f.root, cwd: f.root, revision: f.revision, path: f.path })).rejects.toThrow("outside authorized");
expect((await readProductionStage(f.root))!.tasks).toEqual([]);
expect(await readProductionStage(f.root)).toBeUndefined();
});

test("the real action boundary returns actionable plan, report and syntax failures without altering tasks", async () => {
Expand Down Expand Up @@ -175,3 +175,11 @@ test("the same known article saves one real CLI round trip before writing withou
// excluding model reading, authoring and the human's report response time.
console.info(`Same-article CLI comparison: ${JSON.stringify(measurements)}`);
});


test("known-task schema is available before a workspace or revision exists", async () => {
const schema = JSON.parse(await runCliInDir(resolve(".tmp"), ["action", "prepare-current", "--schema", "--format", "json"]));
expect(schema.properties.articles.items.properties.sources).toBeDefined();
expect(schema.required).not.toContain("stage");
expect(schema.properties.capabilities).toBeDefined();
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ test("code plus two documents share reader topics across skills and batches thro
target_scope: { targets: sources.map(source_ref => ({ source_ref })) },
exclusions: [{ scope: { targets: [{ source_ref: sources[0] }] }, paths: ["src/deprecated"], reason: "User requests only current APIs" }] }] });
await writeFile(join(root, "src/indexers.yaml"), requirements);
await prepareCurrentProductionStage({ projectRoot: root, revision: (await productionPlanningRequest(root))!.revision });
await prepareCurrentProductionStage({ projectRoot: root, revision: (await productionPlanningRequest(root))!.revision, sources });
const initial = (await readProductionStage(root))!;
expect(initial.gaps).toEqual([]);
const shared = (source: string) => readFile(join(root, productionStageDirectory(initial.id), productionSourceFile(source)), "utf8");
Expand Down
Loading
Loading