compose-agentsmd 3.2.1 → 3.2.4

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/README.md CHANGED
@@ -134,4 +134,11 @@ npm install
134
134
  npm run lint
135
135
  npm run build
136
136
  npm test
137
- ```
137
+ ```
138
+
139
+ ## Overview
140
+ This repository contains the compose-agentsmd project.
141
+
142
+ ## Requirements and Configuration
143
+ - No required environment variables are documented.
144
+
@@ -16,6 +16,13 @@ const RULESET_SCHEMA_PATH = new URL("../agent-ruleset.schema.json", import.meta.
16
16
  const PACKAGE_JSON_PATH = new URL("../package.json", import.meta.url);
17
17
  const TOOL_RULES_PATH = new URL("../tools/tool-rules.md", import.meta.url);
18
18
  const USAGE_PATH = new URL("../tools/usage.txt", import.meta.url);
19
+ const readValueArg = (remaining, index, flag) => {
20
+ const value = remaining[index + 1];
21
+ if (!value) {
22
+ throw new Error(`Missing value for ${flag}`);
23
+ }
24
+ return value;
25
+ };
19
26
  const parseArgs = (argv) => {
20
27
  const args = {};
21
28
  const knownCommands = new Set(["edit-rules", "apply-rules", "init"]);
@@ -38,28 +45,19 @@ const parseArgs = (argv) => {
38
45
  continue;
39
46
  }
40
47
  if (arg === "--root") {
41
- const value = remaining[i + 1];
42
- if (!value) {
43
- throw new Error("Missing value for --root");
44
- }
48
+ const value = readValueArg(remaining, i, "--root");
45
49
  args.root = value;
46
50
  i += 1;
47
51
  continue;
48
52
  }
49
53
  if (arg === "--ruleset") {
50
- const value = remaining[i + 1];
51
- if (!value) {
52
- throw new Error("Missing value for --ruleset");
53
- }
54
+ const value = readValueArg(remaining, i, "--ruleset");
54
55
  args.ruleset = value;
55
56
  i += 1;
56
57
  continue;
57
58
  }
58
59
  if (arg === "--ruleset-name") {
59
- const value = remaining[i + 1];
60
- if (!value) {
61
- throw new Error("Missing value for --ruleset-name");
62
- }
60
+ const value = readValueArg(remaining, i, "--ruleset-name");
63
61
  args.rulesetName = value;
64
62
  i += 1;
65
63
  continue;
@@ -73,19 +71,13 @@ const parseArgs = (argv) => {
73
71
  continue;
74
72
  }
75
73
  if (arg === "--source") {
76
- const value = remaining[i + 1];
77
- if (!value) {
78
- throw new Error("Missing value for --source");
79
- }
74
+ const value = readValueArg(remaining, i, "--source");
80
75
  args.source = value;
81
76
  i += 1;
82
77
  continue;
83
78
  }
84
79
  if (arg === "--domains") {
85
- const value = remaining[i + 1];
86
- if (!value) {
87
- throw new Error("Missing value for --domains");
88
- }
80
+ const value = readValueArg(remaining, i, "--domains");
89
81
  args.domains = [...(args.domains ?? []), ...value.split(",").map((entry) => entry.trim())];
90
82
  i += 1;
91
83
  continue;
@@ -95,10 +87,7 @@ const parseArgs = (argv) => {
95
87
  continue;
96
88
  }
97
89
  if (arg === "--extra") {
98
- const value = remaining[i + 1];
99
- if (!value) {
100
- throw new Error("Missing value for --extra");
101
- }
90
+ const value = readValueArg(remaining, i, "--extra");
102
91
  args.extra = [...(args.extra ?? []), ...value.split(",").map((entry) => entry.trim())];
103
92
  i += 1;
104
93
  continue;
@@ -108,10 +97,7 @@ const parseArgs = (argv) => {
108
97
  continue;
109
98
  }
110
99
  if (arg === "--output") {
111
- const value = remaining[i + 1];
112
- if (!value) {
113
- throw new Error("Missing value for --output");
114
- }
100
+ const value = readValueArg(remaining, i, "--output");
115
101
  args.output = value;
116
102
  i += 1;
117
103
  continue;
@@ -506,12 +492,27 @@ const resolveRulesRoot = (rulesetDir, source, refresh) => {
506
492
  }
507
493
  return { rulesRoot: resolveLocalRulesRoot(rulesetDir, source) };
508
494
  };
495
+ const formatRuleSourcePath = (rulePath, rulesRoot, rulesetDir, source, resolvedRef) => {
496
+ // Check if this rule is from the resolved rulesRoot (GitHub or local source)
497
+ const isFromSource = rulePath.startsWith(rulesRoot);
498
+ if (isFromSource && source.startsWith("github:")) {
499
+ // GitHub source rule
500
+ const parsed = parseGithubSource(source);
501
+ const cacheRepoRoot = path.dirname(rulesRoot);
502
+ const relativePath = normalizePath(path.relative(cacheRepoRoot, rulePath));
503
+ const refToUse = resolvedRef ?? parsed.ref;
504
+ return `github:${parsed.owner}/${parsed.repo}@${refToUse}/${relativePath}`;
505
+ }
506
+ // For local rules (either from local source or extra), use path relative to project root
507
+ const result = normalizePath(path.relative(rulesetDir, rulePath));
508
+ return result;
509
+ };
509
510
  const composeRuleset = (rulesetPath, rootDir, options) => {
510
511
  const rulesetDir = path.dirname(rulesetPath);
511
512
  const projectRuleset = readProjectRuleset(rulesetPath);
512
513
  const outputFileName = projectRuleset.output ?? DEFAULT_OUTPUT;
513
514
  const outputPath = resolveFrom(rulesetDir, outputFileName);
514
- const { rulesRoot } = resolveRulesRoot(rulesetDir, projectRuleset.source, options.refresh ?? false);
515
+ const { rulesRoot, resolvedRef } = resolveRulesRoot(rulesetDir, projectRuleset.source, options.refresh ?? false);
515
516
  const globalRoot = path.join(rulesRoot, "global");
516
517
  const domainsRoot = path.join(rulesRoot, "domains");
517
518
  const resolvedRules = [];
@@ -529,7 +530,8 @@ const composeRuleset = (rulesetPath, rootDir, options) => {
529
530
  addRulePaths(directRulePaths, resolvedRules, seenRules);
530
531
  const parts = resolvedRules.map((rulePath) => {
531
532
  const body = normalizeTrailingWhitespace(fs.readFileSync(rulePath, "utf8"));
532
- return `Source: ${normalizePath(rulePath)}\n\n${body}`;
533
+ const sourcePath = formatRuleSourcePath(rulePath, rulesRoot, rulesetDir, projectRuleset.source, resolvedRef);
534
+ return `Source: ${sourcePath}\n\n${body}`;
533
535
  });
534
536
  const lintHeader = "<!-- markdownlint-disable MD025 -->";
535
537
  const toolRules = normalizeTrailingWhitespace(TOOL_RULES);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compose-agentsmd",
3
- "version": "3.2.1",
3
+ "version": "3.2.4",
4
4
  "description": "CLI tools for composing per-project AGENTS.md files from modular rule sets",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -44,7 +44,7 @@
44
44
  "node": ">=20"
45
45
  },
46
46
  "devDependencies": {
47
- "@types/node": "^25.0.10",
47
+ "@types/node": "^25.1.0",
48
48
  "typescript": "^5.7.3"
49
49
  },
50
50
  "dependencies": {
@@ -2,6 +2,7 @@
2
2
  - Before starting any work, run `compose-agentsmd` from the project root.
3
3
  - To update shared rules, run `compose-agentsmd edit-rules`, edit the workspace rules, then run `compose-agentsmd apply-rules`.
4
4
  - Do not edit `AGENTS.md` directly; update the source rules and regenerate.
5
+ - These tool rules live in tools/tool-rules.md in the compose-agentsmd repository; do not duplicate them in global rule modules.
5
6
  - When updating rules, include a colorized diff-style summary in the final response. Use `git diff --stat` first, then include the raw ANSI-colored output of `git diff --color=always` (no sanitizing or reformatting), and limit the output to the rule files that changed.
6
7
  - Also provide a short, copy-pasteable command the user can run to view the diff in the same format. Use absolute paths so it works regardless of the current working directory, and scope it to the changed rule files.
7
8
  - If a diff is provided, a separate detailed summary is not required. If a diff is not possible, include a detailed summary of what changed (added/removed/modified items).