scene-capability-engine 3.0.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/CHANGELOG.md +2513 -0
- package/LICENSE +21 -0
- package/README.md +765 -0
- package/README.zh.md +630 -0
- package/bin/kiro-spec-engine.js +796 -0
- package/bin/kse.js +3 -0
- package/bin/sce.js +3 -0
- package/bin/sco.js +3 -0
- package/docs/331-poc-adaptation-roadmap.md +156 -0
- package/docs/331-poc-dual-track-integration-guide.md +120 -0
- package/docs/331-poc-weekly-delivery-checklist.md +52 -0
- package/docs/OFFLINE_INSTALL.md +96 -0
- package/docs/README.md +279 -0
- package/docs/adopt-migration-guide.md +599 -0
- package/docs/adoption-guide.md +616 -0
- package/docs/agent-hooks-analysis.md +815 -0
- package/docs/architecture.md +733 -0
- package/docs/articles/ai-driven-development-philosophy-and-practice-review.md +208 -0
- package/docs/articles/ai-driven-development-philosophy-and-practice.en.md +459 -0
- package/docs/articles/ai-driven-development-philosophy-and-practice.md +492 -0
- package/docs/autonomous-control-guide.md +851 -0
- package/docs/command-reference.md +1368 -0
- package/docs/community.md +115 -0
- package/docs/cross-tool-guide.md +555 -0
- package/docs/developer-guide.md +619 -0
- package/docs/document-governance.md +865 -0
- package/docs/environment-management-guide.md +526 -0
- package/docs/examples/add-export-command/design.md +194 -0
- package/docs/examples/add-export-command/requirements.md +110 -0
- package/docs/examples/add-export-command/tasks.md +88 -0
- package/docs/examples/add-rest-api/design.md +855 -0
- package/docs/examples/add-rest-api/requirements.md +323 -0
- package/docs/examples/add-rest-api/tasks.md +355 -0
- package/docs/examples/add-user-dashboard/design.md +192 -0
- package/docs/examples/add-user-dashboard/requirements.md +143 -0
- package/docs/examples/add-user-dashboard/tasks.md +91 -0
- package/docs/faq.md +697 -0
- package/docs/handoffs/evidence/ontology/moqui-template-baseline-2026-02-17-232922.json +156 -0
- package/docs/handoffs/evidence/ontology/moqui-template-baseline-2026-02-17-232922.md +24 -0
- package/docs/images/wechat-qr.png +0 -0
- package/docs/integration-modes.md +529 -0
- package/docs/integration-philosophy.md +313 -0
- package/docs/knowledge-management-guide.md +263 -0
- package/docs/manual-workflows-guide.md +418 -0
- package/docs/moqui-capability-matrix.md +73 -0
- package/docs/moqui-template-core-library-playbook.md +109 -0
- package/docs/multi-agent-coordination-guide.md +553 -0
- package/docs/multi-repo-management-guide.md +1344 -0
- package/docs/quick-start-with-ai-tools.md +375 -0
- package/docs/quick-start.md +146 -0
- package/docs/release-checklist.md +121 -0
- package/docs/releases/README.md +13 -0
- package/docs/releases/v1.46.2-validation.md +45 -0
- package/docs/releases/v1.46.2.md +50 -0
- package/docs/scene-runtime-guide.md +347 -0
- package/docs/spec-collaboration-guide.md +369 -0
- package/docs/spec-locking-guide.md +225 -0
- package/docs/spec-numbering-guide.md +348 -0
- package/docs/spec-workflow.md +519 -0
- package/docs/steering-strategy-guide.md +196 -0
- package/docs/team-collaboration-guide.md +465 -0
- package/docs/testing-strategy.md +272 -0
- package/docs/tools/claude-guide.md +654 -0
- package/docs/tools/cursor-guide.md +706 -0
- package/docs/tools/generic-guide.md +446 -0
- package/docs/tools/kiro-guide.md +308 -0
- package/docs/tools/vscode-guide.md +445 -0
- package/docs/tools/windsurf-guide.md +391 -0
- package/docs/troubleshooting.md +1135 -0
- package/docs/upgrade-guide.md +639 -0
- package/docs/value-observability-guide.md +127 -0
- package/docs/zh/README.md +341 -0
- package/docs/zh/quick-start.md +764 -0
- package/docs/zh/release-checklist.md +121 -0
- package/docs/zh/releases/README.md +13 -0
- package/docs/zh/releases/v1.46.2-validation.md +45 -0
- package/docs/zh/releases/v1.46.2.md +50 -0
- package/docs/zh/spec-numbering-guide.md +348 -0
- package/docs/zh/tools/claude-guide.md +349 -0
- package/docs/zh/tools/cursor-guide.md +281 -0
- package/docs/zh/tools/generic-guide.md +499 -0
- package/docs/zh/tools/kiro-guide.md +342 -0
- package/docs/zh/tools/vscode-guide.md +449 -0
- package/docs/zh/tools/windsurf-guide.md +378 -0
- package/docs/zh/value-observability-guide.md +127 -0
- package/docs//344/272/244/344/273/230/346/270/205/345/215/225.md +75 -0
- package/lib/adoption/adoption-logger.js +487 -0
- package/lib/adoption/adoption-strategy.js +538 -0
- package/lib/adoption/backup-manager.js +420 -0
- package/lib/adoption/conflict-resolver.js +410 -0
- package/lib/adoption/detection-engine.js +275 -0
- package/lib/adoption/diff-viewer.js +226 -0
- package/lib/adoption/error-formatter.js +509 -0
- package/lib/adoption/file-classifier.js +385 -0
- package/lib/adoption/progress-reporter.js +534 -0
- package/lib/adoption/smart-orchestrator.js +470 -0
- package/lib/adoption/strategy-selector.js +218 -0
- package/lib/adoption/summary-generator.js +493 -0
- package/lib/adoption/template-sync.js +605 -0
- package/lib/auto/autonomous-engine.js +485 -0
- package/lib/auto/checkpoint-manager.js +300 -0
- package/lib/auto/close-loop-runner.js +2476 -0
- package/lib/auto/config-schema.js +176 -0
- package/lib/auto/decision-engine.js +344 -0
- package/lib/auto/error-recovery-manager.js +580 -0
- package/lib/auto/goal-decomposer.js +278 -0
- package/lib/auto/progress-tracker.js +502 -0
- package/lib/auto/safety-manager.js +186 -0
- package/lib/auto/semantic-decomposer.js +137 -0
- package/lib/auto/state-manager.js +126 -0
- package/lib/auto/task-queue-manager.js +340 -0
- package/lib/backup/backup-system.js +372 -0
- package/lib/backup/selective-backup.js +207 -0
- package/lib/collab/agent-registry.js +240 -0
- package/lib/collab/collab-manager.js +285 -0
- package/lib/collab/contract-manager.js +320 -0
- package/lib/collab/coordinator.js +370 -0
- package/lib/collab/dependency-manager.js +280 -0
- package/lib/collab/index.js +20 -0
- package/lib/collab/integration-manager.js +202 -0
- package/lib/collab/merge-coordinator.js +252 -0
- package/lib/collab/metadata-manager.js +233 -0
- package/lib/collab/multi-agent-config.js +120 -0
- package/lib/collab/spec-lifecycle-manager.js +304 -0
- package/lib/collab/sync-barrier.js +88 -0
- package/lib/collab/visualizer.js +208 -0
- package/lib/commands/adopt.js +749 -0
- package/lib/commands/auto.js +19559 -0
- package/lib/commands/collab.js +275 -0
- package/lib/commands/context.js +99 -0
- package/lib/commands/docs.js +808 -0
- package/lib/commands/doctor.js +273 -0
- package/lib/commands/env.js +420 -0
- package/lib/commands/knowledge.js +309 -0
- package/lib/commands/lock.js +235 -0
- package/lib/commands/ops.js +409 -0
- package/lib/commands/orchestrate.js +446 -0
- package/lib/commands/prompt.js +105 -0
- package/lib/commands/repo.js +118 -0
- package/lib/commands/rollback.js +219 -0
- package/lib/commands/scene.js +15549 -0
- package/lib/commands/spec-bootstrap.js +147 -0
- package/lib/commands/spec-gate.js +157 -0
- package/lib/commands/spec-pipeline.js +205 -0
- package/lib/commands/status.js +321 -0
- package/lib/commands/task.js +199 -0
- package/lib/commands/templates.js +654 -0
- package/lib/commands/upgrade.js +231 -0
- package/lib/commands/value.js +569 -0
- package/lib/commands/watch.js +684 -0
- package/lib/commands/workflows.js +240 -0
- package/lib/commands/workspace-multi.js +325 -0
- package/lib/commands/workspace.js +189 -0
- package/lib/context/context-exporter.js +378 -0
- package/lib/context/prompt-generator.js +482 -0
- package/lib/data/moqui-capability-lexicon.json +45 -0
- package/lib/environment/backup-system.js +189 -0
- package/lib/environment/environment-manager.js +379 -0
- package/lib/environment/environment-registry.js +168 -0
- package/lib/gitignore/gitignore-backup.js +229 -0
- package/lib/gitignore/gitignore-detector.js +239 -0
- package/lib/gitignore/gitignore-integration.js +267 -0
- package/lib/gitignore/gitignore-transformer.js +193 -0
- package/lib/gitignore/layered-rules-template.js +42 -0
- package/lib/governance/archive-tool.js +284 -0
- package/lib/governance/cleanup-tool.js +237 -0
- package/lib/governance/config-manager.js +186 -0
- package/lib/governance/diagnostic-engine.js +271 -0
- package/lib/governance/doc-reference-checker.js +200 -0
- package/lib/governance/execution-logger.js +243 -0
- package/lib/governance/file-scanner.js +285 -0
- package/lib/governance/hooks-manager.js +333 -0
- package/lib/governance/reporter.js +337 -0
- package/lib/governance/validation-engine.js +181 -0
- package/lib/i18n.js +79 -0
- package/lib/knowledge/entry-manager.js +208 -0
- package/lib/knowledge/index-manager.js +261 -0
- package/lib/knowledge/knowledge-manager.js +273 -0
- package/lib/knowledge/template-manager.js +191 -0
- package/lib/lock/index.js +21 -0
- package/lib/lock/lock-file.js +192 -0
- package/lib/lock/lock-manager.js +321 -0
- package/lib/lock/machine-identifier.js +135 -0
- package/lib/lock/steering-file-lock.js +207 -0
- package/lib/lock/task-lock-manager.js +345 -0
- package/lib/operations/audit-logger.js +293 -0
- package/lib/operations/feedback-manager.js +1147 -0
- package/lib/operations/index.js +23 -0
- package/lib/operations/models/index.js +170 -0
- package/lib/operations/operations-manager.js +151 -0
- package/lib/operations/operations-validator.js +280 -0
- package/lib/operations/permission-manager.js +354 -0
- package/lib/operations/template-loader.js +143 -0
- package/lib/orchestrator/agent-spawner.js +629 -0
- package/lib/orchestrator/bootstrap-prompt-builder.js +236 -0
- package/lib/orchestrator/index.js +19 -0
- package/lib/orchestrator/orchestration-engine.js +1270 -0
- package/lib/orchestrator/orchestrator-config.js +173 -0
- package/lib/orchestrator/status-monitor.js +591 -0
- package/lib/python-checker.js +209 -0
- package/lib/repo/config-manager.js +580 -0
- package/lib/repo/errors/config-error.js +13 -0
- package/lib/repo/errors/git-error.js +15 -0
- package/lib/repo/errors/repo-error.js +14 -0
- package/lib/repo/git-operations.js +181 -0
- package/lib/repo/handlers/.gitkeep +1 -0
- package/lib/repo/handlers/exec-handler.js +155 -0
- package/lib/repo/handlers/health-handler.js +169 -0
- package/lib/repo/handlers/init-handler.js +197 -0
- package/lib/repo/handlers/status-handler.js +176 -0
- package/lib/repo/output-formatter.js +184 -0
- package/lib/repo/path-resolver.js +178 -0
- package/lib/repo/repo-manager.js +514 -0
- package/lib/scene-runtime/audit-emitter.js +59 -0
- package/lib/scene-runtime/binding-plugin-loader.js +351 -0
- package/lib/scene-runtime/binding-registry.js +349 -0
- package/lib/scene-runtime/eval-bridge.js +44 -0
- package/lib/scene-runtime/index.js +19 -0
- package/lib/scene-runtime/moqui-adapter.js +620 -0
- package/lib/scene-runtime/moqui-client.js +606 -0
- package/lib/scene-runtime/moqui-extractor.js +2029 -0
- package/lib/scene-runtime/plan-compiler.js +208 -0
- package/lib/scene-runtime/policy-gate.js +58 -0
- package/lib/scene-runtime/runtime-executor.js +358 -0
- package/lib/scene-runtime/scene-loader.js +96 -0
- package/lib/scene-runtime/scene-ontology.js +959 -0
- package/lib/scene-runtime/scene-template-linter.js +852 -0
- package/lib/scene-runtime/templates/scene-template-erp-query-v0.1.yaml +28 -0
- package/lib/scene-runtime/templates/scene-template-hybrid-shadow-v0.1.yaml +34 -0
- package/lib/spec/bootstrap/context-collector.js +48 -0
- package/lib/spec/bootstrap/draft-generator.js +158 -0
- package/lib/spec/bootstrap/questionnaire-engine.js +70 -0
- package/lib/spec/bootstrap/trace-emitter.js +59 -0
- package/lib/spec/multi-spec-orchestrate.js +93 -0
- package/lib/spec/pipeline/constants.js +6 -0
- package/lib/spec/pipeline/stage-adapters.js +118 -0
- package/lib/spec/pipeline/stage-runner.js +146 -0
- package/lib/spec/pipeline/state-store.js +119 -0
- package/lib/spec-gate/engine/gate-engine.js +165 -0
- package/lib/spec-gate/policy/default-policy.js +22 -0
- package/lib/spec-gate/policy/policy-loader.js +103 -0
- package/lib/spec-gate/result-emitter.js +81 -0
- package/lib/spec-gate/rules/default-rules.js +156 -0
- package/lib/spec-gate/rules/rule-registry.js +51 -0
- package/lib/steering/adoption-config.js +164 -0
- package/lib/steering/compliance-auto-fixer.js +204 -0
- package/lib/steering/compliance-cache.js +99 -0
- package/lib/steering/compliance-error-reporter.js +70 -0
- package/lib/steering/context-sync-manager.js +273 -0
- package/lib/steering/index.js +92 -0
- package/lib/steering/spec-steering.js +230 -0
- package/lib/steering/steering-compliance-checker.js +73 -0
- package/lib/steering/steering-loader.js +144 -0
- package/lib/steering/steering-manager.js +289 -0
- package/lib/task/index.js +12 -0
- package/lib/task/task-claimer.js +489 -0
- package/lib/task/task-status-store.js +418 -0
- package/lib/templates/cache-manager.js +440 -0
- package/lib/templates/content-generalizer.js +247 -0
- package/lib/templates/frontmatter-generator.js +128 -0
- package/lib/templates/git-handler.js +471 -0
- package/lib/templates/metadata-collector.js +328 -0
- package/lib/templates/path-utils.js +144 -0
- package/lib/templates/registry-parser.js +505 -0
- package/lib/templates/spec-reader.js +216 -0
- package/lib/templates/template-applicator.js +249 -0
- package/lib/templates/template-creator.js +256 -0
- package/lib/templates/template-error.js +143 -0
- package/lib/templates/template-exporter.js +502 -0
- package/lib/templates/template-manager.js +782 -0
- package/lib/templates/template-validator.js +361 -0
- package/lib/upgrade/migration-engine.js +382 -0
- package/lib/upgrade/migrations/.gitkeep +52 -0
- package/lib/upgrade/migrations/1.0.0-to-1.1.0.js +78 -0
- package/lib/utils/file-diff.js +177 -0
- package/lib/utils/fs-utils.js +274 -0
- package/lib/utils/tool-detector.js +383 -0
- package/lib/utils/validation.js +324 -0
- package/lib/value/gate-summary-emitter.js +99 -0
- package/lib/value/metric-contract-loader.js +210 -0
- package/lib/value/risk-evaluator.js +117 -0
- package/lib/value/weekly-snapshot-builder.js +61 -0
- package/lib/version/version-checker.js +156 -0
- package/lib/version/version-manager.js +327 -0
- package/lib/watch/action-executor.js +458 -0
- package/lib/watch/event-debouncer.js +323 -0
- package/lib/watch/execution-logger.js +550 -0
- package/lib/watch/file-watcher.js +499 -0
- package/lib/watch/presets.js +266 -0
- package/lib/watch/watch-manager.js +533 -0
- package/lib/workspace/multi/global-config.js +150 -0
- package/lib/workspace/multi/index.js +22 -0
- package/lib/workspace/multi/path-utils.js +173 -0
- package/lib/workspace/multi/workspace-context-resolver.js +244 -0
- package/lib/workspace/multi/workspace-registry.js +196 -0
- package/lib/workspace/multi/workspace-state-manager.js +537 -0
- package/lib/workspace/multi/workspace.js +90 -0
- package/lib/workspace/workspace-manager.js +370 -0
- package/lib/workspace/workspace-sync.js +356 -0
- package/locales/en.json +114 -0
- package/locales/zh.json +114 -0
- package/package.json +102 -0
- package/template/.kiro/README.md +247 -0
- package/template/.kiro/hooks/check-spec-on-create.kiro.hook +17 -0
- package/template/.kiro/hooks/run-tests-on-save.kiro.hook +13 -0
- package/template/.kiro/hooks/sync-tasks-on-edit.kiro.hook +16 -0
- package/template/.kiro/specs/SPEC_WORKFLOW_GUIDE.md +134 -0
- package/template/.kiro/steering/CORE_PRINCIPLES.md +133 -0
- package/template/.kiro/steering/CURRENT_CONTEXT.md +30 -0
- package/template/.kiro/steering/ENVIRONMENT.md +35 -0
- package/template/.kiro/steering/RULES_GUIDE.md +46 -0
- package/template/.kiro/templates/operations/default/change-impact.md +112 -0
- package/template/.kiro/templates/operations/default/deployment.md +91 -0
- package/template/.kiro/templates/operations/default/feedback-response.md +269 -0
- package/template/.kiro/templates/operations/default/migration-plan.md +172 -0
- package/template/.kiro/templates/operations/default/monitoring.md +135 -0
- package/template/.kiro/templates/operations/default/operations.md +135 -0
- package/template/.kiro/templates/operations/default/rollback.md +143 -0
- package/template/.kiro/templates/operations/default/tools.yaml +364 -0
- package/template/.kiro/templates/operations/default/troubleshooting.md +123 -0
- package/template/.kiro/tools/backup_manager.py +295 -0
- package/template/.kiro/tools/configuration_manager.py +218 -0
- package/template/.kiro/tools/document_evaluator.py +550 -0
- package/template/.kiro/tools/enhancement_logger.py +168 -0
- package/template/.kiro/tools/error_handler.py +335 -0
- package/template/.kiro/tools/improvement_identifier.py +444 -0
- package/template/.kiro/tools/modification_applicator.py +737 -0
- package/template/.kiro/tools/quality_gate_enforcer.py +207 -0
- package/template/.kiro/tools/quality_scorer.py +305 -0
- package/template/.kiro/tools/report_generator.py +154 -0
- package/template/.kiro/tools/ultrawork_enhancer.py +676 -0
- package/template/.kiro/tools/ultrawork_enhancer_refactored.py +0 -0
- package/template/.kiro/tools/ultrawork_enhancer_v2.py +463 -0
- package/template/.kiro/tools/ultrawork_enhancer_v3.py +606 -0
- package/template/.kiro/tools/workflow_quality_gate.py +100 -0
- package/template/README.md +111 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const docsCommand = require('../../commands/docs');
|
|
4
|
+
|
|
5
|
+
function createDefaultRules(projectPath = process.cwd()) {
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
id: 'mandatory',
|
|
9
|
+
description: 'Verify mandatory Spec files exist',
|
|
10
|
+
async execute(context) {
|
|
11
|
+
const specPath = path.join(projectPath, '.kiro', 'specs', context.specId);
|
|
12
|
+
const requiredFiles = ['requirements.md', 'design.md', 'tasks.md'];
|
|
13
|
+
const checks = await Promise.all(requiredFiles.map(async fileName => {
|
|
14
|
+
const filePath = path.join(specPath, fileName);
|
|
15
|
+
const exists = await fs.pathExists(filePath);
|
|
16
|
+
return { fileName, exists };
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const missing = checks.filter(item => !item.exists).map(item => item.fileName);
|
|
20
|
+
const passRatio = checks.filter(item => item.exists).length / requiredFiles.length;
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
passed: missing.length === 0,
|
|
24
|
+
ratio: passRatio,
|
|
25
|
+
details: {
|
|
26
|
+
requiredFiles,
|
|
27
|
+
missing
|
|
28
|
+
},
|
|
29
|
+
warnings: missing.length > 0 ? [`Missing files: ${missing.join(', ')}`] : []
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'tests',
|
|
35
|
+
description: 'Verify tasks include explicit validation intent',
|
|
36
|
+
async execute(context) {
|
|
37
|
+
const tasksPath = path.join(projectPath, '.kiro', 'specs', context.specId, 'tasks.md');
|
|
38
|
+
if (!await fs.pathExists(tasksPath)) {
|
|
39
|
+
return {
|
|
40
|
+
passed: false,
|
|
41
|
+
ratio: 0,
|
|
42
|
+
details: { reason: 'tasks.md missing' },
|
|
43
|
+
warnings: ['tasks.md missing']
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const content = await fs.readFile(tasksPath, 'utf8');
|
|
48
|
+
const hasValidationHints = /éŖčÆ|Validation|Acceptance/i.test(content);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
passed: hasValidationHints,
|
|
52
|
+
ratio: hasValidationHints ? 1 : 0,
|
|
53
|
+
details: {
|
|
54
|
+
hasValidationHints
|
|
55
|
+
},
|
|
56
|
+
warnings: hasValidationHints ? [] : ['No validation markers found in tasks.md']
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'docs',
|
|
62
|
+
description: 'Validate document structure compatibility',
|
|
63
|
+
async execute(context) {
|
|
64
|
+
const exitCode = await docsCommand('validate', {
|
|
65
|
+
spec: context.specId
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
passed: exitCode === 0,
|
|
70
|
+
ratio: exitCode === 0 ? 1 : 0,
|
|
71
|
+
details: {
|
|
72
|
+
exitCode
|
|
73
|
+
},
|
|
74
|
+
warnings: exitCode === 0 ? [] : [`docs validate returned exit code ${exitCode}`]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'config_consistency',
|
|
80
|
+
description: 'Verify project-level KSE config baseline exists',
|
|
81
|
+
async execute() {
|
|
82
|
+
const kiroDir = path.join(projectPath, '.kiro');
|
|
83
|
+
const configDir = path.join(kiroDir, 'config');
|
|
84
|
+
const hasKiro = await fs.pathExists(kiroDir);
|
|
85
|
+
const hasConfig = await fs.pathExists(configDir);
|
|
86
|
+
|
|
87
|
+
const ratio = hasKiro && hasConfig ? 1 : hasKiro ? 0.5 : 0;
|
|
88
|
+
const warnings = [];
|
|
89
|
+
if (!hasKiro) {
|
|
90
|
+
warnings.push('.kiro directory missing');
|
|
91
|
+
}
|
|
92
|
+
if (hasKiro && !hasConfig) {
|
|
93
|
+
warnings.push('.kiro/config directory missing');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
passed: hasKiro,
|
|
98
|
+
ratio,
|
|
99
|
+
details: {
|
|
100
|
+
hasKiro,
|
|
101
|
+
hasConfig
|
|
102
|
+
},
|
|
103
|
+
warnings
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'traceability',
|
|
109
|
+
description: 'Verify requirement-design-task traceability hints',
|
|
110
|
+
async execute(context) {
|
|
111
|
+
const specPath = path.join(projectPath, '.kiro', 'specs', context.specId);
|
|
112
|
+
const designPath = path.join(specPath, 'design.md');
|
|
113
|
+
const tasksPath = path.join(specPath, 'tasks.md');
|
|
114
|
+
|
|
115
|
+
const hasDesign = await fs.pathExists(designPath);
|
|
116
|
+
const hasTasks = await fs.pathExists(tasksPath);
|
|
117
|
+
|
|
118
|
+
if (!hasDesign || !hasTasks) {
|
|
119
|
+
return {
|
|
120
|
+
passed: false,
|
|
121
|
+
ratio: 0,
|
|
122
|
+
details: {
|
|
123
|
+
hasDesign,
|
|
124
|
+
hasTasks
|
|
125
|
+
},
|
|
126
|
+
warnings: ['design.md or tasks.md missing']
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const [designContent, tasksContent] = await Promise.all([
|
|
131
|
+
fs.readFile(designPath, 'utf8'),
|
|
132
|
+
fs.readFile(tasksPath, 'utf8')
|
|
133
|
+
]);
|
|
134
|
+
|
|
135
|
+
const hasMapping = /Mapping|ę å°|Requirement/i.test(designContent);
|
|
136
|
+
const hasTaskReferences = /Requirement|Design|éę±|设讔/i.test(tasksContent);
|
|
137
|
+
const scoreParts = [hasMapping, hasTaskReferences].filter(Boolean).length;
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
passed: hasMapping && hasTaskReferences,
|
|
141
|
+
ratio: scoreParts / 2,
|
|
142
|
+
details: {
|
|
143
|
+
hasMapping,
|
|
144
|
+
hasTaskReferences
|
|
145
|
+
},
|
|
146
|
+
warnings: hasMapping && hasTaskReferences ? [] : ['Traceability links are incomplete']
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
module.exports = {
|
|
154
|
+
createDefaultRules
|
|
155
|
+
};
|
|
156
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
class RuleRegistry {
|
|
2
|
+
constructor(initialRules = []) {
|
|
3
|
+
this.rules = new Map();
|
|
4
|
+
initialRules.forEach(rule => this.register(rule));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
register(rule) {
|
|
8
|
+
if (!rule || !rule.id || typeof rule.execute !== 'function') {
|
|
9
|
+
throw new Error('Invalid gate rule: expected id and execute()');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
this.rules.set(rule.id, rule);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
setEnabled(ruleId, enabled) {
|
|
16
|
+
const rule = this.rules.get(ruleId);
|
|
17
|
+
if (!rule) {
|
|
18
|
+
throw new Error(`Rule not found: ${ruleId}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
rule.enabled = !!enabled;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get(ruleId) {
|
|
25
|
+
return this.rules.get(ruleId);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
list() {
|
|
29
|
+
return Array.from(this.rules.values());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
listEnabled(policyRules = {}) {
|
|
33
|
+
return this.list().filter(rule => {
|
|
34
|
+
const policy = policyRules[rule.id];
|
|
35
|
+
if (!policy) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof rule.enabled === 'boolean') {
|
|
40
|
+
return rule.enabled;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return policy.enabled !== false;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
RuleRegistry
|
|
50
|
+
};
|
|
51
|
+
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AdoptionConfig - ē®”ē adoption-config.json é
ē½®ęä»¶
|
|
6
|
+
*
|
|
7
|
+
* č®°å½é”¹ē®éēØ kse ę¶ēé
ē½®éę©
|
|
8
|
+
*/
|
|
9
|
+
class AdoptionConfig {
|
|
10
|
+
constructor(projectPath) {
|
|
11
|
+
this.projectPath = projectPath;
|
|
12
|
+
this.configPath = path.join(projectPath, '.kiro', 'adoption-config.json');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 读åé
ē½®ęä»¶
|
|
17
|
+
*
|
|
18
|
+
* @returns {Promise<Object|null>} é
置对豔ļ¼å¦ęäøååØåčæå null
|
|
19
|
+
*/
|
|
20
|
+
async read() {
|
|
21
|
+
try {
|
|
22
|
+
const exists = await fs.pathExists(this.configPath);
|
|
23
|
+
if (!exists) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const content = await fs.readFile(this.configPath, 'utf8');
|
|
28
|
+
return JSON.parse(content);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error(`Error reading adoption config: ${error.message}`);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* åå
„é
ē½®ęä»¶
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} config - é
置对豔
|
|
39
|
+
* @returns {Promise<boolean>} ęÆå¦ęå
|
|
40
|
+
*/
|
|
41
|
+
async write(config) {
|
|
42
|
+
try {
|
|
43
|
+
// ē”®äæē®å½ååØ
|
|
44
|
+
await fs.ensureDir(path.dirname(this.configPath));
|
|
45
|
+
|
|
46
|
+
// åå
„é
ē½®
|
|
47
|
+
await fs.writeFile(
|
|
48
|
+
this.configPath,
|
|
49
|
+
JSON.stringify(config, null, 2),
|
|
50
|
+
'utf8'
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return true;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error(`Error writing adoption config: ${error.message}`);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* ę“ę° steering ēē„é
ē½®
|
|
62
|
+
*
|
|
63
|
+
* @param {string} strategy - ēē„ ('use-kse' | 'use-project')
|
|
64
|
+
* @param {string|null} backupId - å¤ä»½ IDļ¼å¦ęęļ¼
|
|
65
|
+
* @returns {Promise<boolean>} ęÆå¦ęå
|
|
66
|
+
*/
|
|
67
|
+
async updateSteeringStrategy(strategy, backupId = null) {
|
|
68
|
+
// 读åē°ęé
ē½®
|
|
69
|
+
let config = await this.read();
|
|
70
|
+
|
|
71
|
+
if (!config) {
|
|
72
|
+
// å建ę°é
ē½®
|
|
73
|
+
config = {
|
|
74
|
+
version: '1.0.0',
|
|
75
|
+
adoptedAt: new Date().toISOString(),
|
|
76
|
+
multiUserMode: false
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ę“ę° steering ēē„
|
|
81
|
+
config.steeringStrategy = strategy;
|
|
82
|
+
|
|
83
|
+
if (backupId) {
|
|
84
|
+
config.steeringBackupId = backupId;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
config.lastUpdated = new Date().toISOString();
|
|
88
|
+
|
|
89
|
+
// åå
„é
ē½®
|
|
90
|
+
return await this.write(config);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* ę“ę°å¤ēØę·ęØ”å¼é
ē½®
|
|
95
|
+
*
|
|
96
|
+
* @param {boolean} enabled - ęÆå¦åÆēØå¤ēØę·ęØ”å¼
|
|
97
|
+
* @returns {Promise<boolean>} ęÆå¦ęå
|
|
98
|
+
*/
|
|
99
|
+
async updateMultiUserMode(enabled) {
|
|
100
|
+
let config = await this.read();
|
|
101
|
+
|
|
102
|
+
if (!config) {
|
|
103
|
+
config = {
|
|
104
|
+
version: '1.0.0',
|
|
105
|
+
adoptedAt: new Date().toISOString()
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
config.multiUserMode = enabled;
|
|
110
|
+
config.lastUpdated = new Date().toISOString();
|
|
111
|
+
|
|
112
|
+
return await this.write(config);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* č·å steering ēē„
|
|
117
|
+
*
|
|
118
|
+
* @returns {Promise<string|null>} ēē„ę null
|
|
119
|
+
*/
|
|
120
|
+
async getSteeringStrategy() {
|
|
121
|
+
const config = await this.read();
|
|
122
|
+
return config ? config.steeringStrategy : null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* č·å steering å¤ä»½ ID
|
|
127
|
+
*
|
|
128
|
+
* @returns {Promise<string|null>} å¤ä»½ ID ę null
|
|
129
|
+
*/
|
|
130
|
+
async getSteeringBackupId() {
|
|
131
|
+
const config = await this.read();
|
|
132
|
+
return config ? config.steeringBackupId : null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* ę£ę„ęÆå¦åÆēØå¤ēØę·ęØ”å¼
|
|
137
|
+
*
|
|
138
|
+
* @returns {Promise<boolean>} ęÆå¦åÆēØ
|
|
139
|
+
*/
|
|
140
|
+
async isMultiUserMode() {
|
|
141
|
+
const config = await this.read();
|
|
142
|
+
return config ? (config.multiUserMode || false) : false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* å建åå§é
ē½®
|
|
147
|
+
*
|
|
148
|
+
* @param {Object} options - é
ē½®é锹
|
|
149
|
+
* @returns {Promise<boolean>} ęÆå¦ęå
|
|
150
|
+
*/
|
|
151
|
+
async initialize(options = {}) {
|
|
152
|
+
const config = {
|
|
153
|
+
version: '1.0.0',
|
|
154
|
+
adoptedAt: new Date().toISOString(),
|
|
155
|
+
steeringStrategy: options.steeringStrategy || 'use-kse',
|
|
156
|
+
multiUserMode: options.multiUserMode || false,
|
|
157
|
+
...options
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
return await this.write(config);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = AdoptionConfig;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Automatically fix steering directory compliance violations
|
|
7
|
+
* by backing up and removing disallowed files and subdirectories
|
|
8
|
+
*/
|
|
9
|
+
class ComplianceAutoFixer {
|
|
10
|
+
/**
|
|
11
|
+
* Fix compliance violations automatically (no user confirmation)
|
|
12
|
+
* @param {string} steeringPath - Path to steering directory
|
|
13
|
+
* @param {Array} violations - List of violations from compliance check
|
|
14
|
+
* @returns {Object} Fix result with backup info and cleaned files
|
|
15
|
+
*/
|
|
16
|
+
async fix(steeringPath, violations) {
|
|
17
|
+
if (!violations || violations.length === 0) {
|
|
18
|
+
return {
|
|
19
|
+
success: true,
|
|
20
|
+
message: 'No violations to fix',
|
|
21
|
+
backupPath: null,
|
|
22
|
+
cleanedFiles: [],
|
|
23
|
+
cleanedDirs: []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Separate violations by type
|
|
28
|
+
const disallowedFiles = violations
|
|
29
|
+
.filter(v => v.type === 'disallowed_file')
|
|
30
|
+
.map(v => v.name);
|
|
31
|
+
const subdirectories = violations
|
|
32
|
+
.filter(v => v.type === 'subdirectory')
|
|
33
|
+
.map(v => v.name);
|
|
34
|
+
|
|
35
|
+
// Check if this is a multi-user project (contexts/ directory exists)
|
|
36
|
+
const contextsPath = path.join(path.dirname(path.dirname(steeringPath)), 'contexts');
|
|
37
|
+
const isMultiUser = await fs.pathExists(contextsPath);
|
|
38
|
+
|
|
39
|
+
// Show what will be fixed
|
|
40
|
+
console.log(chalk.yellow('\nš§ Auto-fixing steering directory compliance violations...\n'));
|
|
41
|
+
|
|
42
|
+
if (disallowedFiles.length > 0) {
|
|
43
|
+
console.log(chalk.yellow('Disallowed files to be removed:'));
|
|
44
|
+
disallowedFiles.forEach(file => console.log(` - ${file}`));
|
|
45
|
+
console.log();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (subdirectories.length > 0) {
|
|
49
|
+
console.log(chalk.yellow('Subdirectories to be removed:'));
|
|
50
|
+
subdirectories.forEach(dir => console.log(` - ${dir}/`));
|
|
51
|
+
console.log();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Show multi-user warning if applicable
|
|
55
|
+
if (isMultiUser) {
|
|
56
|
+
console.log(chalk.blue('ā¹ļø Multi-user project detected'));
|
|
57
|
+
console.log(chalk.blue(' Your personal CURRENT_CONTEXT.md is preserved in contexts/'));
|
|
58
|
+
console.log();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Create backup
|
|
62
|
+
const backupPath = await this._createBackup(steeringPath, disallowedFiles, subdirectories);
|
|
63
|
+
console.log(chalk.green(`ā Backup created: ${backupPath}\n`));
|
|
64
|
+
|
|
65
|
+
// Clean up violations
|
|
66
|
+
const cleanedFiles = [];
|
|
67
|
+
const cleanedDirs = [];
|
|
68
|
+
|
|
69
|
+
// Remove disallowed files
|
|
70
|
+
for (const file of disallowedFiles) {
|
|
71
|
+
const filePath = path.join(steeringPath, file);
|
|
72
|
+
try {
|
|
73
|
+
await fs.remove(filePath);
|
|
74
|
+
cleanedFiles.push(file);
|
|
75
|
+
console.log(chalk.green(`ā Removed file: ${file}`));
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error(chalk.red(`ā Failed to remove ${file}: ${error.message}`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Remove subdirectories
|
|
82
|
+
for (const dir of subdirectories) {
|
|
83
|
+
const dirPath = path.join(steeringPath, dir);
|
|
84
|
+
try {
|
|
85
|
+
await fs.remove(dirPath);
|
|
86
|
+
cleanedDirs.push(dir);
|
|
87
|
+
console.log(chalk.green(`ā Removed directory: ${dir}/`));
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(chalk.red(`ā Failed to remove ${dir}/: ${error.message}`));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log(chalk.green('\nā Steering directory cleaned successfully!\n'));
|
|
94
|
+
console.log(chalk.blue('Backup location:'));
|
|
95
|
+
console.log(` ${backupPath}\n`);
|
|
96
|
+
console.log(chalk.blue('To restore from backup:'));
|
|
97
|
+
console.log(` kse rollback --backup ${path.basename(backupPath)}\n`);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
message: 'Steering directory fixed successfully',
|
|
102
|
+
backupPath,
|
|
103
|
+
cleanedFiles,
|
|
104
|
+
cleanedDirs
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Create differential backup of violations only
|
|
110
|
+
* @private
|
|
111
|
+
*/
|
|
112
|
+
async _createBackup(steeringPath, files, dirs) {
|
|
113
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
114
|
+
const backupId = `steering-cleanup-${timestamp}`;
|
|
115
|
+
const backupPath = path.join(path.dirname(path.dirname(steeringPath)), 'backups', backupId);
|
|
116
|
+
|
|
117
|
+
// Create backup directory
|
|
118
|
+
await fs.ensureDir(backupPath);
|
|
119
|
+
|
|
120
|
+
// Backup disallowed files
|
|
121
|
+
for (const file of files) {
|
|
122
|
+
const sourcePath = path.join(steeringPath, file);
|
|
123
|
+
const destPath = path.join(backupPath, file);
|
|
124
|
+
|
|
125
|
+
if (await fs.pathExists(sourcePath)) {
|
|
126
|
+
await fs.copy(sourcePath, destPath);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Backup subdirectories
|
|
131
|
+
for (const dir of dirs) {
|
|
132
|
+
const sourcePath = path.join(steeringPath, dir);
|
|
133
|
+
const destPath = path.join(backupPath, dir);
|
|
134
|
+
|
|
135
|
+
if (await fs.pathExists(sourcePath)) {
|
|
136
|
+
await fs.copy(sourcePath, destPath);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Create backup manifest
|
|
141
|
+
const manifest = {
|
|
142
|
+
backupId,
|
|
143
|
+
timestamp: new Date().toISOString(),
|
|
144
|
+
type: 'steering-cleanup',
|
|
145
|
+
steeringPath,
|
|
146
|
+
files,
|
|
147
|
+
directories: dirs,
|
|
148
|
+
totalItems: files.length + dirs.length
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
await fs.writeJson(path.join(backupPath, 'manifest.json'), manifest, { spaces: 2 });
|
|
152
|
+
|
|
153
|
+
return backupPath;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Restore from backup
|
|
158
|
+
* @param {string} backupPath - Path to backup directory
|
|
159
|
+
* @param {string} steeringPath - Path to steering directory
|
|
160
|
+
*/
|
|
161
|
+
async restore(backupPath, steeringPath) {
|
|
162
|
+
// Read manifest
|
|
163
|
+
const manifestPath = path.join(backupPath, 'manifest.json');
|
|
164
|
+
if (!await fs.pathExists(manifestPath)) {
|
|
165
|
+
throw new Error('Invalid backup: manifest.json not found');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const manifest = await fs.readJson(manifestPath);
|
|
169
|
+
|
|
170
|
+
console.log(chalk.yellow('\nš Restoring from backup...\n'));
|
|
171
|
+
|
|
172
|
+
// Restore files
|
|
173
|
+
for (const file of manifest.files) {
|
|
174
|
+
const sourcePath = path.join(backupPath, file);
|
|
175
|
+
const destPath = path.join(steeringPath, file);
|
|
176
|
+
|
|
177
|
+
if (await fs.pathExists(sourcePath)) {
|
|
178
|
+
await fs.copy(sourcePath, destPath);
|
|
179
|
+
console.log(chalk.green(`ā Restored file: ${file}`));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Restore directories
|
|
184
|
+
for (const dir of manifest.directories) {
|
|
185
|
+
const sourcePath = path.join(backupPath, dir);
|
|
186
|
+
const destPath = path.join(steeringPath, dir);
|
|
187
|
+
|
|
188
|
+
if (await fs.pathExists(sourcePath)) {
|
|
189
|
+
await fs.copy(sourcePath, destPath);
|
|
190
|
+
console.log(chalk.green(`ā Restored directory: ${dir}/`));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log(chalk.green('\nā Restore completed!\n'));
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
success: true,
|
|
198
|
+
restoredFiles: manifest.files,
|
|
199
|
+
restoredDirs: manifest.directories
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = ComplianceAutoFixer;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ComplianceCache - Manages version-based check caching
|
|
7
|
+
*
|
|
8
|
+
* Stores the last successful compliance check version to avoid
|
|
9
|
+
* repeated checks for the same kse version.
|
|
10
|
+
*/
|
|
11
|
+
class ComplianceCache {
|
|
12
|
+
/**
|
|
13
|
+
* Create a new ComplianceCache instance
|
|
14
|
+
*
|
|
15
|
+
* @param {string} cachePath - Optional custom cache file path
|
|
16
|
+
*/
|
|
17
|
+
constructor(cachePath = null) {
|
|
18
|
+
this.cachePath = cachePath || this.getDefaultCachePath();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the default cache file path
|
|
23
|
+
*
|
|
24
|
+
* @returns {string} Path to ~/.kse/steering-check-cache.json
|
|
25
|
+
*/
|
|
26
|
+
getDefaultCachePath() {
|
|
27
|
+
const homeDir = os.homedir();
|
|
28
|
+
return path.join(homeDir, '.kse', 'steering-check-cache.json');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if cache is valid for current version
|
|
33
|
+
*
|
|
34
|
+
* @param {string} currentVersion - Current kse version
|
|
35
|
+
* @returns {boolean} True if cache is valid
|
|
36
|
+
*/
|
|
37
|
+
isValid(currentVersion) {
|
|
38
|
+
try {
|
|
39
|
+
if (!fs.existsSync(this.cachePath)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const cache = JSON.parse(fs.readFileSync(this.cachePath, 'utf8'));
|
|
44
|
+
return cache.version === currentVersion && cache.lastCheck === 'success';
|
|
45
|
+
} catch (error) {
|
|
46
|
+
// Treat any cache read error as cache miss
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Update cache with successful check
|
|
53
|
+
*
|
|
54
|
+
* @param {string} version - kse version
|
|
55
|
+
* @returns {boolean} True if update succeeded
|
|
56
|
+
*/
|
|
57
|
+
update(version) {
|
|
58
|
+
try {
|
|
59
|
+
const cacheDir = path.dirname(this.cachePath);
|
|
60
|
+
|
|
61
|
+
// Ensure cache directory exists
|
|
62
|
+
if (!fs.existsSync(cacheDir)) {
|
|
63
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const cacheData = {
|
|
67
|
+
version,
|
|
68
|
+
timestamp: new Date().toISOString(),
|
|
69
|
+
lastCheck: 'success'
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
fs.writeFileSync(this.cachePath, JSON.stringify(cacheData, null, 2), 'utf8');
|
|
73
|
+
return true;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
// Log error but don't throw - cache write failure is not critical
|
|
76
|
+
console.warn(`Warning: Failed to update compliance cache: ${error.message}`);
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Clear the cache
|
|
83
|
+
*
|
|
84
|
+
* @returns {boolean} True if clear succeeded
|
|
85
|
+
*/
|
|
86
|
+
clear() {
|
|
87
|
+
try {
|
|
88
|
+
if (fs.existsSync(this.cachePath)) {
|
|
89
|
+
fs.unlinkSync(this.cachePath);
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.warn(`Warning: Failed to clear compliance cache: ${error.message}`);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = ComplianceCache;
|