@ryuenn3123/agentic-senior-core 4.4.0 → 5.2.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.
Files changed (201) hide show
  1. package/.agents/plugins/agentic-senior-core/plugin.json +3 -0
  2. package/.agents/plugins/agentic-senior-core/rules/agentic-senior-core.md +131 -0
  3. package/.agents/plugins/agentic-senior-core/skills/asc/SKILL.md +16 -0
  4. package/.agents/plugins/agentic-senior-core/skills/asc-audit/SKILL.md +28 -0
  5. package/.agents/plugins/agentic-senior-core/skills/asc-refactor/SKILL.md +35 -0
  6. package/.agents/plugins/agentic-senior-core/skills/asc-review/SKILL.md +54 -0
  7. package/.agents/rules/agentic-senior-core.md +131 -0
  8. package/.claude-plugin/marketplace.json +17 -0
  9. package/.claude-plugin/plugin.json +17 -0
  10. package/.clinerules/agentic-senior-core.md +94 -0
  11. package/.codex-plugin/plugin.json +24 -0
  12. package/.cursor/rules/agentic-senior-core.mdc +99 -0
  13. package/.devin-plugin/plugin.json +13 -0
  14. package/.github/copilot-instructions.md +94 -0
  15. package/.github/plugin/marketplace.json +20 -0
  16. package/.github/plugin/plugin.json +16 -0
  17. package/.kiro/steering/agentic-senior-core.md +94 -0
  18. package/.openclaw/skills/asc/SKILL.md +23 -0
  19. package/.openclaw/skills/asc-audit/SKILL.md +28 -0
  20. package/.openclaw/skills/asc-review/SKILL.md +54 -0
  21. package/.opencode/plugins/agentic-senior-core.mjs +31 -0
  22. package/.windsurf/rules/agentic-senior-core.md +94 -0
  23. package/AGENTS.md +126 -127
  24. package/CONTRIBUTING.md +93 -63
  25. package/README.md +190 -110
  26. package/__init__.py +61 -0
  27. package/bin/agentic-senior-core.js +42 -41
  28. package/commands/asc-audit.md +1 -0
  29. package/commands/asc-audit.toml +2 -0
  30. package/commands/asc-help.md +9 -0
  31. package/commands/asc-help.toml +2 -0
  32. package/commands/asc-refactor.md +1 -0
  33. package/commands/asc-refactor.toml +2 -0
  34. package/commands/asc-review.md +1 -0
  35. package/commands/asc-review.toml +2 -0
  36. package/gemini-extension.json +10 -0
  37. package/hooks/copilot-hooks.json +21 -0
  38. package/hooks/hooks.json +31 -0
  39. package/hooks/session-start.js +36 -0
  40. package/hooks/subagent-start.js +38 -0
  41. package/lib/cli/commands/adapter.mjs +109 -0
  42. package/lib/cli/commands/clean.mjs +63 -0
  43. package/lib/cli/commands/status.mjs +94 -0
  44. package/package.json +43 -60
  45. package/plugin.yaml +16 -0
  46. package/scripts/uninstall.js +38 -0
  47. package/skills/asc/SKILL.md +16 -0
  48. package/skills/asc-audit/SKILL.md +28 -0
  49. package/skills/asc-refactor/SKILL.md +35 -0
  50. package/skills/asc-review/SKILL.md +54 -0
  51. package/.agent-context/policies/llm-judge-threshold.json +0 -29
  52. package/.agent-context/prompts/bootstrap-design.md +0 -63
  53. package/.agent-context/prompts/compact-natural-mode.md +0 -100
  54. package/.agent-context/prompts/init-project.md +0 -60
  55. package/.agent-context/prompts/refactor.md +0 -38
  56. package/.agent-context/prompts/review-code.md +0 -31
  57. package/.agent-context/review-checklists/architecture-review.md +0 -57
  58. package/.agent-context/review-checklists/pr-checklist.md +0 -134
  59. package/.agent-context/rules/api-docs.md +0 -24
  60. package/.agent-context/rules/api-versioning.md +0 -16
  61. package/.agent-context/rules/architecture.md +0 -38
  62. package/.agent-context/rules/background-jobs.md +0 -17
  63. package/.agent-context/rules/config-and-flags.md +0 -16
  64. package/.agent-context/rules/database-design.md +0 -18
  65. package/.agent-context/rules/docker-runtime.md +0 -17
  66. package/.agent-context/rules/error-handling.md +0 -16
  67. package/.agent-context/rules/event-driven.md +0 -16
  68. package/.agent-context/rules/frontend-architecture.md +0 -54
  69. package/.agent-context/rules/microservices.md +0 -16
  70. package/.agent-context/rules/migrations.md +0 -16
  71. package/.agent-context/rules/observability.md +0 -16
  72. package/.agent-context/rules/performance.md +0 -16
  73. package/.agent-context/rules/realtime.md +0 -16
  74. package/.agent-context/rules/resilience.md +0 -18
  75. package/.agent-context/rules/security.md +0 -18
  76. package/.agent-context/rules/testing.md +0 -16
  77. package/.agent-context/state/README.md +0 -25
  78. package/.agent-context/state/architecture-map.md +0 -40
  79. package/.agent-context/state/benchmark-comparison-schema.json +0 -181
  80. package/.agent-context/state/benchmark-reproducibility.json +0 -87
  81. package/.agent-context/state/benchmark-thresholds.json +0 -10
  82. package/.agent-context/state/benchmark-writer-judge-config.json +0 -58
  83. package/.agent-context/state/dependency-map.md +0 -41
  84. package/.agent-context/state/memory-adapter-contract.json +0 -52
  85. package/.agent-context/state/memory-schema-v1.json +0 -88
  86. package/GEMINI.md +0 -1
  87. package/benchmarks/README.md +0 -60
  88. package/benchmarks/compact-natural-mode/fixtures.mjs +0 -359
  89. package/benchmarks/compact-natural-mode/scorer.mjs +0 -331
  90. package/benchmarks/runtime-token-saver/fixtures.mjs +0 -836
  91. package/lib/cli/adaptive-context/catalog.mjs +0 -394
  92. package/lib/cli/adaptive-context/file-signals.mjs +0 -100
  93. package/lib/cli/adaptive-context/implications.mjs +0 -44
  94. package/lib/cli/adaptive-context.mjs +0 -151
  95. package/lib/cli/audits/typography-palette-anti-repeat/color-utils.mjs +0 -156
  96. package/lib/cli/audits/typography-palette-anti-repeat/file-scanner.mjs +0 -103
  97. package/lib/cli/audits/typography-palette-anti-repeat/typography-utils.mjs +0 -70
  98. package/lib/cli/backup.mjs +0 -210
  99. package/lib/cli/commands/context.mjs +0 -140
  100. package/lib/cli/commands/init/project-context.mjs +0 -60
  101. package/lib/cli/commands/init/runtime-environment.mjs +0 -59
  102. package/lib/cli/commands/init/setup-decisions.mjs +0 -83
  103. package/lib/cli/commands/init.mjs +0 -654
  104. package/lib/cli/commands/launch.mjs +0 -76
  105. package/lib/cli/commands/optimize.mjs +0 -284
  106. package/lib/cli/commands/rollback.mjs +0 -64
  107. package/lib/cli/commands/upgrade/token-optimization-state.mjs +0 -51
  108. package/lib/cli/commands/upgrade.mjs +0 -451
  109. package/lib/cli/compiler.mjs +0 -187
  110. package/lib/cli/constants.mjs +0 -136
  111. package/lib/cli/detector/constants.mjs +0 -135
  112. package/lib/cli/detector/design-evidence/collector.mjs +0 -256
  113. package/lib/cli/detector/design-evidence/constants.mjs +0 -39
  114. package/lib/cli/detector/design-evidence/file-traversal.mjs +0 -83
  115. package/lib/cli/detector/design-evidence/structured-attribute-evidence.mjs +0 -117
  116. package/lib/cli/detector/design-evidence/summary.mjs +0 -109
  117. package/lib/cli/detector/design-evidence/utility-helpers.mjs +0 -122
  118. package/lib/cli/detector/design-evidence.mjs +0 -25
  119. package/lib/cli/detector/stack-detection.mjs +0 -243
  120. package/lib/cli/detector/ui-signals.mjs +0 -150
  121. package/lib/cli/detector/workspace-scan.mjs +0 -177
  122. package/lib/cli/detector.mjs +0 -23
  123. package/lib/cli/init-detection-flow.mjs +0 -48
  124. package/lib/cli/init-options.mjs +0 -237
  125. package/lib/cli/init-selection.mjs +0 -29
  126. package/lib/cli/memory-continuity.mjs +0 -537
  127. package/lib/cli/preflight.mjs +0 -76
  128. package/lib/cli/project-scaffolder/constants.mjs +0 -69
  129. package/lib/cli/project-scaffolder/discovery.mjs +0 -272
  130. package/lib/cli/project-scaffolder/prompt-builders.mjs +0 -171
  131. package/lib/cli/project-scaffolder/storage.mjs +0 -144
  132. package/lib/cli/project-scaffolder/ui-scope-detection.mjs +0 -36
  133. package/lib/cli/project-scaffolder.mjs +0 -29
  134. package/lib/cli/rollback.mjs +0 -66
  135. package/lib/cli/token-optimization.mjs +0 -401
  136. package/lib/cli/utils/filesystem.mjs +0 -81
  137. package/lib/cli/utils/managed-surface.mjs +0 -280
  138. package/lib/cli/utils/prompting.mjs +0 -44
  139. package/lib/cli/utils.mjs +0 -479
  140. package/mcp.json +0 -134
  141. package/scripts/adaptive-context/fixtures.mjs +0 -183
  142. package/scripts/adaptive-context-benchmark.mjs +0 -9
  143. package/scripts/ascx-runtime-token-saver-benchmark.mjs +0 -9
  144. package/scripts/benchmark-evidence-bundle.mjs +0 -645
  145. package/scripts/benchmark-gate.mjs +0 -121
  146. package/scripts/benchmark-intelligence.mjs +0 -33
  147. package/scripts/benchmark-writer-judge-matrix.mjs +0 -379
  148. package/scripts/build-release-benchmark-bundle.mjs +0 -202
  149. package/scripts/bump-version.mjs +0 -103
  150. package/scripts/clean-local-artifacts.mjs +0 -78
  151. package/scripts/compact-natural-mode-benchmark.mjs +0 -9
  152. package/scripts/context-triggered-audit.mjs +0 -391
  153. package/scripts/detection-benchmark.mjs +0 -127
  154. package/scripts/docs-quality-drift-report.mjs +0 -358
  155. package/scripts/documentation-boundary-audit.mjs +0 -305
  156. package/scripts/explain-on-demand-audit.mjs +0 -427
  157. package/scripts/forbidden-content-check.mjs +0 -123
  158. package/scripts/frontend-usability-audit.mjs +0 -243
  159. package/scripts/generate-sbom.mjs +0 -61
  160. package/scripts/governance-weekly-report.mjs +0 -466
  161. package/scripts/llm-judge/checklist-loader.mjs +0 -45
  162. package/scripts/llm-judge/constants.mjs +0 -66
  163. package/scripts/llm-judge/diff-collection.mjs +0 -74
  164. package/scripts/llm-judge/prompting.mjs +0 -78
  165. package/scripts/llm-judge/providers.mjs +0 -111
  166. package/scripts/llm-judge/verdict.mjs +0 -134
  167. package/scripts/llm-judge.mjs +0 -200
  168. package/scripts/memory-continuity-benchmark.mjs +0 -322
  169. package/scripts/quality-trend-report.mjs +0 -289
  170. package/scripts/release-gate/audit-checks.mjs +0 -441
  171. package/scripts/release-gate/constants.mjs +0 -53
  172. package/scripts/release-gate/runtime.mjs +0 -63
  173. package/scripts/release-gate/static-checks.mjs +0 -182
  174. package/scripts/release-gate.mjs +0 -42
  175. package/scripts/rules-guardian-audit.mjs +0 -580
  176. package/scripts/single-source-lazy-loading-audit.mjs +0 -449
  177. package/scripts/sync-thin-adapters.mjs +0 -72
  178. package/scripts/token-optimization-benchmark.mjs +0 -252
  179. package/scripts/ui-design-judge/constants.mjs +0 -13
  180. package/scripts/ui-design-judge/design-execution-summary.mjs +0 -81
  181. package/scripts/ui-design-judge/git-input.mjs +0 -134
  182. package/scripts/ui-design-judge/prompting.mjs +0 -52
  183. package/scripts/ui-design-judge/providers.mjs +0 -102
  184. package/scripts/ui-design-judge/reporting.mjs +0 -183
  185. package/scripts/ui-design-judge/rubric-calibration.mjs +0 -214
  186. package/scripts/ui-design-judge/rubric-goldset.json +0 -188
  187. package/scripts/ui-design-judge.mjs +0 -319
  188. package/scripts/ui-rubric-calibration.mjs +0 -35
  189. package/scripts/validate/audits/cache-layer-contract.mjs +0 -230
  190. package/scripts/validate/audits/caching-scope-hygiene.mjs +0 -235
  191. package/scripts/validate/audits/file-size.mjs +0 -158
  192. package/scripts/validate/audits/reflection-citations.mjs +0 -130
  193. package/scripts/validate/audits/release-bundle.mjs +0 -135
  194. package/scripts/validate/audits/rule-id-uniqueness.mjs +0 -278
  195. package/scripts/validate/config.mjs +0 -501
  196. package/scripts/validate/coverage-checks.mjs +0 -446
  197. package/scripts/validate/file-structure.mjs +0 -158
  198. package/scripts/validate/markdown-content.mjs +0 -109
  199. package/scripts/validate/project-metadata.mjs +0 -166
  200. package/scripts/validate/utils.mjs +0 -52
  201. package/scripts/validate.mjs +0 -267
@@ -1,66 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { pathExists, ensureDirectory } from './utils.mjs';
4
- import { BACKUP_DIR_NAME } from './constants.mjs';
5
-
6
- /**
7
- * Performs a rollback of a target directory using the backup manifest.
8
- * @param {string} targetDirectoryPath
9
- */
10
- export async function performRollback(targetDirectoryPath) {
11
- const startTime = Date.now();
12
- const backupRoot = path.join(targetDirectoryPath, BACKUP_DIR_NAME);
13
- const manifestPath = path.join(backupRoot, 'manifest.json');
14
- const objectsDir = path.join(backupRoot, 'objects');
15
-
16
- if (!(await pathExists(manifestPath))) {
17
- throw new Error(`Rollback failed: Backup manifest not found at ${manifestPath}`);
18
- }
19
-
20
- const manifestData = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
21
- const report = {
22
- restoredFiles: [],
23
- deletedFiles: [],
24
- errors: []
25
- };
26
-
27
- for (const [relativePath, fileManifest] of Object.entries(manifestData.files)) {
28
- const destinationPath = path.join(targetDirectoryPath, relativePath);
29
-
30
- if (fileManifest.action === 'restore') {
31
- const sourceObjectPath = path.join(objectsDir, fileManifest.hash);
32
- if (!(await pathExists(sourceObjectPath))) {
33
- report.errors.push(`Missing backup object for file: ${relativePath} (Expected hash: ${fileManifest.hash})`);
34
- continue;
35
- }
36
-
37
- try {
38
- await ensureDirectory(path.dirname(destinationPath));
39
- await fs.copyFile(sourceObjectPath, destinationPath);
40
- report.restoredFiles.push(relativePath);
41
- } catch (err) {
42
- report.errors.push(`Failed to restore ${relativePath}: ${err.message}`);
43
- }
44
- } else if (fileManifest.action === 'delete') {
45
- // File did not exist before, but might exist now
46
- if (await pathExists(destinationPath)) {
47
- try {
48
- const stats = await fs.stat(destinationPath);
49
- if (stats.isDirectory()) {
50
- await fs.rm(destinationPath, { recursive: true, force: true });
51
- } else {
52
- await fs.unlink(destinationPath);
53
- }
54
- report.deletedFiles.push(relativePath);
55
- } catch (err) {
56
- report.errors.push(`Failed to delete dynamically added file ${relativePath}: ${err.message}`);
57
- }
58
- }
59
- }
60
- }
61
-
62
- report.durationMs = Date.now() - startTime;
63
- report.success = report.errors.length === 0;
64
-
65
- return report;
66
- }
@@ -1,401 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { spawnSync } from 'node:child_process';
5
- import { platform } from 'node:process';
6
-
7
- import { REPOSITORY_ROOT } from './constants.mjs';
8
- import { pathExists } from './utils.mjs';
9
-
10
- export const TOKEN_OPTIMIZATION_STATE_FILE_NAME = 'token-optimization.json';
11
- export const TOKEN_OPTIMIZATION_REPORT_FILE_NAME = 'token-optimization-report.json';
12
-
13
- const TOKEN_OPTIMIZATION_SCHEMA_VERSION = 'token-optimization-v1';
14
- const FALLBACK_AGENT_NAME = 'copilot';
15
-
16
- const SUPPORTED_AGENT_NAMES = new Set([
17
- 'copilot',
18
- 'claude',
19
- 'cursor',
20
- 'windsurf',
21
- 'gemini',
22
- 'codex',
23
- 'cline',
24
- ]);
25
-
26
- const COMMAND_REWRITE_MAPPINGS = [
27
- {
28
- rawCommand: 'git status',
29
- optimizedCommand: 'ascx git status',
30
- reason: 'ASCX condenses status output while preserving changed-file evidence and raw tee safety.',
31
- },
32
- {
33
- rawCommand: 'git diff',
34
- optimizedCommand: 'ascx git diff',
35
- reason: 'ASCX preserves changed files, hunk anchors, binary/deleted markers, truncation notes, and raw tee safety.',
36
- },
37
- {
38
- rawCommand: 'npm test',
39
- optimizedCommand: 'ascx npm test',
40
- reason: 'ASCX preserves exit code, failing tests, assertions, file paths, and raw tee safety.',
41
- },
42
- ];
43
-
44
-
45
- const OUTPUT_FOLDING_STRATEGY = {
46
- mode: 'compact-high-signal-output',
47
- appliesTo: [
48
- 'shell-command-output',
49
- 'test-output',
50
- 'build-output',
51
- 'diff-output',
52
- 'log-output',
53
- ],
54
- preserveAlways: [
55
- 'exit-code',
56
- 'failing-command',
57
- 'file-and-line',
58
- 'error-message',
59
- 'actionable-warning',
60
- ],
61
- foldByDefault: [
62
- 'repeated-success-lines',
63
- 'large-unchanged-diff-context',
64
- 'verbose-install-progress',
65
- 'duplicated-stack-frames',
66
- 'low-signal-directory-noise',
67
- ],
68
- nativeFallback: [
69
- 'prefer --stat or --name-only before full diff',
70
- 'prefer focused rg queries before broad file dumps',
71
- 'prefer failure-focused test reporters when available',
72
- 'summarize long logs before hydrating full detail',
73
- ],
74
- safetyBoundary: [
75
- 'never hide failing checks',
76
- 'never drop the command that produced output',
77
- 'never persist secrets into summaries',
78
- 'hydrate full output only when the compact summary is insufficient',
79
- ],
80
- };
81
-
82
- function parseRtkVersion(versionOutput) {
83
- const versionMatch = versionOutput.match(/\d+\.\d+\.\d+/);
84
- return versionMatch ? versionMatch[0] : null;
85
- }
86
-
87
- export function normalizeAgentName(rawAgentName = FALLBACK_AGENT_NAME) {
88
- const normalizedAgentName = String(rawAgentName || '')
89
- .trim()
90
- .toLowerCase();
91
-
92
- if (!normalizedAgentName) {
93
- return FALLBACK_AGENT_NAME;
94
- }
95
-
96
- if (!SUPPORTED_AGENT_NAMES.has(normalizedAgentName)) {
97
- throw new Error(
98
- `Unsupported agent "${rawAgentName}". Supported values: ${Array.from(SUPPORTED_AGENT_NAMES).join(', ')}`
99
- );
100
- }
101
-
102
- return normalizedAgentName;
103
- }
104
-
105
- export function detectRtkBinary() {
106
- try {
107
- const versionResult = spawnSync('rtk', ['--version'], {
108
- encoding: 'utf8',
109
- stdio: ['ignore', 'pipe', 'pipe'],
110
- });
111
-
112
- if (versionResult.status !== 0) {
113
- return {
114
- isAvailable: false,
115
- version: null,
116
- detectionError: (versionResult.stderr || versionResult.stdout || 'Unknown external proxy detection error').trim(),
117
- };
118
- }
119
-
120
- const detectedVersion = parseRtkVersion(versionResult.stdout || '');
121
- return {
122
- isAvailable: true,
123
- version: detectedVersion,
124
- detectionError: null,
125
- };
126
- } catch (detectionError) {
127
- return {
128
- isAvailable: false,
129
- version: null,
130
- detectionError: detectionError instanceof Error ? detectionError.message : String(detectionError),
131
- };
132
- }
133
- }
134
-
135
- export function detectAscxRuntime() {
136
- const localBinPath = path.join(REPOSITORY_ROOT, 'bin', 'ascx.js');
137
- const pathDetection = spawnSync('ascx', [], {
138
- encoding: 'utf8',
139
- stdio: ['ignore', 'pipe', 'pipe'],
140
- });
141
- const pathBinaryLooksAvailable = pathDetection.error == null
142
- && typeof pathDetection.status === 'number'
143
- && /command is required/i.test(`${pathDetection.stdout || ''}\n${pathDetection.stderr || ''}`);
144
-
145
- if (pathBinaryLooksAvailable) {
146
- return {
147
- isAvailable: true,
148
- source: 'path',
149
- command: 'ascx',
150
- localBinPath,
151
- detectionError: null,
152
- };
153
- }
154
-
155
- if (existsSync(localBinPath)) {
156
- return {
157
- isAvailable: true,
158
- source: 'package-bin',
159
- command: `node ${localBinPath}`,
160
- localBinPath,
161
- detectionError: pathDetection.error ? pathDetection.error.message : null,
162
- };
163
- }
164
-
165
- return {
166
- isAvailable: false,
167
- source: 'missing',
168
- command: null,
169
- localBinPath,
170
- detectionError: pathDetection.error
171
- ? pathDetection.error.message
172
- : (pathDetection.stderr || pathDetection.stdout || 'ascx binary was not detected').trim(),
173
- };
174
- }
175
-
176
- export async function checkAscxTeeReadiness(targetDirectoryPath, options = {}) {
177
- const shouldWriteProbe = options.writeProbe === true;
178
- const stateDirectoryPath = path.join(targetDirectoryPath, '.agent-context', 'state');
179
- const teeDirectoryPath = path.join(stateDirectoryPath, 'token-saver', 'tee');
180
-
181
- try {
182
- if (shouldWriteProbe) {
183
- await fs.mkdir(teeDirectoryPath, { recursive: true });
184
- const probeFilePath = path.join(teeDirectoryPath, `.ascx-probe-${process.pid}.tmp`);
185
- await fs.writeFile(probeFilePath, 'ascx tee probe\n', 'utf8');
186
- await fs.rm(probeFilePath, { force: true });
187
- } else {
188
- await fs.access(stateDirectoryPath);
189
- }
190
-
191
- return {
192
- status: 'writable',
193
- path: teeDirectoryPath,
194
- error: null,
195
- };
196
- } catch (readinessError) {
197
- return {
198
- status: 'not-writable',
199
- path: teeDirectoryPath,
200
- error: readinessError instanceof Error ? readinessError.message : String(readinessError),
201
- };
202
- }
203
- }
204
-
205
- export function resolveRuntimeTokenSaverMode({
206
- tokenOptimizationState,
207
- ascxDetection,
208
- rtkDetection,
209
- }) {
210
- const stateEnabled = tokenOptimizationState?.enabled === true;
211
- const rtkDetected = rtkDetection?.isAvailable === true;
212
-
213
- if (stateEnabled && ascxDetection?.isAvailable && rtkDetected) {
214
- return 'conflict-risk';
215
- }
216
-
217
- if (stateEnabled && ascxDetection?.isAvailable) {
218
- return 'runtime-on';
219
- }
220
-
221
- if (stateEnabled) {
222
- return 'policy-only';
223
- }
224
-
225
- if (rtkDetected) {
226
- return 'external-runtime-detected';
227
- }
228
-
229
- return 'runtime-off';
230
- }
231
-
232
- export function buildRuntimeTokenSaverWarnings({
233
- mode,
234
- onboardingReport,
235
- ascxDetection,
236
- teeReadiness,
237
- rtkDetection,
238
- }) {
239
- const warnings = [];
240
-
241
- if (!onboardingReport) {
242
- warnings.push('project is not initialized; run init before enabling runtime token saving');
243
- }
244
-
245
- if (!ascxDetection?.isAvailable) {
246
- warnings.push('ascx binary is missing; supported commands will not be compressed');
247
- }
248
-
249
- if (teeReadiness?.status !== 'writable') {
250
- warnings.push('raw tee folder is not writable; failing commands may lose safety logs');
251
- }
252
-
253
- if (mode === 'conflict-risk') {
254
- warnings.push('ASCX and an external runtime compressor both appear active; avoid double compression');
255
- } else if (rtkDetection?.isAvailable) {
256
- warnings.push('external runtime compressor detected; keep only one runtime compressor enabled by default');
257
- }
258
-
259
- return warnings;
260
- }
261
-
262
- export function buildRuntimeTokenSaverNextAction({ mode, warnings }) {
263
- if (warnings.some((warning) => warning.includes('not initialized'))) {
264
- return 'Run agentic-senior-core init before enabling ASCX runtime saving.';
265
- }
266
-
267
- if (warnings.some((warning) => warning.includes('tee folder'))) {
268
- return 'Fix .agent-context/state write access, then rerun optimize doctor.';
269
- }
270
-
271
- if (mode === 'conflict-risk') {
272
- return 'Disable either ASCX runtime saving or the external compressor before using compressed command output.';
273
- }
274
-
275
- if (mode === 'runtime-on') {
276
- return 'Use ascx git status, ascx git diff, and ascx npm test for supported high-volume command output.';
277
- }
278
-
279
- if (mode === 'policy-only') {
280
- return 'Install or expose the ascx binary, then rerun optimize doctor.';
281
- }
282
-
283
- return 'Run agentic-senior-core optimize install to enable ASCX guidance for this repository.';
284
- }
285
-
286
- export function buildRtkInstallHint() {
287
- return 'If an external token optimizer (rtk) is installed, prefer it for commands not covered by ASCX.';
288
- }
289
-
290
- export function buildRtkHookCommand(selectedAgentName) {
291
- const normalizedAgentName = normalizeAgentName(selectedAgentName);
292
- return `rtk init -g --${normalizedAgentName}`;
293
- }
294
-
295
-
296
- export function createTokenOptimizationState({
297
- isEnabled,
298
- selectedAgentName,
299
- rtkDetection,
300
- }) {
301
- return {
302
- schemaVersion: TOKEN_OPTIMIZATION_SCHEMA_VERSION,
303
- enabled: Boolean(isEnabled),
304
- selectedAgent: normalizeAgentName(selectedAgentName),
305
- preferredShellProxy: rtkDetection.isAvailable ? 'external-proxy' : 'native-fallback',
306
- externalProxy: {
307
- detected: Boolean(rtkDetection.isAvailable),
308
- version: rtkDetection.version,
309
- detectionError: rtkDetection.detectionError,
310
- },
311
- commandRewriteMappings: COMMAND_REWRITE_MAPPINGS.map((mapping) => ({ ...mapping })),
312
- outputFoldingStrategy: {
313
- ...OUTPUT_FOLDING_STRATEGY,
314
- appliesTo: [...OUTPUT_FOLDING_STRATEGY.appliesTo],
315
- preserveAlways: [...OUTPUT_FOLDING_STRATEGY.preserveAlways],
316
- foldByDefault: [...OUTPUT_FOLDING_STRATEGY.foldByDefault],
317
- nativeFallback: [...OUTPUT_FOLDING_STRATEGY.nativeFallback],
318
- safetyBoundary: [...OUTPUT_FOLDING_STRATEGY.safetyBoundary],
319
- },
320
- generatedAt: new Date().toISOString(),
321
- };
322
- }
323
-
324
- export async function readTokenOptimizationState(targetDirectoryPath) {
325
- const stateFilePath = path.join(
326
- targetDirectoryPath,
327
- '.agent-context',
328
- 'state',
329
- TOKEN_OPTIMIZATION_STATE_FILE_NAME
330
- );
331
-
332
- if (!(await pathExists(stateFilePath))) {
333
- return null;
334
- }
335
-
336
- try {
337
- const stateContent = await fs.readFile(stateFilePath, 'utf8');
338
- const parsedState = JSON.parse(stateContent);
339
- if (typeof parsedState.enabled !== 'boolean') {
340
- return null;
341
- }
342
- return parsedState;
343
- } catch {
344
- return null;
345
- }
346
- }
347
-
348
- export async function writeTokenOptimizationState(targetDirectoryPath, tokenOptimizationState) {
349
- const stateDirectoryPath = path.join(targetDirectoryPath, '.agent-context', 'state');
350
- const stateFilePath = path.join(stateDirectoryPath, TOKEN_OPTIMIZATION_STATE_FILE_NAME);
351
-
352
- await fs.mkdir(stateDirectoryPath, { recursive: true });
353
- await fs.writeFile(stateFilePath, JSON.stringify(tokenOptimizationState, null, 2) + '\n', 'utf8');
354
- }
355
-
356
- export function buildTokenOptimizationGuidanceBlock(tokenOptimizationState) {
357
- if (!tokenOptimizationState?.enabled) {
358
- return [
359
- 'Token optimization mode is disabled for this repository.',
360
- 'Use native shell commands with manual output limiting when needed.',
361
- ].join('\n');
362
- }
363
-
364
- const rewriteLines = (tokenOptimizationState.commandRewriteMappings || []).map(
365
- (mapping) => `- ${mapping.rawCommand} => ${mapping.optimizedCommand} (${mapping.reason})`
366
- );
367
-
368
- const fallbackGuidance = [
369
- '- Use ascx git status, ascx git diff, and ascx npm test when the ascx binary is available.',
370
- '- Use command variants with bounded output such as git diff --stat, rg --max-count, and npm test -- --reporter=dot.',
371
- '- Request only the lines or sections required for the current decision.',
372
- '- If shell output is still large, summarize and continue iteratively instead of dumping full logs.',
373
- ];
374
-
375
- const outputFoldingStrategy = tokenOptimizationState.outputFoldingStrategy || OUTPUT_FOLDING_STRATEGY;
376
- const outputFoldingLines = [
377
- `- Mode: ${outputFoldingStrategy.mode || OUTPUT_FOLDING_STRATEGY.mode}.`,
378
- `- Preserve always: ${(outputFoldingStrategy.preserveAlways || OUTPUT_FOLDING_STRATEGY.preserveAlways).join(', ')}.`,
379
- `- Fold by default: ${(outputFoldingStrategy.foldByDefault || OUTPUT_FOLDING_STRATEGY.foldByDefault).join(', ')}.`,
380
- `- Safety boundary: ${(outputFoldingStrategy.safetyBoundary || OUTPUT_FOLDING_STRATEGY.safetyBoundary).join(', ')}.`,
381
- ];
382
-
383
- return [
384
- `Token optimization mode is enabled for agent: ${tokenOptimizationState.selectedAgent}.`,
385
- `Preferred shell proxy: ${tokenOptimizationState.preferredShellProxy}.`,
386
- '',
387
- 'Apply command rewrites before running verbose shell commands:',
388
- ...rewriteLines,
389
- '',
390
- 'Important scope note:',
391
- '- ASCX wrappers are explicit local command wrappers, not provider gateways.',
392
- '- Shell rewrite hooks affect shell tool calls only.',
393
- '- Built-in read/grep/glob style tools may bypass shell rewrites, so explicit compact shell commands should be preferred in high-volume sessions.',
394
- '',
395
- 'Output folding policy:',
396
- ...outputFoldingLines,
397
- '',
398
- 'Fallback behavior when external proxy is unavailable:',
399
- ...fallbackGuidance,
400
- ].join('\n');
401
- }
@@ -1,81 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
-
4
- export async function pathExists(targetPath) {
5
- try {
6
- await fs.stat(targetPath);
7
- return true;
8
- } catch {
9
- return false;
10
- }
11
- }
12
-
13
- export async function ensureDirectory(directoryPath) {
14
- await fs.mkdir(directoryPath, { recursive: true });
15
- }
16
-
17
- export async function copyDirectory(sourceDirectoryPath, targetDirectoryPath) {
18
- if (path.resolve(sourceDirectoryPath) === path.resolve(targetDirectoryPath)) {
19
- return;
20
- }
21
-
22
- await ensureDirectory(targetDirectoryPath);
23
- const directoryEntries = await fs.readdir(sourceDirectoryPath, { withFileTypes: true });
24
-
25
- for (const directoryEntry of directoryEntries) {
26
- const sourceEntryPath = path.join(sourceDirectoryPath, directoryEntry.name);
27
- const targetEntryPath = path.join(targetDirectoryPath, directoryEntry.name);
28
-
29
- if (directoryEntry.isDirectory()) {
30
- await copyDirectory(sourceEntryPath, targetEntryPath);
31
- continue;
32
- }
33
-
34
- if (path.resolve(sourceEntryPath) === path.resolve(targetEntryPath)) {
35
- continue;
36
- }
37
-
38
- await fs.copyFile(sourceEntryPath, targetEntryPath);
39
- }
40
- }
41
-
42
- export function isAgenticManagedContent(content) {
43
- const normalizedContent = Buffer.isBuffer(content)
44
- ? content.toString('utf8')
45
- : String(content || '');
46
-
47
- return [
48
- 'Agentic-Senior-Core',
49
- 'AGENTIC-SENIOR-CORE',
50
- 'Adapter Mode: thin',
51
- 'Adapter Mode: legacy-thin',
52
- 'Canonical Snapshot SHA256',
53
- 'Canonical baseline: .instructions.md',
54
- 'canonical instruction source for this repository',
55
- '@AGENTS.md',
56
- ].some((managedSignal) => normalizedContent.includes(managedSignal));
57
- }
58
-
59
- export async function syncFile(sourcePath, targetPath, options = {}) {
60
- if (!(await pathExists(sourcePath))) return { status: 'skipped' };
61
-
62
- if (!(await pathExists(targetPath))) {
63
- await ensureDirectory(path.dirname(targetPath));
64
- await fs.copyFile(sourcePath, targetPath);
65
- return { status: 'created' };
66
- }
67
-
68
- const sourceContent = await fs.readFile(sourcePath);
69
- const targetContent = await fs.readFile(targetPath);
70
-
71
- if (sourceContent.equals(targetContent)) {
72
- return { status: 'unchanged' };
73
- }
74
-
75
- if (options.preserveUserOwned === true && !isAgenticManagedContent(targetContent)) {
76
- return { status: 'preserved' };
77
- }
78
-
79
- await fs.copyFile(sourcePath, targetPath);
80
- return { status: 'updated' };
81
- }