diff --git a/CHANGELOG.md b/CHANGELOG.md index 0116ec32..620139a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to Context are documented here. +## 0.7.90 - 2026-10-28 + +- A `context update --pending` decision can now revise existing pages whose citations did not change. The update lists them in `scope_pages`; they need no decision, but when an addition or a shared change affects one, include it with an `instruction`. Previously only pages with changed citations could be submitted, so such a page was rejected as not a candidate. + ## 0.7.88 - 2026-10-28 - `context update --pending` processes registered repositories whose commit moved past the version approved knowledge was processed at, such as after `context source add repo --ref `. Only pages whose cited text changed become update candidates, listed with their sections in `changed_references`; the update still asks for one scope decision covering additions and shared dependencies, and the new commit settles, with moved citations updating their locations, only after that decision. The workspace Route runs it before the idle task gate, `source add repo` returns a `next` hint for it, and `verify` warnings point to it when a cited repository moved. diff --git a/bun.lock b/bun.lock index 2385b27b..c72a487f 100644 --- a/bun.lock +++ b/bun.lock @@ -18,7 +18,7 @@ }, "packages/context": { "name": "@c4a/context", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "yaml": "^2.5.1", "zod": "^3.23.8", @@ -26,7 +26,7 @@ }, "packages/context-cli": { "name": "@c4a/context-cli", - "version": "0.7.88", + "version": "0.7.90", "bin": { "context": "dist/cli.js", }, @@ -76,7 +76,7 @@ }, "packages/core": { "name": "@c4a/core", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "picomatch": "^4.0.4", "yaml": "^2.4.5", @@ -88,7 +88,7 @@ }, "packages/dev-cli": { "name": "@c4a/dev-cli", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/context": "workspace:*", "@c4a/core": "workspace:*", @@ -100,7 +100,7 @@ }, "packages/extract": { "name": "@c4a/extract", - "version": "0.7.88", + "version": "0.7.90", "bin": { "c4a-extract-code": "./dist/bin/c4a-extract-code.js", }, @@ -115,7 +115,7 @@ }, "packages/extract-contract": { "name": "@c4a/extract-contract", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "graphql": "^16.14.2", @@ -125,7 +125,7 @@ }, "packages/extract-go": { "name": "@c4a/extract-go", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "@c4a/extract": "workspace:*", @@ -135,7 +135,7 @@ }, "packages/extract-mdx": { "name": "@c4a/extract-mdx", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "remark-mdx": "^3.1.1", @@ -147,7 +147,7 @@ }, "packages/extract-proto": { "name": "@c4a/extract-proto", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "zod": "^3.23.8", @@ -155,7 +155,7 @@ }, "packages/extract-rush": { "name": "@c4a/extract-rush", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "typescript": "^5.5.4", @@ -165,7 +165,7 @@ }, "packages/extract-sql": { "name": "@c4a/extract-sql", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "node-sql-parser": "^5.4.0", @@ -174,7 +174,7 @@ }, "packages/extract-style": { "name": "@c4a/extract-style", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "postcss": "^8.5.26", @@ -186,7 +186,7 @@ }, "packages/extract-thrift": { "name": "@c4a/extract-thrift", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "zod": "^3.23.8", @@ -194,7 +194,7 @@ }, "packages/extract-ts": { "name": "@c4a/extract-ts", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "@c4a/core": "workspace:*", "@c4a/extract": "workspace:*", @@ -205,7 +205,7 @@ }, "packages/tui": { "name": "@c4a/tui", - "version": "0.7.88", + "version": "0.7.90", "dependencies": { "ink": "^5.0.0", "react": "^18.3.1", diff --git a/package.json b/package.json index 1c36b093..44163890 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "context", - "version": "0.7.88", + "version": "0.7.90", "packageManager": "bun@1.3.9", "repository": { "type": "git", diff --git a/packages/context-cli/context-workflow/provider.yaml b/packages/context-cli/context-workflow/provider.yaml index f83ca494..363ae6a6 100644 --- a/packages/context-cli/context-workflow/provider.yaml +++ b/packages/context-cli/context-workflow/provider.yaml @@ -1,6 +1,6 @@ schema: agent-graph.provider.v1 id: c4a/context -version: 0.7.88 +version: 0.7.90 name: Context workflow description: Internal work contract for Context knowledge workspaces. graphs: diff --git a/packages/context-cli/context-workflow/resources/manuals/guides/knowledge-updates.md b/packages/context-cli/context-workflow/resources/manuals/guides/knowledge-updates.md index ece929c0..8f055f95 100644 --- a/packages/context-cli/context-workflow/resources/manuals/guides/knowledge-updates.md +++ b/packages/context-cli/context-workflow/resources/manuals/guides/knowledge-updates.md @@ -429,7 +429,8 @@ Moving a repository with `context source add repo --ref ` only changes its registration. When approved knowledge was processed at the previous commit, run `context update --pending --format json`. Only pages whose cited text changed become candidates, listed in `changed_references`; still inspect the change for -additions and shared dependencies before deciding. Moved citations update their +additions and shared dependencies before deciding. Other pages citing the source +are listed in `scope_pages` and can be revised in the same decision. Moved citations update their locations when the update settles. Before importing a `note`, read [note source preparation](note.md). diff --git a/packages/context-cli/context-workflow/resources/procedures/knowledge-updates.md b/packages/context-cli/context-workflow/resources/procedures/knowledge-updates.md index 311071d0..3f47d0e3 100644 --- a/packages/context-cli/context-workflow/resources/procedures/knowledge-updates.md +++ b/packages/context-cli/context-workflow/resources/procedures/knowledge-updates.md @@ -429,7 +429,8 @@ Moving a repository with `context source add repo --ref ` only changes its registration. When approved knowledge was processed at the previous commit, run `context update --pending --format json`. Only pages whose cited text changed become candidates, listed in `changed_references`; still inspect the change for -additions and shared dependencies before deciding. Moved citations update their +additions and shared dependencies before deciding. Other pages citing the source +are listed in `scope_pages` and can be revised in the same decision. Moved citations update their locations when the update settles. Before importing a `note`, read [note source preparation](note.md). diff --git a/packages/context-cli/context-workflow/resources/procedures/source-update.md b/packages/context-cli/context-workflow/resources/procedures/source-update.md index a7403b4e..e2be4935 100644 --- a/packages/context-cli/context-workflow/resources/procedures/source-update.md +++ b/packages/context-cli/context-workflow/resources/procedures/source-update.md @@ -22,6 +22,8 @@ cited text changed (`changed`) or could not be read (`unavailable`, such as a renamed or deleted file). For `context update --pending`, pages whose citations are unchanged or only moved are not candidates, so an empty list is possible; still check the change for additions before submitting the scope decision. +Those pages are listed in `scope_pages`: they need no decision, but include one +with an `instruction` when an addition or shared change affects it. Also inspect additions and shared dependencies in the source change. Existing page references cannot discover every new topic. List necessary new pages in `new_topics`, each with a readable `path` in an existing diff --git a/packages/context-cli/package.json b/packages/context-cli/package.json index 704679e4..db6177c7 100644 --- a/packages/context-cli/package.json +++ b/packages/context-cli/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/context-cli", "description": "Local runtime and Agent integration for traceable knowledge production", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/context-cli/src/__tests__/projectPendingSourceUpdate.test.ts b/packages/context-cli/src/__tests__/projectPendingSourceUpdate.test.ts index f7cc9e77..258f729c 100644 --- a/packages/context-cli/src/__tests__/projectPendingSourceUpdate.test.ts +++ b/packages/context-cli/src/__tests__/projectPendingSourceUpdate.test.ts @@ -11,6 +11,7 @@ import { beginKnowledgeUpdate, readKnowledgeUpdate } from "../project/knowledgeU import { pendingSourceUpdateScopes } from "../project/pendingSourceUpdates.js"; import { registeredRepoHistoryReader } from "../project/articleSourceReader.js"; import { collectProjectStatus } from "../project/status.js"; +import { readApprovedRevision } from "../project/approvedRevision.js"; const roots: string[] = []; afterEach(async () => { for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); }); @@ -73,6 +74,22 @@ test("a pending update with only moved citations still requires the scope decisi expect(await pendingSourceUpdateScopes(root)).toEqual([]); }); +test("the scope decision can revise an existing page whose citations are unchanged", async () => { + const root = await settledKnowledge(); + const before = await baseline(root); + await moveCitedTextAndAddExport(root); + await beginKnowledgeUpdate(root, undefined, { pending: true }); + const update = (await readKnowledgeUpdate(root))!; + expect(update.candidates).toEqual([]); + expect(update.scope_pages).toEqual(["architecture/overview.md", "architecture/usage.md"]); + const status = await collectProjectStatus(root, { managed: true }); + expect(await completeCurrentIndexerAction({ cwd: root, revision: status.workflow.current!.revision, managed: true, + value: { stage: "source-update", decisions: [{ path: "architecture/overview.md", instruction: "Mention newPublicFeature." }], + scope_summary: "The overview introduces the new export.", new_topics: [] } })).toMatchObject({ outcome: "revisions-prepared" }); + expect((await readApprovedRevision(root))?.target.path).toBe("architecture/overview.md"); + expect(await baseline(root)).toEqual(before); +}); + test("concurrent history reads in a shallow checkout share one fetch and confirm every moved citation", async () => { const root = await settledKnowledge(); const source = join(root, "fixture-source"); diff --git a/packages/context-cli/src/project/indexerBaseContracts.ts b/packages/context-cli/src/project/indexerBaseContracts.ts index afb6093c..2e5a4fbd 100644 --- a/packages/context-cli/src/project/indexerBaseContracts.ts +++ b/packages/context-cli/src/project/indexerBaseContracts.ts @@ -21,7 +21,7 @@ import { bundledMarkdownReaderQuestionContracts } from "./indexerBaseMarkdownAuthoringCatalog.js"; const BASE_CONTRACT_VERSION = "1.1.0"; -export const BUNDLED_INDEXER_PARSER_PACKAGE_VERSION = "0.7.88"; +export const BUNDLED_INDEXER_PARSER_PACKAGE_VERSION = "0.7.90"; const BUNDLED_PARSER_REQUIREMENTS = buildIndexerParserCapabilityRequirements( BUNDLED_INDEXER_PARSER_PACKAGE_VERSION, ); diff --git a/packages/context-cli/src/project/knowledgeUpdate.ts b/packages/context-cli/src/project/knowledgeUpdate.ts index 5f4be6a8..90886973 100644 --- a/packages/context-cli/src/project/knowledgeUpdate.ts +++ b/packages/context-cli/src/project/knowledgeUpdate.ts @@ -36,6 +36,7 @@ const updateSchema = z.object({ structure_proposal: indexerCurrentActionInputDefinitions.sourceUpdate.omit({ stage: true }).optional(), previous_versions: z.array(z.string().nullable()), changes: z.string().optional(), repo_content: z.unknown().optional(), + scope_pages: z.array(z.string()).optional(), changed_references: z.array(z.object({ path: z.string(), section_id: z.string(), state: z.enum(["changed", "unavailable"]), source_ref: z.string(), locator: z.unknown() }).strict()).optional(), }).strict(); @@ -90,6 +91,9 @@ export async function beginKnowledgeUpdate(projectRoot: string, value: unknown, view_ref: article.article_id, source_refs: [...new Set(article.sections.flatMap(section => section.references.map(reference => reference.source_ref)))] }; })); + // Pending updates ask only about changed citations, but the scope review may + // still revise any existing page that cites these sources. + const scopePages = options.pending ? cited.map(article => article.path).filter(path => !changedPaths.has(path)) : []; const registry = await readProductionRequirements(projectRoot); const repoReferences = articles.flatMap(article => article.sections.flatMap(section => section.references.filter(ref => ref.source_ref.startsWith("repo-content:") && @@ -104,6 +108,7 @@ export async function beginKnowledgeUpdate(projectRoot: string, value: unknown, const requirements = registry.requirements.filter((requirement) => requirementIds.has(requirement.id)); const payload = { protocol: "context.source-update/v1" as const, scopes, requirements, candidates, ...(repoContent === undefined ? {} : { repo_content: repoContent }), + ...(scopePages.length === 0 ? {} : { scope_pages: scopePages }), ...(inspected.unresolved.length === 0 ? {} : { changed_references: inspected.unresolved.map(item => ({ path: item.path, section_id: item.section_id, state: item.state, source_ref: item.reference.source_ref, locator: item.reference.locator })) }), previous_versions: scopes.map((scope) => processedVersionForScope(settled, scope) ?? null), @@ -178,12 +183,13 @@ export async function completeKnowledgeUpdate(input: { projectRoot: string; revi if (repeated.length) throw new SubmissionInputError(`Update page paths must be unique; repeated: ${repeated.join(", ")}`, ["decisions"]); const candidates = new Set(request.candidates.map((candidate) => candidate.path)); const missing = [...candidates].filter((path) => !input.decisions.some((decision) => decision.path === path)); - const unknown = input.decisions.map((decision) => decision.path).filter((path) => !candidates.has(path)); + const scopePages = new Set(request.scope_pages ?? []); + const unknown = input.decisions.map((decision) => decision.path).filter((path) => !candidates.has(path) && !scopePages.has(path)); if (missing.length || unknown.length) { throw new SubmissionInputError([ "Decide each source-bound candidate once; an omitted page is not a no-change decision. List a candidate with only its path to keep it unchanged.", ...(missing.length ? [`Missing: ${missing.join(", ")}.`] : []), - ...(unknown.length ? [`Not candidates (use new_topics for new pages): ${unknown.join(", ")}.`] : []), + ...(unknown.length ? [`Not candidates or scope pages (use new_topics for new pages): ${unknown.join(", ")}.`] : []), ].join(" "), ["decisions"]); } await captureProcessedScopes(input.projectRoot, request.scopes); diff --git a/packages/context/docs/guides/knowledge-updates.md b/packages/context/docs/guides/knowledge-updates.md index b7e02051..769ed14e 100644 --- a/packages/context/docs/guides/knowledge-updates.md +++ b/packages/context/docs/guides/knowledge-updates.md @@ -423,7 +423,8 @@ Moving a repository with `context source add repo --ref ` only changes its registration. When approved knowledge was processed at the previous commit, run `context update --pending --format json`. Only pages whose cited text changed become candidates, listed in `changed_references`; still inspect the change for -additions and shared dependencies before deciding. Moved citations update their +additions and shared dependencies before deciding. Other pages citing the source +are listed in `scope_pages` and can be revised in the same decision. Moved citations update their locations when the update settles. Before importing a `note`, read [note source preparation](note.md). diff --git a/packages/context/package.json b/packages/context/package.json index 1f01bf4c..f42735d1 100644 --- a/packages/context/package.json +++ b/packages/context/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/context", "description": "Declarative SDK for Context knowledge sources, workflows, review, and package outputs", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/core/package.json b/packages/core/package.json index 11b6208d..45f8f311 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/core", "description": "Shared extraction types, schemas, and utilities for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/dev-cli/package.json b/packages/dev-cli/package.json index 3eea73af..573e9251 100644 --- a/packages/dev-cli/package.json +++ b/packages/dev-cli/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/dev-cli", "description": "Developer menu for Context build, verification, link, and release preparation", - "version": "0.7.88", + "version": "0.7.90", "private": true, "type": "module", "license": "MIT", diff --git a/packages/extract-contract/package.json b/packages/extract-contract/package.json index 5dcc4cd3..abd468cd 100644 --- a/packages/extract-contract/package.json +++ b/packages/extract-contract/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-contract", "description": "OpenAPI and GraphQL contract catalog adapter for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-go/package.json b/packages/extract-go/package.json index b996e668..259766f3 100644 --- a/packages/extract-go/package.json +++ b/packages/extract-go/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-go", "description": "Go extraction plugin and structural index for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-mdx/package.json b/packages/extract-mdx/package.json index 5d91d086..847417d9 100644 --- a/packages/extract-mdx/package.json +++ b/packages/extract-mdx/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-mdx", "description": "MDX component and example catalog bridge for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-proto/package.json b/packages/extract-proto/package.json index 63bdbeff..225f8c4a 100644 --- a/packages/extract-proto/package.json +++ b/packages/extract-proto/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-proto", "description": "Protocol Buffers IDL catalog parser for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-rush/package.json b/packages/extract-rush/package.json index 2dfd4200..9df5c5cf 100644 --- a/packages/extract-rush/package.json +++ b/packages/extract-rush/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-rush", "description": "Rush workspace structural index for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-sql/package.json b/packages/extract-sql/package.json index 9291c844..8d75f2a2 100644 --- a/packages/extract-sql/package.json +++ b/packages/extract-sql/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-sql", "description": "Dialect-bound lightweight SQL evidence adapter for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-style/package.json b/packages/extract-style/package.json index 73a51598..551efe30 100644 --- a/packages/extract-style/package.json +++ b/packages/extract-style/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-style", "description": "Lightweight CSS and SCSS evidence adapter for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-thrift/package.json b/packages/extract-thrift/package.json index 606f550e..98bde51d 100644 --- a/packages/extract-thrift/package.json +++ b/packages/extract-thrift/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-thrift", "description": "Apache Thrift IDL catalog parser for Context", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract-ts/package.json b/packages/extract-ts/package.json index 3ad5f294..48db2bb5 100644 --- a/packages/extract-ts/package.json +++ b/packages/extract-ts/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract-ts", "description": "TypeScript and JavaScript extraction plugin for the Context ExtractionResult v2 contract", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/extract/package.json b/packages/extract/package.json index 97762607..2fe693f4 100644 --- a/packages/extract/package.json +++ b/packages/extract/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/extract", "description": "Language-plugin framework and repository runner for Context code evidence", - "version": "0.7.88", + "version": "0.7.90", "type": "module", "license": "MIT", "engines": { diff --git a/packages/tui/package.json b/packages/tui/package.json index 98c9ca4a..d7e850fb 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -1,7 +1,7 @@ { "name": "@c4a/tui", "description": "Shared terminal UI components (Ink + React) for Context development tools", - "version": "0.7.88", + "version": "0.7.90", "private": true, "type": "module", "license": "MIT", diff --git a/plugins/context/repo-install/claude/.claude-plugin/plugin.json b/plugins/context/repo-install/claude/.claude-plugin/plugin.json index bd9ea168..f0648b48 100644 --- a/plugins/context/repo-install/claude/.claude-plugin/plugin.json +++ b/plugins/context/repo-install/claude/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "c4a", "description": "Start or continue a project-local knowledge workspace through one graph-routed entry.", - "version": "0.7.88", + "version": "0.7.90", "author": { "name": "c4a" }, diff --git a/plugins/context/repo-install/codex/.codex-plugin/plugin.json b/plugins/context/repo-install/codex/.codex-plugin/plugin.json index 2ab72420..abcefbf5 100644 --- a/plugins/context/repo-install/codex/.codex-plugin/plugin.json +++ b/plugins/context/repo-install/codex/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "c4a", - "version": "0.7.88", + "version": "0.7.90", "description": "Start or continue a project-local knowledge workspace through one graph-routed entry.", "author": { "name": "c4a" }, "homepage": "https://github.com/context4ai/c4a", @@ -10,7 +10,7 @@ "skills": "./skills/", "interface": { "displayName": "C4A Context", - "shortDescription": "Initialize and advance a local, source-linked project knowledge workspace.\nv0.7.88", + "shortDescription": "Initialize and advance a local, source-linked project knowledge workspace.\nv0.7.90", "longDescription": "Create a Context workspace and use agent-guided next steps to register sources, run extraction, review candidates, build package outputs, and verify health without silently mutating source repositories.", "developerName": "c4a", "category": "Productivity", diff --git a/plugins/context/repo-install/cursor/.cursor-plugin/plugin.json b/plugins/context/repo-install/cursor/.cursor-plugin/plugin.json index 05b11b87..c0404be3 100644 --- a/plugins/context/repo-install/cursor/.cursor-plugin/plugin.json +++ b/plugins/context/repo-install/cursor/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "c4a", "displayName": "C4A Context", - "version": "0.7.88", + "version": "0.7.90", "description": "Start or continue a project-local knowledge workspace through one graph-routed entry.", "author": { "name": "Context4AI",