@kitschpatrol/chagent 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +14 -2
- package/dist/lib/bumpp.d.ts +1 -1
- package/dist/lib/bumpp.js +1 -1
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +2 -2
- package/dist/{lib-advgvAk1.js → lib-Byxdn2st.js} +1 -1
- package/dist/{review-ClBbl31P.js → review-DftIAoEl.js} +85 -28
- package/dist/{types-COQP1I5w.d.ts → types-B6FOOkTQ.d.ts} +9 -1
- package/package.json +1 -1
- package/readme.md +26 -19
package/dist/bin/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as
|
|
3
|
-
import { n as assertAmendable, t as amendRelease } from "../lib-
|
|
2
|
+
import { C as maxTimeoutMinutes, S as defaults, b as setLogger, d as rootChangelogs, i as generateChangelog, l as agentNames, n as previewChangelog, r as reviewChangelog, s as writeChangelog, t as assertReviewTerminal, u as efforts, w as version, x as defaultModels } from "../review-DftIAoEl.js";
|
|
3
|
+
import { n as assertAmendable, t as amendRelease } from "../lib-Byxdn2st.js";
|
|
4
4
|
import { t as createProgressLine } from "../progress-DQtRnH1N.js";
|
|
5
5
|
import { createLogger } from "lognow";
|
|
6
6
|
import path from "node:path";
|
|
@@ -109,6 +109,16 @@ try {
|
|
|
109
109
|
default: false,
|
|
110
110
|
description: "Amend a verified unpublished release commit and matching local tags",
|
|
111
111
|
type: "boolean"
|
|
112
|
+
}).option("root-changelog", {
|
|
113
|
+
choices: rootChangelogs,
|
|
114
|
+
defaultDescription: defaults.rootChangelog,
|
|
115
|
+
description: "Monorepo root changelog: a summary of package releases, the root package alone, or none",
|
|
116
|
+
type: "string"
|
|
117
|
+
}).option("skip-package", {
|
|
118
|
+
array: true,
|
|
119
|
+
defaultDescription: "none",
|
|
120
|
+
description: "Workspace package directory glob to leave without a changelog; repeatable",
|
|
121
|
+
type: "string"
|
|
112
122
|
}).option("github", {
|
|
113
123
|
defaultDescription: String(defaults.github),
|
|
114
124
|
description: "Enrich Git evidence using gh when available; disable with --no-github",
|
|
@@ -148,7 +158,9 @@ try {
|
|
|
148
158
|
reporter.report(message);
|
|
149
159
|
},
|
|
150
160
|
rebuild: args.rebuild,
|
|
161
|
+
rootChangelog: args.rootChangelog,
|
|
151
162
|
signal: controller.signal,
|
|
163
|
+
skipPackage: args.skipPackage,
|
|
152
164
|
timeout: args.timeout
|
|
153
165
|
}));
|
|
154
166
|
try {
|
package/dist/lib/bumpp.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as GenerateOptions } from "../types-
|
|
1
|
+
import { u as GenerateOptions } from "../types-B6FOOkTQ.js";
|
|
2
2
|
import { VersionBumpOptions } from "bumpp";
|
|
3
3
|
type ExecuteHook = Exclude<NonNullable<VersionBumpOptions['execute']>, string>;
|
|
4
4
|
export type BumppHookOptions = Omit<GenerateOptions, 'cwd' | 'release'> & {
|
package/dist/lib/bumpp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as git, h as localDate, i as generateChangelog, r as reviewChangelog, s as writeChangelog, t as assertReviewTerminal } from "../review-DftIAoEl.js";
|
|
2
2
|
import { t as createProgressLine } from "../progress-DQtRnH1N.js";
|
|
3
3
|
|
|
4
4
|
// src/lib/bumpp.ts
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as RunSettings, a as ChangeSet, b as loadConfig, c as Evidence, d as GenerationRequest, f as GenerationResponse, g as RootChangelog, h as ReleaseSummary, i as Change, l as FileEdit, m as ReleaseRequest, n as AgentName, o as ChangelogPlan, p as ReleaseContext, r as Category, s as Effort, t as AgentAdapter, u as GenerateOptions, v as Config, y as defineConfig } from "../types-B6FOOkTQ.js";
|
|
2
2
|
import { ILogBasic, ILogLayer } from "lognow";
|
|
3
3
|
/** Create an adapter for an installed CLI using its existing authentication. */
|
|
4
4
|
export declare function createAgent(name: AgentName): AgentAdapter;
|
|
@@ -28,4 +28,4 @@ export declare function reviewChangelog(plan: ChangelogPlan, options?: {
|
|
|
28
28
|
* writes.
|
|
29
29
|
*/
|
|
30
30
|
export declare function writeChangelog(plan: ChangelogPlan): Promise<string[]>;
|
|
31
|
-
export { type AgentAdapter, type AgentName, type Category, type Change, type ChangeSet, type ChangelogPlan, type Config, type Effort, type Evidence, type FileEdit, type GenerateOptions, type GenerationRequest, type GenerationResponse, type ReleaseContext, type ReleaseRequest, type ReleaseSummary, type RunSettings, defineConfig, loadConfig };
|
|
31
|
+
export { type AgentAdapter, type AgentName, type Category, type Change, type ChangeSet, type ChangelogPlan, type Config, type Effort, type Evidence, type FileEdit, type GenerateOptions, type GenerationRequest, type GenerationResponse, type ReleaseContext, type ReleaseRequest, type ReleaseSummary, type RootChangelog, type RunSettings, defineConfig, loadConfig };
|
package/dist/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as defineConfig, c as createAgent, i as generateChangelog, n as previewChangelog, o as loadConfig, r as reviewChangelog, s as writeChangelog
|
|
2
|
-
import { t as amendRelease } from "../lib-
|
|
1
|
+
import { a as defineConfig, b as setLogger, c as createAgent, i as generateChangelog, n as previewChangelog, o as loadConfig, r as reviewChangelog, s as writeChangelog } from "../review-DftIAoEl.js";
|
|
2
|
+
import { t as amendRelease } from "../lib-Byxdn2st.js";
|
|
3
3
|
|
|
4
4
|
export { amendRelease, createAgent, defineConfig, generateChangelog, loadConfig, previewChangelog, reviewChangelog, setLogger, writeChangelog };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as git, f as LOCKFILE_PATH, g as manifestAt, m as isVersionOnlyChange, p as inspectRepository, s as writeChangelog, v as isAncestor, y as runCommand } from "./review-DftIAoEl.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { realpath } from "node:fs/promises";
|
|
4
4
|
|
|
@@ -15,7 +15,7 @@ import { isCancel, select } from "@clack/prompts";
|
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
17
|
var name = "@kitschpatrol/chagent";
|
|
18
|
-
var version = "0.
|
|
18
|
+
var version = "0.4.0";
|
|
19
19
|
var engines = { "node": "^24.16.0 || >=26.3.0" };
|
|
20
20
|
|
|
21
21
|
// src/lib/defaults.ts
|
|
@@ -25,6 +25,7 @@ const defaults = {
|
|
|
25
25
|
effort: "xhigh",
|
|
26
26
|
github: true,
|
|
27
27
|
maxInputChars: 8e4,
|
|
28
|
+
rootChangelog: "summary",
|
|
28
29
|
timeout: 20
|
|
29
30
|
};
|
|
30
31
|
const defaultModels = {
|
|
@@ -486,21 +487,15 @@ function pnpmWorkspaceGlobs(text) {
|
|
|
486
487
|
if (!workspace.success) throw new Error(`Invalid pnpm-workspace.yaml:\n${z.prettifyError(workspace.error)}`, { cause: workspace.error });
|
|
487
488
|
return workspace.data?.packages;
|
|
488
489
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const workspaceText = await readOptional(path.join(root, "pnpm-workspace.yaml"));
|
|
492
|
-
if (workspaceText !== void 0) patterns = pnpmWorkspaceGlobs(workspaceText) ?? patterns;
|
|
493
|
-
patterns = config.packages ?? patterns;
|
|
490
|
+
/** Find directories matching globs, as POSIX paths relative to the root. */
|
|
491
|
+
async function matchDirectories(root, patterns, exclude = []) {
|
|
494
492
|
const directories = [];
|
|
495
|
-
const
|
|
496
|
-
const negative = patterns.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
497
|
-
const matches = glob(positive, {
|
|
493
|
+
const matches = glob(patterns, {
|
|
498
494
|
cwd: root,
|
|
499
495
|
exclude: [
|
|
500
496
|
"**/node_modules/**",
|
|
501
497
|
"**/.git/**",
|
|
502
|
-
...
|
|
503
|
-
...config.exclude ?? []
|
|
498
|
+
...exclude
|
|
504
499
|
],
|
|
505
500
|
withFileTypes: true
|
|
506
501
|
});
|
|
@@ -508,6 +503,27 @@ async function workspacePackages(root, manifest, config) {
|
|
|
508
503
|
if (!entry.isDirectory()) continue;
|
|
509
504
|
directories.push(path.relative(root, path.join(entry.parentPath, entry.name)).split(path.sep).join("/"));
|
|
510
505
|
}
|
|
506
|
+
return directories;
|
|
507
|
+
}
|
|
508
|
+
/** Mark the packages that remain boundaries but get no changelog. */
|
|
509
|
+
async function markSkipped(root, packages, patterns) {
|
|
510
|
+
const skipped = /* @__PURE__ */ new Set();
|
|
511
|
+
for (const pattern of patterns) {
|
|
512
|
+
const matches = (await matchDirectories(root, [pattern])).filter((directory) => packages.some((pkg) => pkg.directory === directory));
|
|
513
|
+
if (matches.length === 0) throw new Error(`skipPackage pattern "${pattern}" matches no workspace package directory. Use a directory glob relative to the repository root, such as "packages/docs"; rootChangelog controls the root changelog.`);
|
|
514
|
+
for (const directory of matches) skipped.add(directory);
|
|
515
|
+
}
|
|
516
|
+
return packages.map((pkg) => skipped.has(pkg.directory) ? {
|
|
517
|
+
...pkg,
|
|
518
|
+
skipped: true
|
|
519
|
+
} : pkg);
|
|
520
|
+
}
|
|
521
|
+
async function workspacePackages(root, manifest, config) {
|
|
522
|
+
let patterns = Array.isArray(manifest?.workspaces) ? manifest.workspaces : manifest?.workspaces?.packages ?? [];
|
|
523
|
+
const workspaceText = await readOptional(path.join(root, "pnpm-workspace.yaml"));
|
|
524
|
+
if (workspaceText !== void 0) patterns = pnpmWorkspaceGlobs(workspaceText) ?? patterns;
|
|
525
|
+
patterns = config.packages ?? patterns;
|
|
526
|
+
const directories = await matchDirectories(root, patterns.filter((pattern) => !pattern.startsWith("!")), [...patterns.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1)), ...config.exclude ?? []]);
|
|
511
527
|
const packages = [];
|
|
512
528
|
for (const directory of directories.toSorted()) {
|
|
513
529
|
if (!(await realpath(path.join(root, directory))).startsWith(root + path.sep)) throw new Error(`Workspace package escapes the repository: ${directory}`);
|
|
@@ -515,7 +531,11 @@ async function workspacePackages(root, manifest, config) {
|
|
|
515
531
|
if (text === void 0 && config.packages === void 0) continue;
|
|
516
532
|
packages.push(packageInfo(text === void 0 ? void 0 : parseManifest(text, `${directory}/package.json`), directory, path.posix.basename(directory)));
|
|
517
533
|
}
|
|
518
|
-
return packages;
|
|
534
|
+
return markSkipped(root, packages, config.skipPackage ?? []);
|
|
535
|
+
}
|
|
536
|
+
/** Select the workspace packages that get changelogs of their own. */
|
|
537
|
+
function describedPackages(repository) {
|
|
538
|
+
return repository.packages.filter((pkg) => pkg.skipped !== true);
|
|
519
539
|
}
|
|
520
540
|
async function taggedReleases(repository, pkg, config) {
|
|
521
541
|
const candidates = [];
|
|
@@ -735,6 +755,11 @@ const efforts = [
|
|
|
735
755
|
"xhigh",
|
|
736
756
|
"max"
|
|
737
757
|
];
|
|
758
|
+
const rootChangelogs = [
|
|
759
|
+
"summary",
|
|
760
|
+
"package",
|
|
761
|
+
"none"
|
|
762
|
+
];
|
|
738
763
|
|
|
739
764
|
// src/lib/agents.ts
|
|
740
765
|
const CONTROL_CHARACTERS = /\p{Cc}/v;
|
|
@@ -1062,6 +1087,13 @@ const configSchema = z.strictObject({
|
|
|
1062
1087
|
model: z.string().min(1).optional(),
|
|
1063
1088
|
/** Workspace directory globs, overriding manifest workspace discovery. */
|
|
1064
1089
|
packages: z.array(z.string()).optional(),
|
|
1090
|
+
/**
|
|
1091
|
+
* What a monorepo's root changelog records: a summary of package releases,
|
|
1092
|
+
* the root package's own changes, or nothing.
|
|
1093
|
+
*/
|
|
1094
|
+
rootChangelog: z.enum(rootChangelogs).optional(),
|
|
1095
|
+
/** Workspace package directory globs that get no changelog of their own. */
|
|
1096
|
+
skipPackage: z.array(z.string()).optional(),
|
|
1065
1097
|
/** Templates containing {version} and optionally {name}. */
|
|
1066
1098
|
tagPatterns: z.array(z.string().includes("{version}")).optional(),
|
|
1067
1099
|
/** Minutes each agent session may run. */
|
|
@@ -1073,6 +1105,7 @@ const resolvedConfigSchema = configSchema.required({
|
|
|
1073
1105
|
effort: true,
|
|
1074
1106
|
github: true,
|
|
1075
1107
|
maxInputChars: true,
|
|
1108
|
+
rootChangelog: true,
|
|
1076
1109
|
timeout: true
|
|
1077
1110
|
}).transform(({ timeout, ...config }) => ({
|
|
1078
1111
|
...config,
|
|
@@ -1331,8 +1364,11 @@ function ignored(file, packages) {
|
|
|
1331
1364
|
const relative = owner === void 0 ? file : file.slice(owner.directory.length + 1);
|
|
1332
1365
|
return LOCKFILE_PATH.test(file) || GENERATED_ANYWHERE.test(file) || GENERATED_DIRECTORY.test(relative);
|
|
1333
1366
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1367
|
+
/**
|
|
1368
|
+
* A package's directory and, transitively, those of the workspace packages it
|
|
1369
|
+
* depends on at a ref.
|
|
1370
|
+
*/
|
|
1371
|
+
async function packageScope(repository, pkg, ref) {
|
|
1336
1372
|
const directories = /* @__PURE__ */ new Set([pkg.directory]);
|
|
1337
1373
|
const visit = async (current) => {
|
|
1338
1374
|
const manifest = await manifestAt(repository.root, current.directory, ref);
|
|
@@ -1402,7 +1438,7 @@ async function commitsInRange(root, range, paths) {
|
|
|
1402
1438
|
/** Collect source changes, excluding generated notes and release-only commits. */
|
|
1403
1439
|
async function collectEvidence(repository, pkg, release, excludeDirectories = []) {
|
|
1404
1440
|
const { packages, root } = repository;
|
|
1405
|
-
const paths = [...(await
|
|
1441
|
+
const paths = [...(pkg.directory === "." ? ["."] : await packageScope(repository, pkg, release.ref)).map((directory) => `:(literal)${directory}`), ...excludeDirectories.map((directory) => `:(exclude,literal)${directory}`)];
|
|
1406
1442
|
const range = release.previousRef === void 0 ? release.ref : `${release.previousRef}..${release.ref}`;
|
|
1407
1443
|
const from = release.previousRef ?? await git(root, [
|
|
1408
1444
|
"hash-object",
|
|
@@ -1642,7 +1678,7 @@ function researchEvidence(evidence, limit) {
|
|
|
1642
1678
|
async function prepareRelease(context, pkg, release, existingEntries, mode, from, onlyRepositoryFiles = false) {
|
|
1643
1679
|
const { options, repository } = context;
|
|
1644
1680
|
options.signal?.throwIfAborted();
|
|
1645
|
-
const excludeDirectories =
|
|
1681
|
+
const excludeDirectories = await excludedPackages(context, pkg, release.ref, onlyRepositoryFiles);
|
|
1646
1682
|
return {
|
|
1647
1683
|
evidence: await collectEvidence(repository, pkg, from === void 0 ? release : {
|
|
1648
1684
|
...release,
|
|
@@ -1659,10 +1695,24 @@ async function prepareRelease(context, pkg, release, existingEntries, mode, from
|
|
|
1659
1695
|
from: from ?? release.previousRef,
|
|
1660
1696
|
to: release.ref
|
|
1661
1697
|
},
|
|
1662
|
-
scope: pkg.directory === "." && repository.packages.length > 0 ? "repository" : "package",
|
|
1698
|
+
scope: pkg.directory === "." && repository.packages.length > 0 && options.rootChangelog === "summary" ? "repository" : "package",
|
|
1663
1699
|
version: release.version
|
|
1664
1700
|
};
|
|
1665
1701
|
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Select the package directories a release leaves out: every package when
|
|
1704
|
+
* describing repository files alone, skipped packages in a whole-repository
|
|
1705
|
+
* summary, or, when the root is a package itself, those it does not depend on.
|
|
1706
|
+
*/
|
|
1707
|
+
async function excludedPackages(context, pkg, ref, onlyRepositoryFiles) {
|
|
1708
|
+
const { options, repository } = context;
|
|
1709
|
+
const directories = repository.packages.map((item) => item.directory);
|
|
1710
|
+
if (onlyRepositoryFiles || directories.length === 0) return directories;
|
|
1711
|
+
if (pkg.directory !== ".") return [];
|
|
1712
|
+
if (options.rootChangelog === "summary") return repository.packages.filter((item) => item.skipped === true).map((item) => item.directory);
|
|
1713
|
+
const scope = new Set(await packageScope(repository, pkg, ref));
|
|
1714
|
+
return directories.filter((directory) => !scope.has(directory));
|
|
1715
|
+
}
|
|
1666
1716
|
function cacheKey(context, release) {
|
|
1667
1717
|
const { effort, maxInputChars, model } = context.options;
|
|
1668
1718
|
return JSON.stringify({
|
|
@@ -2076,7 +2126,7 @@ function aggregateShared(context, prepared, results, exception, quiet) {
|
|
|
2076
2126
|
const rootEdit = plan.files.find((file) => path.dirname(file.path) === repository.root);
|
|
2077
2127
|
if (rootEdit === void 0) return;
|
|
2078
2128
|
const additions = prepared.summaries.map((summary) => ({
|
|
2079
|
-
changes: aggregateChanges(repository, plan.releases.filter((item) => item.version === summary.version && !quiet.has(`${item.changelogPath}@${item.version}`))),
|
|
2129
|
+
changes: aggregateChanges(repository, plan.releases.filter((item) => item.version === summary.version && item.ref === summary.ref && !quiet.has(`${item.changelogPath}@${item.version}`))),
|
|
2080
2130
|
existingBody: parseChangelog(rootEdit.after).sections.find((section) => section.version === summary.version)?.body,
|
|
2081
2131
|
release: prepared.releases.find((item) => item.version === summary.version)
|
|
2082
2132
|
}));
|
|
@@ -2089,11 +2139,11 @@ async function generateWorkspace(context) {
|
|
|
2089
2139
|
const shared = rootReleases.some((release) => release.version !== "Unreleased");
|
|
2090
2140
|
const rootFile = await findChangelog(repository.root);
|
|
2091
2141
|
const rootContent = options.rebuild ? void 0 : rootFile.content;
|
|
2092
|
-
const rootMissing = shared ?
|
|
2093
|
-
const needsPackageHistory = rootMissing === void 0 || rootMissing.
|
|
2094
|
-
const recordedAtRoot = (summary) => rootMissing === void 0 ? rootContent !== void 0 && missingPackageSummaries([summary], rootContent).length === 0 :
|
|
2142
|
+
const rootMissing = shared ? missingReleases(rootReleases, rootContent) : void 0;
|
|
2143
|
+
const needsPackageHistory = rootMissing === void 0 || rootMissing.some((release) => release.version !== "Unreleased");
|
|
2144
|
+
const recordedAtRoot = (summary) => rootMissing === void 0 ? rootContent !== void 0 && missingPackageSummaries([summary], rootContent).length === 0 : rootMissing.every((release) => release.version !== summary.version || release.ref !== summary.ref);
|
|
2095
2145
|
const packages = [];
|
|
2096
|
-
for (const pkg of repository
|
|
2146
|
+
for (const pkg of describedPackages(repository)) packages.push(await preparePackage(context, pkg, needsPackageHistory, recordedAtRoot));
|
|
2097
2147
|
const root = shared ? await preparePackage(context, repository.rootPackage) : void 0;
|
|
2098
2148
|
const independent = shared ? void 0 : await prepareIndependent(context, packages.flatMap((pkg) => pkg.summaries));
|
|
2099
2149
|
const requests = [...packages, ...root === void 0 ? [] : [root]].flatMap((pkg) => pkg.work.map((item) => item.request));
|
|
@@ -2127,6 +2177,7 @@ async function generateChangelog(options = {}) {
|
|
|
2127
2177
|
log.debug(`Resolved options: ${JSON.stringify(config)}`);
|
|
2128
2178
|
const repository = await inspectRepository(root, config);
|
|
2129
2179
|
log.debug(`Repository ${root} at ${repository.head}: ${repository.tags.length} reachable tags, ${repository.packages.length} workspace packages.`);
|
|
2180
|
+
if (config.rootChangelog === "none" && describedPackages(repository).length === 0) throw new Error("The root changelog is set to \"none\", but no workspace packages remain to describe, so there is no changelog to generate. Choose another root changelog mode, or configure packages that are not skipped.");
|
|
2130
2181
|
const agent = typeof selected === "object" ? selected : createAgent(config.agent);
|
|
2131
2182
|
const plan = {
|
|
2132
2183
|
checkpoints: [],
|
|
@@ -2154,14 +2205,20 @@ async function generateChangelog(options = {}) {
|
|
|
2154
2205
|
plan,
|
|
2155
2206
|
repository
|
|
2156
2207
|
};
|
|
2157
|
-
if (repository.packages.length ===
|
|
2158
|
-
|
|
2159
|
-
const results = await generateReleases(context, prepared.work.map((item) => item.request));
|
|
2160
|
-
plan.releases.push(...renderPackage(context, prepared, results));
|
|
2161
|
-
} else await generateWorkspace(context);
|
|
2208
|
+
if (repository.packages.length > 0 && config.rootChangelog === "summary") await generateWorkspace(context);
|
|
2209
|
+
else await generatePackages(context);
|
|
2162
2210
|
if (rebuild) keepEmptyRebuilds(plan);
|
|
2163
2211
|
return plan;
|
|
2164
2212
|
}
|
|
2213
|
+
/** Generate each changelog on its own, with no root summary. */
|
|
2214
|
+
async function generatePackages(context) {
|
|
2215
|
+
const { options, plan, repository } = context;
|
|
2216
|
+
const packages = options.rootChangelog === "none" ? describedPackages(repository) : [repository.rootPackage, ...describedPackages(repository)];
|
|
2217
|
+
const prepared = [];
|
|
2218
|
+
for (const pkg of packages) prepared.push(await preparePackage(context, pkg));
|
|
2219
|
+
const results = await generateReleases(context, prepared.flatMap((item) => item.work.map((work) => work.request)));
|
|
2220
|
+
for (const item of prepared) plan.releases.push(...renderPackage(context, item, results));
|
|
2221
|
+
}
|
|
2165
2222
|
/** A rebuild that finds nothing to record must not erase an existing changelog. */
|
|
2166
2223
|
function keepEmptyRebuilds(plan) {
|
|
2167
2224
|
plan.files = plan.files.filter((edit) => {
|
|
@@ -2322,4 +2379,4 @@ async function reviewChangelog(plan, options = {}) {
|
|
|
2322
2379
|
}
|
|
2323
2380
|
}
|
|
2324
2381
|
|
|
2325
|
-
export {
|
|
2382
|
+
export { maxTimeoutMinutes as C, defaults as S, git as _, defineConfig as a, setLogger as b, createAgent as c, rootChangelogs as d, LOCKFILE_PATH as f, manifestAt as g, localDate as h, generateChangelog as i, agentNames as l, isVersionOnlyChange as m, previewChangelog as n, loadConfig as o, inspectRepository as p, reviewChangelog as r, writeChangelog as s, assertReviewTerminal as t, efforts as u, isAncestor as v, version as w, defaultModels as x, runCommand as y };
|
|
@@ -17,6 +17,12 @@ declare const configSchema: z.ZodObject<{
|
|
|
17
17
|
maxInputChars: z.ZodOptional<z.ZodNumber>;
|
|
18
18
|
model: z.ZodOptional<z.ZodString>;
|
|
19
19
|
packages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
20
|
+
rootChangelog: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
summary: "summary";
|
|
22
|
+
package: "package";
|
|
23
|
+
none: "none";
|
|
24
|
+
}>>;
|
|
25
|
+
skipPackage: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
20
26
|
tagPatterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
21
27
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
22
28
|
}, z.core.$strict>;
|
|
@@ -29,8 +35,10 @@ declare const categories: readonly ["Added", "Changed", "Deprecated", "Removed",
|
|
|
29
35
|
type Category = (typeof categories)[number];
|
|
30
36
|
declare const agentNames: readonly ["codex", "claude"];
|
|
31
37
|
declare const efforts: readonly ["low", "medium", "high", "xhigh", "max"];
|
|
38
|
+
declare const rootChangelogs: readonly ["summary", "package", "none"];
|
|
32
39
|
type AgentName = (typeof agentNames)[number];
|
|
33
40
|
type Effort = (typeof efforts)[number];
|
|
41
|
+
type RootChangelog = (typeof rootChangelogs)[number];
|
|
34
42
|
type Change = {
|
|
35
43
|
breaking: boolean;
|
|
36
44
|
category: Category;
|
|
@@ -159,4 +167,4 @@ type ChangelogPlan = {
|
|
|
159
167
|
releases: ReleaseSummary[];
|
|
160
168
|
root: string;
|
|
161
169
|
};
|
|
162
|
-
export {
|
|
170
|
+
export { RunSettings as _, ChangeSet as a, loadConfig as b, Evidence as c, GenerationRequest as d, GenerationResponse as f, RootChangelog as g, ReleaseSummary as h, Change as i, FileEdit as l, ReleaseRequest as m, AgentName as n, ChangelogPlan as o, ReleaseContext as p, Category as r, Effort as s, AgentAdapter as t, GenerateOptions as u, Config as v, defineConfig as y };
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -132,24 +132,26 @@ Usage:
|
|
|
132
132
|
chagent
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
| Option | Description
|
|
136
|
-
| ----------------------- |
|
|
137
|
-
| `--cwd` | Repository directory
|
|
138
|
-
| `--agent` | Installed agent CLI
|
|
139
|
-
| `--model` | Agent model
|
|
140
|
-
| `--effort` | Reasoning effort
|
|
141
|
-
| `--interactive`<br>`-i` | Review a diff and optionally edit before writing
|
|
142
|
-
| `--editor` | Editor command for interactive review; configure GUI editors to wait
|
|
143
|
-
| `--dry-run` | Print a diff without applying changes
|
|
144
|
-
| `--rebuild` | Reconstruct all history, replacing existing release text
|
|
145
|
-
| `--amend` | Amend a verified unpublished release commit and matching local tags
|
|
146
|
-
| `--
|
|
147
|
-
| `--
|
|
148
|
-
| `--
|
|
149
|
-
| `--
|
|
150
|
-
| `--
|
|
151
|
-
| `--
|
|
152
|
-
| `--
|
|
135
|
+
| Option | Description | Type | Default |
|
|
136
|
+
| ----------------------- | --------------------------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------- |
|
|
137
|
+
| `--cwd` | Repository directory | `string` | current directory |
|
|
138
|
+
| `--agent` | Installed agent CLI | `"codex"` `"claude"` | `codex` |
|
|
139
|
+
| `--model` | Agent model | `string` | gpt-6.1-sol (Codex); claude-opus-5-5 (Claude) |
|
|
140
|
+
| `--effort` | Reasoning effort | `"low"` `"medium"` `"high"` `"xhigh"` `"max"` | `xhigh` |
|
|
141
|
+
| `--interactive`<br>`-i` | Review a diff and optionally edit before writing | `boolean` | `false` |
|
|
142
|
+
| `--editor` | Editor command for interactive review; configure GUI editors to wait | `string` | git var GIT_EDITOR |
|
|
143
|
+
| `--dry-run` | Print a diff without applying changes | `boolean` | `false` |
|
|
144
|
+
| `--rebuild` | Reconstruct all history, replacing existing release text | `boolean` | `false` |
|
|
145
|
+
| `--amend` | Amend a verified unpublished release commit and matching local tags | `boolean` | `false` |
|
|
146
|
+
| `--root-changelog` | Monorepo root changelog: a summary of package releases, the root package alone, or none | `"summary"` `"package"` `"none"` | `summary` |
|
|
147
|
+
| `--skip-package` | Workspace package directory glob to leave without a changelog; repeatable | `array` | `none` |
|
|
148
|
+
| `--github` | Enrich Git evidence using gh when available; disable with --no-github | `boolean` | `true` |
|
|
149
|
+
| `--cache` | Cache drafts and incremental state; disable with --no-cache | `boolean` | `true` |
|
|
150
|
+
| `--config` | Configuration file path | `string` | auto-detected from repository root |
|
|
151
|
+
| `--timeout` | Agent timeout in minutes | `number` | `20` |
|
|
152
|
+
| `--verbose` | Log commands, cache decisions, and session details to stderr | `boolean` | `false` |
|
|
153
|
+
| `--help`<br>`-h` | Show help | `boolean` | |
|
|
154
|
+
| `--version`<br>`-v` | Show version number | `boolean` | |
|
|
153
155
|
|
|
154
156
|
<!-- /cli-help -->
|
|
155
157
|
|
|
@@ -246,6 +248,10 @@ For an existing post-bump workflow, `chagent --amend` explicitly amends an unpub
|
|
|
246
248
|
|
|
247
249
|
Workspace declarations in `pnpm-workspace.yaml` or `package.json` determine the packages to process. Each current workspace package gets its own changelog. The root contains repository highlights and links to package releases.
|
|
248
250
|
|
|
251
|
+
Use the `rootChangelog` option or `--root-changelog` flag to choose what the root changelog records. The default, `summary`, works as described above. `package` treats the root as a package of its own, for repositories whose main package lives at the root: its changelog describes the root's files and the workspace packages it depends on in full detail, without changes from other packages or links to their releases. `none` writes only the package changelogs. After changing the mode of an existing root changelog, run with `--rebuild` to reconstruct its history in the new form.
|
|
252
|
+
|
|
253
|
+
Use `skipPackage` directory globs, or repeat `--skip-package`, to leave workspace packages such as documentation sites or examples without changelogs. A skipped package is left out of the root changelog, and its changes are not counted among the root's own, but packages that depend on it still include its relevant changes. To count a directory's changes as the root's instead, `exclude` it from workspace discovery. A pattern that matches no workspace package is an error.
|
|
254
|
+
|
|
249
255
|
For other monorepo layouts, configure `packages` directory globs. These directories do not need npm manifests; their Git tags identify releases, using the directory basename as the package name.
|
|
250
256
|
|
|
251
257
|
Shared-version repositories use repository versions at the root. Independently versioned repositories use package-qualified headings such as `@example/package@1.2.0`. Repository infrastructure changes appear in the root's `Unreleased` section. Explicit workspace dependencies contribute relevant source context to dependent packages. Dependency and tooling maintenance belongs under `Maintenance`. `build`, `coverage`, and `dist` directories at the top of a package count as generated output and are excluded, so a package named `packages/build` is still treated as source.
|
|
@@ -266,6 +272,7 @@ export default defineConfig({
|
|
|
266
272
|
github: true,
|
|
267
273
|
maxInputChars: 80_000,
|
|
268
274
|
model: 'gpt-6.1-sol',
|
|
275
|
+
rootChangelog: 'summary',
|
|
269
276
|
timeout: 20,
|
|
270
277
|
})
|
|
271
278
|
```
|
|
@@ -274,7 +281,7 @@ Importing `defineConfig` requires chagent in the repository's own dependencies.
|
|
|
274
281
|
|
|
275
282
|
Also supported: `chagent.config.mjs`, `chagent.config.js`, `chagent.config.json`, or a `chagent` key in `package.json`. CLI flags override configured values. `--config` selects a specific file.
|
|
276
283
|
|
|
277
|
-
Use `packages` and `exclude` directory globs to customize workspace discovery. Use `tagPatterns` to select unusual release tag conventions. Templates support `{name}` and `{version}`; defaults recognize `v1.2.3`, `1.2.3`, `@scope/package@1.2.3`, and `@scope/package/v1.2.3`.
|
|
284
|
+
Use `packages` and `exclude` directory globs to customize workspace discovery, and `skipPackage` to leave discovered packages without changelogs. Use `tagPatterns` to select unusual release tag conventions. Templates support `{name}` and `{version}`; defaults recognize `v1.2.3`, `1.2.3`, `@scope/package@1.2.3`, and `@scope/package/v1.2.3`.
|
|
278
285
|
|
|
279
286
|
## Background
|
|
280
287
|
|