@hongmaple0820/scale-engine 0.14.0 → 0.15.1
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.en.md +13 -5
- package/README.md +13 -5
- package/dist/adapters/AiderAdapter.js +52 -52
- package/dist/adapters/ClaudeCodeAdapter.js +5 -5
- package/dist/adapters/DeepSeekTuiAdapter.js +5 -5
- package/dist/adapters/DoubaoAdapter.js +33 -33
- package/dist/adapters/KimiAdapter.js +32 -32
- package/dist/adapters/KiroAdapter.js +26 -26
- package/dist/adapters/WindsurfAdapter.js +32 -32
- package/dist/api/cli.js +296 -3
- package/dist/api/cli.js.map +1 -1
- package/dist/api/doctor.d.ts +2 -0
- package/dist/api/doctor.js +83 -0
- package/dist/api/doctor.js.map +1 -1
- package/dist/api/mcp.js +2 -1
- package/dist/api/mcp.js.map +1 -1
- package/dist/capabilities/InstalledSkillsIntegration.d.ts +3 -0
- package/dist/capabilities/InstalledSkillsIntegration.js +41 -17
- package/dist/capabilities/InstalledSkillsIntegration.js.map +1 -1
- package/dist/cli/phaseCommands.js +63 -5
- package/dist/cli/phaseCommands.js.map +1 -1
- package/dist/core/logger.d.ts +2 -0
- package/dist/core/logger.js +33 -1
- package/dist/core/logger.js.map +1 -1
- package/dist/output/HTMLDocumentRenderer.js +3 -2
- package/dist/output/HTMLDocumentRenderer.js.map +1 -1
- package/dist/skills/ExternalSkills.js +9 -4
- package/dist/skills/ExternalSkills.js.map +1 -1
- package/dist/skills/SkillDiscovery.js +5 -3
- package/dist/skills/SkillDiscovery.js.map +1 -1
- package/dist/skills/SkillDoctor.js +178 -1
- package/dist/skills/SkillDoctor.js.map +1 -1
- package/dist/skills/SkillInstaller.js +5 -0
- package/dist/skills/SkillInstaller.js.map +1 -1
- package/dist/skills/routing/SkillPlanner.js +40 -40
- package/dist/skills/routing/SkillPolicy.js +168 -5
- package/dist/skills/routing/SkillPolicy.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.js +15 -0
- package/dist/version.js.map +1 -0
- package/dist/workflow/EngineeringStandards.d.ts +143 -0
- package/dist/workflow/EngineeringStandards.js +679 -0
- package/dist/workflow/EngineeringStandards.js.map +1 -0
- package/dist/workflow/GovernanceTemplatePacks.d.ts +1 -1
- package/dist/workflow/GovernanceTemplatePacks.js +136 -10
- package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
- package/dist/workflow/GovernanceTemplates.d.ts +1 -1
- package/dist/workflow/GovernanceTemplates.js +606 -429
- package/dist/workflow/GovernanceTemplates.js.map +1 -1
- package/dist/workflow/ResourceGovernance.d.ts +120 -0
- package/dist/workflow/ResourceGovernance.js +512 -0
- package/dist/workflow/ResourceGovernance.js.map +1 -0
- package/dist/workflow/TaskArtifactScaffolder.js +13 -10
- package/dist/workflow/TaskArtifactScaffolder.js.map +1 -1
- package/dist/workflow/VerificationProfile.d.ts +2 -0
- package/dist/workflow/VerificationProfile.js +7 -0
- package/dist/workflow/VerificationProfile.js.map +1 -1
- package/dist/workflow/WorkspaceLifecycle.d.ts +2 -0
- package/dist/workflow/WorkspaceLifecycle.js +34 -8
- package/dist/workflow/WorkspaceLifecycle.js.map +1 -1
- package/dist/workflow/WorkspaceTopology.d.ts +49 -0
- package/dist/workflow/WorkspaceTopology.js +125 -0
- package/dist/workflow/WorkspaceTopology.js.map +1 -0
- package/dist/workflow/index.d.ts +3 -0
- package/dist/workflow/index.js +3 -0
- package/dist/workflow/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GovernanceTemplates.js","sourceRoot":"","sources":["../../src/workflow/GovernanceTemplates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAA;AAC7E,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EACL,6BAA6B,GAG9B,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"GovernanceTemplates.js","sourceRoot":"","sources":["../../src/workflow/GovernanceTemplates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export type ResourceAssetType = 'canonical-doc' | 'task-artifact' | 'evidence-report' | 'temporary' | 'reusable-script' | 'generated-media' | 'contract' | 'decision-record' | 'unknown';
|
|
2
|
+
export type ResourceLifecycle = 'maintained' | 'immutable' | 'task-scoped' | 'temporary' | 'generated' | 'review-required';
|
|
3
|
+
export type ResourceGitPolicy = 'commit' | 'ignore' | 'lfs' | 'external' | 'review';
|
|
4
|
+
export type ResourceFindingSeverity = 'info' | 'warn' | 'fail';
|
|
5
|
+
export interface ResourceAsset {
|
|
6
|
+
path: string;
|
|
7
|
+
type: ResourceAssetType;
|
|
8
|
+
lifecycle: ResourceLifecycle;
|
|
9
|
+
gitPolicy: ResourceGitPolicy;
|
|
10
|
+
reason: string;
|
|
11
|
+
sizeBytes: number;
|
|
12
|
+
modifiedAt: string;
|
|
13
|
+
tracked: boolean;
|
|
14
|
+
retentionDays?: number;
|
|
15
|
+
expiresAt?: string;
|
|
16
|
+
owner?: string;
|
|
17
|
+
module?: string;
|
|
18
|
+
sourceOfTruth?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface ResourceManifestAsset {
|
|
21
|
+
path: string;
|
|
22
|
+
type?: ResourceAssetType;
|
|
23
|
+
lifecycle?: ResourceLifecycle;
|
|
24
|
+
gitPolicy?: ResourceGitPolicy;
|
|
25
|
+
owner?: string;
|
|
26
|
+
module?: string;
|
|
27
|
+
sourceOfTruth?: boolean;
|
|
28
|
+
retentionDays?: number;
|
|
29
|
+
lastReviewedAt?: string;
|
|
30
|
+
reviewIntervalDays?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface ResourceManifestFile {
|
|
33
|
+
version?: number;
|
|
34
|
+
assets?: ResourceManifestAsset[];
|
|
35
|
+
}
|
|
36
|
+
export interface ResourcePolicyFile {
|
|
37
|
+
version?: number;
|
|
38
|
+
maxGitFileSizeBytes?: number;
|
|
39
|
+
ignoredDirectories?: string[];
|
|
40
|
+
retainedRuntimeDirectories?: string[];
|
|
41
|
+
owners?: Record<string, string>;
|
|
42
|
+
modules?: Record<string, {
|
|
43
|
+
path: string;
|
|
44
|
+
owner?: string;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
export interface ResolvedResourcePolicy {
|
|
48
|
+
version: number;
|
|
49
|
+
maxGitFileSizeBytes: number;
|
|
50
|
+
ignoredDirectories: string[];
|
|
51
|
+
retainedRuntimeDirectories: string[];
|
|
52
|
+
owners: Record<string, string>;
|
|
53
|
+
modules: Record<string, {
|
|
54
|
+
path: string;
|
|
55
|
+
owner?: string;
|
|
56
|
+
}>;
|
|
57
|
+
warnings: string[];
|
|
58
|
+
}
|
|
59
|
+
export interface ResolvedResourceManifest {
|
|
60
|
+
version: number;
|
|
61
|
+
assets: ResourceManifestAsset[];
|
|
62
|
+
warnings: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface ResourceScanOptions {
|
|
65
|
+
projectDir?: string;
|
|
66
|
+
scaleDir?: string;
|
|
67
|
+
includeIgnored?: boolean;
|
|
68
|
+
trackedPaths?: string[];
|
|
69
|
+
now?: Date;
|
|
70
|
+
}
|
|
71
|
+
export interface ResourceScanSummary {
|
|
72
|
+
total: number;
|
|
73
|
+
byType: Record<ResourceAssetType, number>;
|
|
74
|
+
byGitPolicy: Record<ResourceGitPolicy, number>;
|
|
75
|
+
trackedForbidden: number;
|
|
76
|
+
expired: number;
|
|
77
|
+
largeTracked: number;
|
|
78
|
+
}
|
|
79
|
+
export interface ResourceScanReport {
|
|
80
|
+
projectDir: string;
|
|
81
|
+
policyPath: string;
|
|
82
|
+
manifestPath: string;
|
|
83
|
+
policy: ResolvedResourcePolicy;
|
|
84
|
+
manifest: ResolvedResourceManifest;
|
|
85
|
+
assets: ResourceAsset[];
|
|
86
|
+
summary: ResourceScanSummary;
|
|
87
|
+
warnings: string[];
|
|
88
|
+
}
|
|
89
|
+
export interface ResourceFinding {
|
|
90
|
+
severity: ResourceFindingSeverity;
|
|
91
|
+
code: string;
|
|
92
|
+
path?: string;
|
|
93
|
+
message: string;
|
|
94
|
+
fix?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface ResourceDoctorReport {
|
|
97
|
+
ok: boolean;
|
|
98
|
+
projectDir: string;
|
|
99
|
+
findings: ResourceFinding[];
|
|
100
|
+
scan: ResourceScanReport;
|
|
101
|
+
}
|
|
102
|
+
export interface ResourceSettleOptions extends ResourceScanOptions {
|
|
103
|
+
taskId?: string;
|
|
104
|
+
artifactsDir?: string;
|
|
105
|
+
}
|
|
106
|
+
export interface ResourceSettleReport {
|
|
107
|
+
ok: boolean;
|
|
108
|
+
taskId?: string;
|
|
109
|
+
resourceImpactPath?: string;
|
|
110
|
+
doctor: ResourceDoctorReport;
|
|
111
|
+
}
|
|
112
|
+
export declare function resourcePolicyPath(projectDir?: string, scaleDir?: string): string;
|
|
113
|
+
export declare function resourceManifestPath(projectDir?: string, scaleDir?: string): string;
|
|
114
|
+
export declare function resourcePolicyTemplate(): string;
|
|
115
|
+
export declare function resourceManifestTemplate(): string;
|
|
116
|
+
export declare function loadResourcePolicy(projectDir?: string, scaleDir?: string): ResolvedResourcePolicy;
|
|
117
|
+
export declare function loadResourceManifest(projectDir?: string, scaleDir?: string): ResolvedResourceManifest;
|
|
118
|
+
export declare function scanResourceAssets(options?: ResourceScanOptions): ResourceScanReport;
|
|
119
|
+
export declare function doctorResourceAssets(options?: ResourceScanOptions): ResourceDoctorReport;
|
|
120
|
+
export declare function settleResourceAssets(options?: ResourceSettleOptions): ResourceSettleReport;
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { extname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
const DEFAULT_IGNORED_DIRECTORIES = [
|
|
5
|
+
'.git',
|
|
6
|
+
'node_modules',
|
|
7
|
+
'dist',
|
|
8
|
+
'build',
|
|
9
|
+
'vendor',
|
|
10
|
+
'.next',
|
|
11
|
+
'.turbo',
|
|
12
|
+
];
|
|
13
|
+
const DEFAULT_RUNTIME_DIRECTORIES = [
|
|
14
|
+
'.scale/tmp',
|
|
15
|
+
'.scale/evidence',
|
|
16
|
+
'.scale/reports',
|
|
17
|
+
'.scale/resource-reports',
|
|
18
|
+
'tmp',
|
|
19
|
+
'temp',
|
|
20
|
+
'test-results',
|
|
21
|
+
'playwright-report',
|
|
22
|
+
'coverage',
|
|
23
|
+
];
|
|
24
|
+
const DEFAULT_OWNERS = {
|
|
25
|
+
docs: 'engineering',
|
|
26
|
+
'docs/standards': 'engineering',
|
|
27
|
+
'docs/workflow': 'engineering',
|
|
28
|
+
'docs/decisions': 'architecture',
|
|
29
|
+
'docs/modules': 'module-owner',
|
|
30
|
+
'.scale': 'engineering',
|
|
31
|
+
};
|
|
32
|
+
const MEDIA_EXTENSIONS = new Set([
|
|
33
|
+
'.png',
|
|
34
|
+
'.jpg',
|
|
35
|
+
'.jpeg',
|
|
36
|
+
'.gif',
|
|
37
|
+
'.webp',
|
|
38
|
+
'.svg',
|
|
39
|
+
'.mp4',
|
|
40
|
+
'.webm',
|
|
41
|
+
'.mov',
|
|
42
|
+
'.mp3',
|
|
43
|
+
'.wav',
|
|
44
|
+
'.m4a',
|
|
45
|
+
]);
|
|
46
|
+
const SCRIPT_EXTENSIONS = new Set(['.sh', '.ps1', '.cmd', '.bat', '.js', '.mjs', '.cjs', '.ts', '.py']);
|
|
47
|
+
const CONTRACT_EXTENSIONS = new Set(['.openapi.yaml', '.openapi.yml', '.proto']);
|
|
48
|
+
const RESOURCE_ASSET_TYPES = [
|
|
49
|
+
'canonical-doc',
|
|
50
|
+
'task-artifact',
|
|
51
|
+
'evidence-report',
|
|
52
|
+
'temporary',
|
|
53
|
+
'reusable-script',
|
|
54
|
+
'generated-media',
|
|
55
|
+
'contract',
|
|
56
|
+
'decision-record',
|
|
57
|
+
'unknown',
|
|
58
|
+
];
|
|
59
|
+
const RESOURCE_LIFECYCLES = [
|
|
60
|
+
'maintained',
|
|
61
|
+
'immutable',
|
|
62
|
+
'task-scoped',
|
|
63
|
+
'temporary',
|
|
64
|
+
'generated',
|
|
65
|
+
'review-required',
|
|
66
|
+
];
|
|
67
|
+
const RESOURCE_GIT_POLICIES = ['commit', 'ignore', 'lfs', 'external', 'review'];
|
|
68
|
+
export function resourcePolicyPath(projectDir = process.cwd(), scaleDir = '.scale') {
|
|
69
|
+
return join(projectDir, scaleDir, 'resource-policy.json');
|
|
70
|
+
}
|
|
71
|
+
export function resourceManifestPath(projectDir = process.cwd(), scaleDir = '.scale') {
|
|
72
|
+
return join(projectDir, scaleDir, 'assets.json');
|
|
73
|
+
}
|
|
74
|
+
export function resourcePolicyTemplate() {
|
|
75
|
+
return JSON.stringify({
|
|
76
|
+
version: 1,
|
|
77
|
+
maxGitFileSizeBytes: 5 * 1024 * 1024,
|
|
78
|
+
ignoredDirectories: DEFAULT_IGNORED_DIRECTORIES,
|
|
79
|
+
retainedRuntimeDirectories: DEFAULT_RUNTIME_DIRECTORIES,
|
|
80
|
+
owners: DEFAULT_OWNERS,
|
|
81
|
+
modules: {
|
|
82
|
+
example: {
|
|
83
|
+
path: 'src/example',
|
|
84
|
+
owner: 'team-or-owner',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
}, null, 2) + '\n';
|
|
88
|
+
}
|
|
89
|
+
export function resourceManifestTemplate() {
|
|
90
|
+
return JSON.stringify({
|
|
91
|
+
version: 1,
|
|
92
|
+
assets: [],
|
|
93
|
+
}, null, 2) + '\n';
|
|
94
|
+
}
|
|
95
|
+
export function loadResourcePolicy(projectDir = process.cwd(), scaleDir = '.scale') {
|
|
96
|
+
const path = resourcePolicyPath(projectDir, scaleDir);
|
|
97
|
+
const warnings = [];
|
|
98
|
+
let parsed = {};
|
|
99
|
+
if (existsSync(path)) {
|
|
100
|
+
try {
|
|
101
|
+
parsed = JSON.parse(readFileSync(path, 'utf-8'));
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
warnings.push(`Failed to read ${path}: ${error.message}; using built-in defaults.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
version: typeof parsed.version === 'number' ? parsed.version : 1,
|
|
109
|
+
maxGitFileSizeBytes: parsed.maxGitFileSizeBytes ?? 5 * 1024 * 1024,
|
|
110
|
+
ignoredDirectories: parsed.ignoredDirectories ?? DEFAULT_IGNORED_DIRECTORIES,
|
|
111
|
+
retainedRuntimeDirectories: parsed.retainedRuntimeDirectories ?? DEFAULT_RUNTIME_DIRECTORIES,
|
|
112
|
+
owners: { ...DEFAULT_OWNERS, ...(parsed.owners ?? {}) },
|
|
113
|
+
modules: parsed.modules ?? {},
|
|
114
|
+
warnings,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function loadResourceManifest(projectDir = process.cwd(), scaleDir = '.scale') {
|
|
118
|
+
const path = resourceManifestPath(projectDir, scaleDir);
|
|
119
|
+
const warnings = [];
|
|
120
|
+
let parsed = {};
|
|
121
|
+
if (existsSync(path)) {
|
|
122
|
+
try {
|
|
123
|
+
parsed = JSON.parse(readFileSync(path, 'utf-8'));
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
warnings.push(`Failed to read ${path}: ${error.message}; using empty asset manifest.`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
version: typeof parsed.version === 'number' ? parsed.version : 1,
|
|
131
|
+
assets: Array.isArray(parsed.assets)
|
|
132
|
+
? parsed.assets
|
|
133
|
+
.filter(item => item && typeof item === 'object' && typeof item.path === 'string' && item.path.length > 0)
|
|
134
|
+
.map(item => ({
|
|
135
|
+
path: normalizePath(item.path),
|
|
136
|
+
type: isResourceAssetType(item.type) ? item.type : undefined,
|
|
137
|
+
lifecycle: isResourceLifecycle(item.lifecycle) ? item.lifecycle : undefined,
|
|
138
|
+
gitPolicy: isResourceGitPolicy(item.gitPolicy) ? item.gitPolicy : undefined,
|
|
139
|
+
owner: typeof item.owner === 'string' ? item.owner : undefined,
|
|
140
|
+
module: typeof item.module === 'string' ? item.module : undefined,
|
|
141
|
+
sourceOfTruth: typeof item.sourceOfTruth === 'boolean' ? item.sourceOfTruth : undefined,
|
|
142
|
+
retentionDays: typeof item.retentionDays === 'number' ? item.retentionDays : undefined,
|
|
143
|
+
lastReviewedAt: typeof item.lastReviewedAt === 'string' ? item.lastReviewedAt : undefined,
|
|
144
|
+
reviewIntervalDays: typeof item.reviewIntervalDays === 'number' ? item.reviewIntervalDays : undefined,
|
|
145
|
+
}))
|
|
146
|
+
: [],
|
|
147
|
+
warnings,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function scanResourceAssets(options = {}) {
|
|
151
|
+
const projectDir = options.projectDir ?? process.cwd();
|
|
152
|
+
const scaleDir = options.scaleDir ?? '.scale';
|
|
153
|
+
const policy = loadResourcePolicy(projectDir, scaleDir);
|
|
154
|
+
const manifest = loadResourceManifest(projectDir, scaleDir);
|
|
155
|
+
const manifestAssets = new Map(manifest.assets.map(asset => [normalizePath(asset.path), asset]));
|
|
156
|
+
const tracked = new Set(options.trackedPaths ?? readTrackedPaths(projectDir));
|
|
157
|
+
const files = walkFiles(projectDir, policy.ignoredDirectories);
|
|
158
|
+
const now = options.now ?? new Date();
|
|
159
|
+
const assets = files
|
|
160
|
+
.map(file => classifyFile(projectDir, file, policy, manifestAssets, tracked, now))
|
|
161
|
+
.filter((asset) => Boolean(asset));
|
|
162
|
+
return {
|
|
163
|
+
projectDir,
|
|
164
|
+
policyPath: resourcePolicyPath(projectDir, scaleDir),
|
|
165
|
+
manifestPath: resourceManifestPath(projectDir, scaleDir),
|
|
166
|
+
policy,
|
|
167
|
+
manifest,
|
|
168
|
+
assets,
|
|
169
|
+
summary: summarizeAssets(assets, policy, now),
|
|
170
|
+
warnings: [...policy.warnings, ...manifest.warnings],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export function doctorResourceAssets(options = {}) {
|
|
174
|
+
const scan = scanResourceAssets(options);
|
|
175
|
+
const now = options.now ?? new Date();
|
|
176
|
+
const findings = [];
|
|
177
|
+
for (const warning of scan.policy.warnings) {
|
|
178
|
+
findings.push({ severity: 'warn', code: 'policy-read-warning', message: warning });
|
|
179
|
+
}
|
|
180
|
+
for (const warning of scan.manifest.warnings) {
|
|
181
|
+
findings.push({ severity: 'warn', code: 'manifest-read-warning', message: warning });
|
|
182
|
+
}
|
|
183
|
+
for (const asset of scan.manifest.assets) {
|
|
184
|
+
const exists = existsSync(join(scan.projectDir, ...normalizePath(asset.path).split('/')));
|
|
185
|
+
if (!exists && asset.sourceOfTruth) {
|
|
186
|
+
findings.push({
|
|
187
|
+
severity: 'fail',
|
|
188
|
+
code: 'missing-source-of-truth',
|
|
189
|
+
path: asset.path,
|
|
190
|
+
message: 'Declared source-of-truth asset is missing from the workspace.',
|
|
191
|
+
fix: 'Restore the maintained asset, update .scale/assets.json, or promote the replacement source of truth.',
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else if (!exists) {
|
|
195
|
+
findings.push({
|
|
196
|
+
severity: 'warn',
|
|
197
|
+
code: 'missing-declared-resource',
|
|
198
|
+
path: asset.path,
|
|
199
|
+
message: 'Declared resource is missing from the workspace.',
|
|
200
|
+
fix: 'Restore the file, update .scale/assets.json, or remove the stale catalog entry.',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (exists &&
|
|
204
|
+
(asset.sourceOfTruth || asset.lifecycle === 'maintained') &&
|
|
205
|
+
asset.lastReviewedAt &&
|
|
206
|
+
asset.reviewIntervalDays &&
|
|
207
|
+
isStaleReview(asset.lastReviewedAt, asset.reviewIntervalDays, now)) {
|
|
208
|
+
findings.push({
|
|
209
|
+
severity: 'warn',
|
|
210
|
+
code: 'stale-maintained-resource',
|
|
211
|
+
path: asset.path,
|
|
212
|
+
message: `Maintained resource was last reviewed at ${asset.lastReviewedAt}; review interval is ${asset.reviewIntervalDays} days.`,
|
|
213
|
+
fix: 'Review the asset against current code and requirements, then update lastReviewedAt.',
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
for (const asset of scan.assets) {
|
|
218
|
+
if (asset.tracked && (asset.gitPolicy === 'ignore' || asset.gitPolicy === 'external')) {
|
|
219
|
+
findings.push({
|
|
220
|
+
severity: 'fail',
|
|
221
|
+
code: 'forbidden-tracked-resource',
|
|
222
|
+
path: asset.path,
|
|
223
|
+
message: `${asset.type} should not be tracked in Git (${asset.gitPolicy}).`,
|
|
224
|
+
fix: 'Move it to runtime artifact storage, delete it from Git, or promote it to a maintained asset with an explicit policy.',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (asset.tracked && asset.sizeBytes > scan.policy.maxGitFileSizeBytes && asset.gitPolicy !== 'lfs') {
|
|
228
|
+
findings.push({
|
|
229
|
+
severity: 'warn',
|
|
230
|
+
code: 'large-tracked-resource',
|
|
231
|
+
path: asset.path,
|
|
232
|
+
message: `Tracked file is ${asset.sizeBytes} bytes, above ${scan.policy.maxGitFileSizeBytes}.`,
|
|
233
|
+
fix: 'Use Git LFS, external artifact storage, or keep only a lightweight source representation.',
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
if (asset.expiresAt && new Date(asset.expiresAt).getTime() < now.getTime()) {
|
|
237
|
+
findings.push({
|
|
238
|
+
severity: 'warn',
|
|
239
|
+
code: 'expired-resource',
|
|
240
|
+
path: asset.path,
|
|
241
|
+
message: `${asset.type} expired at ${asset.expiresAt}.`,
|
|
242
|
+
fix: 'Delete it, archive it outside Git, or promote the final result into canonical documentation.',
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
if (asset.type === 'canonical-doc' && !asset.owner) {
|
|
246
|
+
findings.push({
|
|
247
|
+
severity: 'warn',
|
|
248
|
+
code: 'missing-owner',
|
|
249
|
+
path: asset.path,
|
|
250
|
+
message: 'Canonical documentation has no owner in resource policy.',
|
|
251
|
+
fix: 'Add an owner under .scale/resource-policy.json owners or modules.',
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
ok: !findings.some(finding => finding.severity === 'fail'),
|
|
257
|
+
projectDir: scan.projectDir,
|
|
258
|
+
findings,
|
|
259
|
+
scan,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
export function settleResourceAssets(options = {}) {
|
|
263
|
+
const doctor = doctorResourceAssets(options);
|
|
264
|
+
const resourceImpactPath = options.artifactsDir
|
|
265
|
+
? appendResourceImpact({
|
|
266
|
+
projectDir: options.projectDir ?? process.cwd(),
|
|
267
|
+
artifactsDir: options.artifactsDir,
|
|
268
|
+
taskId: options.taskId,
|
|
269
|
+
doctor,
|
|
270
|
+
})
|
|
271
|
+
: undefined;
|
|
272
|
+
return {
|
|
273
|
+
ok: doctor.ok,
|
|
274
|
+
taskId: options.taskId,
|
|
275
|
+
resourceImpactPath,
|
|
276
|
+
doctor,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function classifyFile(projectDir, absolutePath, policy, manifestAssets, tracked, now) {
|
|
280
|
+
const path = normalizePath(relative(projectDir, absolutePath));
|
|
281
|
+
if (!path || path.startsWith('..'))
|
|
282
|
+
return null;
|
|
283
|
+
const stat = statSync(absolutePath);
|
|
284
|
+
const classification = classifyPath(path, policy);
|
|
285
|
+
if (!classification)
|
|
286
|
+
return null;
|
|
287
|
+
const selected = classification;
|
|
288
|
+
const manifestAsset = manifestAssets.get(path);
|
|
289
|
+
const retentionDays = manifestAsset?.retentionDays ?? selected.retentionDays;
|
|
290
|
+
const expiresAt = retentionDays
|
|
291
|
+
? new Date(stat.mtime.getTime() + retentionDays * 24 * 60 * 60 * 1000).toISOString()
|
|
292
|
+
: undefined;
|
|
293
|
+
return {
|
|
294
|
+
path,
|
|
295
|
+
type: manifestAsset?.type ?? selected.type,
|
|
296
|
+
lifecycle: manifestAsset?.lifecycle ?? selected.lifecycle,
|
|
297
|
+
gitPolicy: manifestAsset?.gitPolicy ?? selected.gitPolicy,
|
|
298
|
+
reason: selected.reason,
|
|
299
|
+
sizeBytes: stat.size,
|
|
300
|
+
modifiedAt: stat.mtime.toISOString(),
|
|
301
|
+
tracked: tracked.has(path),
|
|
302
|
+
retentionDays,
|
|
303
|
+
expiresAt,
|
|
304
|
+
owner: manifestAsset?.owner ?? ownerForPath(path, policy),
|
|
305
|
+
module: manifestAsset?.module ?? moduleForPath(path, policy),
|
|
306
|
+
sourceOfTruth: manifestAsset?.sourceOfTruth ?? selected.sourceOfTruth,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function appendResourceImpact(options) {
|
|
310
|
+
const dir = isAbsolute(options.artifactsDir)
|
|
311
|
+
? options.artifactsDir
|
|
312
|
+
: resolve(options.projectDir, options.artifactsDir);
|
|
313
|
+
if (!existsSync(dir))
|
|
314
|
+
mkdirSync(dir, { recursive: true });
|
|
315
|
+
const path = join(dir, 'resource-impact.md');
|
|
316
|
+
if (!existsSync(path)) {
|
|
317
|
+
writeFileSync(path, '# Resource Impact\n\n', 'utf-8');
|
|
318
|
+
}
|
|
319
|
+
appendFileSync(path, resourceSettlementMarkdown(options), 'utf-8');
|
|
320
|
+
return path;
|
|
321
|
+
}
|
|
322
|
+
function resourceSettlementMarkdown(options) {
|
|
323
|
+
const findings = options.doctor.findings.length
|
|
324
|
+
? options.doctor.findings.map(finding => `| ${finding.severity.toUpperCase()} | ${finding.code} | ${escapeCell(finding.path ?? '')} | ${escapeCell(finding.message)} |`).join('\n')
|
|
325
|
+
: '| OK | no-findings | | No resource lifecycle findings. |';
|
|
326
|
+
const summary = options.doctor.scan.summary;
|
|
327
|
+
return `
|
|
328
|
+
## SCALE Resource Settlement - ${new Date().toISOString()}
|
|
329
|
+
|
|
330
|
+
Task: ${options.taskId ?? 'unspecified'}
|
|
331
|
+
Status: ${options.doctor.ok ? 'passed' : 'blocked'}
|
|
332
|
+
|
|
333
|
+
| Metric | Value |
|
|
334
|
+
| --- | ---: |
|
|
335
|
+
| Total resources | ${summary.total} |
|
|
336
|
+
| Tracked forbidden | ${summary.trackedForbidden} |
|
|
337
|
+
| Large tracked | ${summary.largeTracked} |
|
|
338
|
+
| Expired | ${summary.expired} |
|
|
339
|
+
|
|
340
|
+
| Severity | Code | Path | Message |
|
|
341
|
+
| --- | --- | --- | --- |
|
|
342
|
+
${findings}
|
|
343
|
+
`;
|
|
344
|
+
}
|
|
345
|
+
function classifyPath(path, policy) {
|
|
346
|
+
if (path === resourcePolicyPath('', '').replace(/^[\\/]/, '') || path === '.scale/resource-policy.json' || path === '.scale/assets.json') {
|
|
347
|
+
return { type: 'canonical-doc', lifecycle: 'maintained', gitPolicy: 'commit', reason: 'resource governance source of truth', sourceOfTruth: true };
|
|
348
|
+
}
|
|
349
|
+
if (path.startsWith('docs/decisions/') || /(^|\/)ADR-\d+/i.test(path)) {
|
|
350
|
+
return { type: 'decision-record', lifecycle: 'immutable', gitPolicy: 'commit', reason: 'architecture decision record', sourceOfTruth: true };
|
|
351
|
+
}
|
|
352
|
+
if (path.startsWith('docs/worklog/tasks/') && path.endsWith('.md')) {
|
|
353
|
+
return { type: 'task-artifact', lifecycle: 'task-scoped', gitPolicy: 'review', reason: 'task evidence artifact', retentionDays: 180 };
|
|
354
|
+
}
|
|
355
|
+
if (path.startsWith('docs/modules/') || path.startsWith('docs/standards/') || path.startsWith('docs/architecture/') || path.startsWith('docs/workflow/') || /^docs\/[^/]+\.md$/i.test(path) || path === 'README.md' || path === 'CHANGELOG.md') {
|
|
356
|
+
return { type: 'canonical-doc', lifecycle: 'maintained', gitPolicy: 'commit', reason: 'maintained project documentation', sourceOfTruth: true };
|
|
357
|
+
}
|
|
358
|
+
if (path.startsWith('scripts/tmp/') || path.startsWith('tmp/') || path.startsWith('temp/') || path.startsWith('.scale/tmp/')) {
|
|
359
|
+
return { type: 'temporary', lifecycle: 'temporary', gitPolicy: 'ignore', reason: 'temporary workspace output', retentionDays: 7 };
|
|
360
|
+
}
|
|
361
|
+
if (isRuntimePath(path, policy)) {
|
|
362
|
+
const media = MEDIA_EXTENSIONS.has(extname(path).toLowerCase());
|
|
363
|
+
return { type: media ? 'generated-media' : 'evidence-report', lifecycle: 'generated', gitPolicy: 'ignore', reason: 'runtime evidence or generated report', retentionDays: 30 };
|
|
364
|
+
}
|
|
365
|
+
if (path.startsWith('scripts/') && SCRIPT_EXTENSIONS.has(extname(path).toLowerCase())) {
|
|
366
|
+
return { type: 'reusable-script', lifecycle: 'maintained', gitPolicy: 'commit', reason: 'reusable automation script', sourceOfTruth: true };
|
|
367
|
+
}
|
|
368
|
+
if (isContractPath(path)) {
|
|
369
|
+
return { type: 'contract', lifecycle: 'maintained', gitPolicy: 'commit', reason: 'machine-readable interface contract', sourceOfTruth: true };
|
|
370
|
+
}
|
|
371
|
+
if (MEDIA_EXTENSIONS.has(extname(path).toLowerCase())) {
|
|
372
|
+
const largeMedia = /\.(mp4|webm|mov|mp3|wav|m4a)$/i.test(path);
|
|
373
|
+
return {
|
|
374
|
+
type: 'generated-media',
|
|
375
|
+
lifecycle: largeMedia ? 'review-required' : 'generated',
|
|
376
|
+
gitPolicy: largeMedia ? 'external' : 'review',
|
|
377
|
+
reason: largeMedia ? 'large media should live outside normal Git history' : 'media requires explicit documentation purpose',
|
|
378
|
+
retentionDays: largeMedia ? 30 : undefined,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
function summarizeAssets(assets, policy, now) {
|
|
384
|
+
const byType = emptyTypeSummary();
|
|
385
|
+
const byGitPolicy = emptyGitPolicySummary();
|
|
386
|
+
for (const asset of assets) {
|
|
387
|
+
byType[asset.type] += 1;
|
|
388
|
+
byGitPolicy[asset.gitPolicy] += 1;
|
|
389
|
+
}
|
|
390
|
+
return {
|
|
391
|
+
total: assets.length,
|
|
392
|
+
byType,
|
|
393
|
+
byGitPolicy,
|
|
394
|
+
trackedForbidden: assets.filter(asset => asset.tracked && (asset.gitPolicy === 'ignore' || asset.gitPolicy === 'external')).length,
|
|
395
|
+
expired: assets.filter(asset => asset.expiresAt && new Date(asset.expiresAt).getTime() < now.getTime()).length,
|
|
396
|
+
largeTracked: assets.filter(asset => asset.tracked && asset.sizeBytes > policy.maxGitFileSizeBytes && asset.gitPolicy !== 'lfs').length,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function walkFiles(projectDir, ignoredDirectories) {
|
|
400
|
+
if (!existsSync(projectDir))
|
|
401
|
+
return [];
|
|
402
|
+
const ignored = new Set(ignoredDirectories.map(normalizePath));
|
|
403
|
+
const files = [];
|
|
404
|
+
const visit = (dir) => {
|
|
405
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
406
|
+
const fullPath = join(dir, entry.name);
|
|
407
|
+
const rel = normalizePath(relative(projectDir, fullPath));
|
|
408
|
+
if (entry.isDirectory()) {
|
|
409
|
+
if (ignored.has(rel) || ignored.has(entry.name))
|
|
410
|
+
continue;
|
|
411
|
+
visit(fullPath);
|
|
412
|
+
}
|
|
413
|
+
else if (entry.isFile()) {
|
|
414
|
+
files.push(fullPath);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
visit(projectDir);
|
|
419
|
+
return files;
|
|
420
|
+
}
|
|
421
|
+
function readTrackedPaths(projectDir) {
|
|
422
|
+
try {
|
|
423
|
+
return execFileSync('git', ['ls-files'], { cwd: projectDir, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] })
|
|
424
|
+
.split(/\r?\n/)
|
|
425
|
+
.map(line => normalizePath(line.trim()))
|
|
426
|
+
.filter(Boolean);
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
return [];
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function ownerForPath(path, policy) {
|
|
433
|
+
if (path === '.scale/resource-policy.json' || path === '.scale/assets.json')
|
|
434
|
+
return 'engineering';
|
|
435
|
+
if (path === 'README.md' || path === 'CHANGELOG.md')
|
|
436
|
+
return 'engineering';
|
|
437
|
+
const ownerMatch = Object.entries(policy.owners)
|
|
438
|
+
.sort((a, b) => b[0].length - a[0].length)
|
|
439
|
+
.find(([prefix]) => path === prefix || path.startsWith(`${normalizePath(prefix)}/`));
|
|
440
|
+
if (ownerMatch)
|
|
441
|
+
return ownerMatch[1];
|
|
442
|
+
const moduleName = moduleForPath(path, policy);
|
|
443
|
+
return moduleName ? policy.modules[moduleName]?.owner : undefined;
|
|
444
|
+
}
|
|
445
|
+
function moduleForPath(path, policy) {
|
|
446
|
+
for (const [name, module] of Object.entries(policy.modules)) {
|
|
447
|
+
const modulePath = normalizePath(module.path);
|
|
448
|
+
if (path === modulePath || path.startsWith(`${modulePath}/`))
|
|
449
|
+
return name;
|
|
450
|
+
if (path.startsWith(`docs/modules/${name}/`))
|
|
451
|
+
return name;
|
|
452
|
+
}
|
|
453
|
+
const match = path.match(/^docs\/modules\/([^/]+)\//);
|
|
454
|
+
return match?.[1];
|
|
455
|
+
}
|
|
456
|
+
function isRuntimePath(path, policy) {
|
|
457
|
+
return policy.retainedRuntimeDirectories
|
|
458
|
+
.map(normalizePath)
|
|
459
|
+
.some(prefix => path === prefix || path.startsWith(`${prefix}/`));
|
|
460
|
+
}
|
|
461
|
+
function isContractPath(path) {
|
|
462
|
+
const lower = path.toLowerCase();
|
|
463
|
+
if (lower.startsWith('openapi/') || lower.startsWith('contracts/') || lower.startsWith('proto/'))
|
|
464
|
+
return true;
|
|
465
|
+
if (lower.endsWith('.proto'))
|
|
466
|
+
return true;
|
|
467
|
+
return [...CONTRACT_EXTENSIONS].some(suffix => lower.endsWith(suffix));
|
|
468
|
+
}
|
|
469
|
+
function isStaleReview(lastReviewedAt, reviewIntervalDays, now) {
|
|
470
|
+
const reviewedAt = new Date(`${lastReviewedAt}T00:00:00Z`);
|
|
471
|
+
if (Number.isNaN(reviewedAt.getTime()) || reviewIntervalDays <= 0)
|
|
472
|
+
return false;
|
|
473
|
+
return now.getTime() - reviewedAt.getTime() > reviewIntervalDays * 24 * 60 * 60 * 1000;
|
|
474
|
+
}
|
|
475
|
+
function isResourceAssetType(value) {
|
|
476
|
+
return typeof value === 'string' && RESOURCE_ASSET_TYPES.includes(value);
|
|
477
|
+
}
|
|
478
|
+
function isResourceLifecycle(value) {
|
|
479
|
+
return typeof value === 'string' && RESOURCE_LIFECYCLES.includes(value);
|
|
480
|
+
}
|
|
481
|
+
function isResourceGitPolicy(value) {
|
|
482
|
+
return typeof value === 'string' && RESOURCE_GIT_POLICIES.includes(value);
|
|
483
|
+
}
|
|
484
|
+
function emptyTypeSummary() {
|
|
485
|
+
return {
|
|
486
|
+
'canonical-doc': 0,
|
|
487
|
+
'task-artifact': 0,
|
|
488
|
+
'evidence-report': 0,
|
|
489
|
+
temporary: 0,
|
|
490
|
+
'reusable-script': 0,
|
|
491
|
+
'generated-media': 0,
|
|
492
|
+
contract: 0,
|
|
493
|
+
'decision-record': 0,
|
|
494
|
+
unknown: 0,
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function emptyGitPolicySummary() {
|
|
498
|
+
return {
|
|
499
|
+
commit: 0,
|
|
500
|
+
ignore: 0,
|
|
501
|
+
lfs: 0,
|
|
502
|
+
external: 0,
|
|
503
|
+
review: 0,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function normalizePath(path) {
|
|
507
|
+
return path.split(sep).join('/').replace(/^\.\//, '');
|
|
508
|
+
}
|
|
509
|
+
function escapeCell(value) {
|
|
510
|
+
return value.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
|
|
511
|
+
}
|
|
512
|
+
//# sourceMappingURL=ResourceGovernance.js.map
|