@lamentis/naome 1.3.0 → 1.3.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.
Files changed (137) hide show
  1. package/Cargo.lock +2 -2
  2. package/README.md +11 -2
  3. package/bin/naome.js +62 -24
  4. package/crates/naome-cli/Cargo.toml +1 -1
  5. package/crates/naome-cli/src/context_commands.rs +47 -0
  6. package/crates/naome-cli/src/dispatcher.rs +6 -0
  7. package/crates/naome-cli/src/main.rs +43 -6
  8. package/crates/naome-cli/src/quality_commands.rs +31 -46
  9. package/crates/naome-cli/src/quality_output.rs +34 -0
  10. package/crates/naome-cli/src/quality_reconcile_command.rs +45 -0
  11. package/crates/naome-cli/src/repository_model_commands.rs +84 -0
  12. package/crates/naome-cli/src/task_commands.rs +62 -0
  13. package/crates/naome-cli/src/workflow_commands.rs +100 -3
  14. package/crates/naome-core/Cargo.toml +1 -1
  15. package/crates/naome-core/src/context/helpers.rs +75 -0
  16. package/crates/naome-core/src/context/select.rs +134 -0
  17. package/crates/naome-core/src/context/types.rs +43 -0
  18. package/crates/naome-core/src/context.rs +6 -0
  19. package/crates/naome-core/src/decision/states.rs +1 -1
  20. package/crates/naome-core/src/decision.rs +4 -1
  21. package/crates/naome-core/src/install_plan.rs +18 -0
  22. package/crates/naome-core/src/journal.rs +2 -7
  23. package/crates/naome-core/src/lib.rs +33 -10
  24. package/crates/naome-core/src/quality/adapter_ios.rs +131 -0
  25. package/crates/naome-core/src/quality/adapter_support.rs +67 -0
  26. package/crates/naome-core/src/quality/adapters.rs +81 -18
  27. package/crates/naome-core/src/quality/cache.rs +7 -9
  28. package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +4 -7
  29. package/crates/naome-core/src/quality/config.rs +21 -3
  30. package/crates/naome-core/src/quality/mod.rs +138 -7
  31. package/crates/naome-core/src/quality/reconcile.rs +138 -0
  32. package/crates/naome-core/src/quality/reconcile_anchors.rs +64 -0
  33. package/crates/naome-core/src/quality/scanner/analysis.rs +20 -5
  34. package/crates/naome-core/src/quality/scanner.rs +62 -17
  35. package/crates/naome-core/src/quality/semantic/checks.rs +17 -0
  36. package/crates/naome-core/src/quality/semantic/route.rs +1 -1
  37. package/crates/naome-core/src/quality/structure/adapter_ios.rs +149 -0
  38. package/crates/naome-core/src/quality/structure/adapters.rs +60 -42
  39. package/crates/naome-core/src/quality/structure/checks/directory.rs +6 -4
  40. package/crates/naome-core/src/quality/structure/classify/roles.rs +51 -5
  41. package/crates/naome-core/src/quality/structure/config.rs +24 -3
  42. package/crates/naome-core/src/quality/structure/mod.rs +3 -0
  43. package/crates/naome-core/src/quality/types.rs +20 -1
  44. package/crates/naome-core/src/repository_model/detect.rs +188 -0
  45. package/crates/naome-core/src/repository_model/explain.rs +121 -0
  46. package/crates/naome-core/src/repository_model/path_scan.rs +67 -0
  47. package/crates/naome-core/src/repository_model/path_support.rs +59 -0
  48. package/crates/naome-core/src/repository_model/types.rs +152 -0
  49. package/crates/naome-core/src/repository_model/world.rs +48 -0
  50. package/crates/naome-core/src/repository_model/world_adapters.rs +145 -0
  51. package/crates/naome-core/src/repository_model/world_path_facts.rs +55 -0
  52. package/crates/naome-core/src/repository_model/world_paths.rs +168 -0
  53. package/crates/naome-core/src/repository_model.rs +164 -0
  54. package/crates/naome-core/src/route/builtin_checks.rs +40 -1
  55. package/crates/naome-core/src/task_ledger/import.rs +142 -0
  56. package/crates/naome-core/src/task_ledger/model.rs +13 -0
  57. package/crates/naome-core/src/task_ledger/proof_record.rs +52 -0
  58. package/crates/naome-core/src/task_ledger/read.rs +118 -0
  59. package/crates/naome-core/src/task_ledger/render.rs +55 -0
  60. package/crates/naome-core/src/task_ledger/write.rs +38 -0
  61. package/crates/naome-core/src/task_ledger.rs +48 -0
  62. package/crates/naome-core/src/task_state/api.rs +4 -2
  63. package/crates/naome-core/src/task_state/completed_refresh.rs +5 -16
  64. package/crates/naome-core/src/task_state/diff.rs +2 -2
  65. package/crates/naome-core/src/task_state/evidence.rs +8 -3
  66. package/crates/naome-core/src/task_state/mod.rs +1 -1
  67. package/crates/naome-core/src/task_state/progress.rs +13 -0
  68. package/crates/naome-core/src/task_state/proof_model.rs +8 -8
  69. package/crates/naome-core/src/task_state/repair.rs +2 -2
  70. package/crates/naome-core/src/task_state/task_diff_api.rs +9 -18
  71. package/crates/naome-core/src/task_state/types.rs +24 -0
  72. package/crates/naome-core/src/verification.rs +29 -18
  73. package/crates/naome-core/src/workflow/agent/capability.rs +194 -0
  74. package/crates/naome-core/src/workflow/agent/context_delta.rs +42 -0
  75. package/crates/naome-core/src/workflow/agent/decision.rs +32 -0
  76. package/crates/naome-core/src/workflow/agent/execution.rs +80 -0
  77. package/crates/naome-core/src/workflow/agent/proof.rs +24 -0
  78. package/crates/naome-core/src/workflow/agent/support.rs +58 -0
  79. package/crates/naome-core/src/workflow/agent/watchdog.rs +47 -0
  80. package/crates/naome-core/src/workflow/agent.rs +34 -0
  81. package/crates/naome-core/src/workflow/agent_types.rs +105 -0
  82. package/crates/naome-core/src/workflow/doctor.rs +39 -0
  83. package/crates/naome-core/src/workflow/mod.rs +11 -0
  84. package/crates/naome-core/src/workflow/output.rs +8 -2
  85. package/crates/naome-core/src/workflow/phase_inference.rs +1 -1
  86. package/crates/naome-core/tests/context.rs +99 -0
  87. package/crates/naome-core/tests/harness_health.rs +4 -0
  88. package/crates/naome-core/tests/install_plan.rs +12 -0
  89. package/crates/naome-core/tests/quality.rs +178 -2
  90. package/crates/naome-core/tests/quality_performance.rs +39 -2
  91. package/crates/naome-core/tests/quality_structure_adapters.rs +39 -0
  92. package/crates/naome-core/tests/repo_support/mod.rs +5 -1
  93. package/crates/naome-core/tests/repo_support/verification_values.rs +55 -0
  94. package/crates/naome-core/tests/repository_model.rs +281 -0
  95. package/crates/naome-core/tests/route_user_diff.rs +49 -1
  96. package/crates/naome-core/tests/semantic_legacy.rs +72 -38
  97. package/crates/naome-core/tests/task_ledger.rs +328 -0
  98. package/crates/naome-core/tests/task_state.rs +28 -0
  99. package/crates/naome-core/tests/verification.rs +29 -36
  100. package/crates/naome-core/tests/workflow_agent.rs +233 -0
  101. package/crates/naome-core/tests/workflow_agent_support/mod.rs +159 -0
  102. package/crates/naome-core/tests/workflow_doctor.rs +21 -0
  103. package/installer/codex-hooks.js +121 -0
  104. package/installer/context.js +10 -0
  105. package/installer/filesystem.js +4 -0
  106. package/installer/flows.js +8 -4
  107. package/installer/harness-files.js +6 -0
  108. package/installer/install-plan.js +4 -0
  109. package/installer/main.js +1 -1
  110. package/installer/native.js +1 -1
  111. package/native/darwin-arm64/naome +0 -0
  112. package/native/linux-x64/naome +0 -0
  113. package/package.json +1 -1
  114. package/templates/naome-root/.codex/config.toml +2 -0
  115. package/templates/naome-root/.codex/hooks.json +70 -0
  116. package/templates/naome-root/.naome/bin/check-harness-health.js +8 -6
  117. package/templates/naome-root/.naome/bin/check-task-state.js +12 -7
  118. package/templates/naome-root/.naome/bin/codex-hook-io.js +122 -0
  119. package/templates/naome-root/.naome/bin/codex-hook-policy.js +180 -0
  120. package/templates/naome-root/.naome/bin/codex-hook-runtime.js +174 -0
  121. package/templates/naome-root/.naome/bin/codex-hook.js +6 -0
  122. package/templates/naome-root/.naome/bin/naome.js +35 -4
  123. package/templates/naome-root/.naome/manifest.json +12 -6
  124. package/templates/naome-root/.naome/repository-model.json +6 -0
  125. package/templates/naome-root/.naome/repository-quality.json +3 -1
  126. package/templates/naome-root/.naome/verification.json +15 -1
  127. package/templates/naome-root/AGENTS.md +38 -83
  128. package/templates/naome-root/docs/naome/agent-workflow.md +54 -18
  129. package/templates/naome-root/docs/naome/codex-hooks.md +82 -0
  130. package/templates/naome-root/docs/naome/context-economy.md +73 -0
  131. package/templates/naome-root/docs/naome/first-run.md +25 -14
  132. package/templates/naome-root/docs/naome/index.md +18 -10
  133. package/templates/naome-root/docs/naome/repository-model.md +92 -0
  134. package/templates/naome-root/docs/naome/repository-quality.md +47 -7
  135. package/templates/naome-root/docs/naome/repository-structure.md +10 -3
  136. package/templates/naome-root/docs/naome/task-ledger.md +71 -0
  137. package/templates/naome-root/docs/naome/testing.md +16 -3
@@ -1,3 +1,4 @@
1
+ mod context;
1
2
  mod decision;
2
3
  mod git;
3
4
  mod harness_health;
@@ -7,12 +8,18 @@ mod journal;
7
8
  mod models;
8
9
  mod paths;
9
10
  mod quality;
11
+ mod repository_model;
10
12
  mod route;
13
+ mod task_ledger;
11
14
  mod task_state;
12
15
  mod verification;
13
16
  mod verification_contract;
14
17
  mod workflow;
15
18
 
19
+ pub use context::{
20
+ select_context_for_changed_paths, select_context_for_prompt, ContextBudgetLedger,
21
+ ContextCapsule, ContextItem, ContextSelection,
22
+ };
16
23
  pub use decision::{evaluate_decision, format_decision, EvaluationOptions};
17
24
  pub use harness_health::{validate_harness_health, HarnessHealthOptions};
18
25
  pub use install_plan::{install_plan, InstallPlan};
@@ -21,15 +28,27 @@ pub use intent::{evaluate_intent, format_intent, IntentDecision, PromptEvidence}
21
28
  pub use journal::{append_task_journal, TaskJournalEntry};
22
29
  pub use models::{Decision, NaomeError};
23
30
  pub use quality::{
24
- check_repository_quality, check_semantic_legacy, explain_repository_structure,
25
- clear_quality_cache, init_repository_quality, init_repository_quality_with_mode,
26
- plan_quality_cleanup, quality_cache_status, route_quality_cleanup,
27
- semantic_route_for_finding, QualityCacheStatus, QualityCleanupPlan, QualityCleanupRoute,
28
- QualityCleanupTask, QualityInitMode, QualityInitResult, QualityMode, QualityReport,
31
+ check_repository_quality, check_repository_quality_paths, check_semantic_legacy,
32
+ check_semantic_legacy_paths,
33
+ clear_quality_cache, explain_repository_structure, init_repository_quality,
34
+ init_repository_quality_with_mode, plan_quality_cleanup, quality_cache_status,
35
+ reconcile_repository_quality, route_quality_cleanup, semantic_route_for_finding,
36
+ QualityCacheStatus, QualityCleanupPlan, QualityCleanupRoute, QualityCleanupTask,
37
+ QualityInitMode, QualityInitResult, QualityMode, QualityReconcileReport, QualityReport,
29
38
  QualitySummary, QualityViolation, RepositoryQualityConfig, RepositoryStructureConfig,
30
39
  SemanticFinding, SemanticReport, StructurePathExplanation,
31
40
  };
41
+ pub use repository_model::{
42
+ explain_repository_model_path, refresh_repository_model, repository_model_drift,
43
+ RepositoryEntity, RepositoryFact, RepositoryModel, RepositoryModelDrift,
44
+ RepositoryModelRefresh, RepositoryPathExplanation, RepositoryPathFact, RepositoryRoot,
45
+ RepositoryVerificationCheck, RepositoryWorldSignal,
46
+ };
32
47
  pub use route::{evaluate_route, explain_route, ExplainDecision, RouteDecision, RouteOptions};
48
+ pub use task_ledger::{
49
+ migrate_task_state_to_ledger, read_task_state_projection, render_task_state_from_ledger,
50
+ TaskLedgerProjection, TaskLedgerStatus,
51
+ };
33
52
  pub use task_state::{
34
53
  completed_task_commit_paths, validate_task_state, TaskStateMode, TaskStateOptions,
35
54
  TaskStateReport,
@@ -37,9 +56,13 @@ pub use task_state::{
37
56
  pub use verification::seed_builtin_verification_checks;
38
57
  pub use verification_contract::validate_verification_contract;
39
58
  pub use workflow::{
40
- classify_mutations, doctor_report, refresh_integrity, safe_rg_args, summarize_command_output,
41
- tracked_process_report, validate_read_boundaries, validate_search_command,
42
- verification_phase_plan, CommandCheckResult, CommandOutputSummary, DoctorReport, DoctorSection,
43
- IntegrityRefreshReport, MutationClassification, ProcessReport, ReadActivity,
44
- RepositoryPolicySection, VerificationPhasePlan, WorkflowFinding,
59
+ agent_run_plan, classify_mutations, context_delta_report, decision_gate, doctor_report,
60
+ edit_session_watchdog, proof_plan_for_task, refresh_integrity, repository_capability_graph,
61
+ safe_rg_args, summarize_command_output, tracked_process_report, validate_read_boundaries,
62
+ validate_search_command, verification_phase_plan, AgentRunPlan, CapabilityGraph,
63
+ CapabilityRoot, CommandCheckResult, CommandOutputSummary, ContextDeltaReport, DecisionGate,
64
+ DoctorReport, DoctorSection, EditSessionWatchdog, ExecutionPlanLedger, ExecutionPlanStep,
65
+ IntegrityRefreshReport, MutationClassification, ProcessReport, ProofPlan, ReadActivity,
66
+ RepositoryCapability, RepositoryPolicySection, VerificationEdge, VerificationPhasePlan,
67
+ WorkflowFinding,
45
68
  };
@@ -0,0 +1,131 @@
1
+ use super::adapters::{path_rule, test_file_limits};
2
+ use super::types::{QualityLimitOverrides, QualityPathRule};
3
+
4
+ pub(super) fn swift_path_rules() -> Vec<QualityPathRule> {
5
+ vec![path_rule(
6
+ "swift-source",
7
+ &["**/*.swift"],
8
+ source_limits(450, 300, 180, 100, 30, 10, 0.9),
9
+ &[],
10
+ )]
11
+ }
12
+
13
+ pub(super) fn xctest_path_rules() -> Vec<QualityPathRule> {
14
+ vec![path_rule(
15
+ "xctest-tests",
16
+ &[
17
+ "**/*Tests.swift",
18
+ "**/*UITests.swift",
19
+ "Tests/**/*.swift",
20
+ "**/Tests/**/*.swift",
21
+ "**/*Tests/**/*.swift",
22
+ "**/*UITests/**/*.swift",
23
+ ],
24
+ test_file_limits(80),
25
+ &[],
26
+ )]
27
+ }
28
+
29
+ pub(super) fn swiftui_path_rules() -> Vec<QualityPathRule> {
30
+ vec![path_rule(
31
+ "swiftui-views",
32
+ &[
33
+ "**/*View.swift",
34
+ "**/Views/**/*.swift",
35
+ "**/Preview Content/**",
36
+ ],
37
+ source_limits(360, 240, 160, 80, 24, 10, 0.92),
38
+ &[],
39
+ )]
40
+ }
41
+
42
+ pub(super) fn ios_app_structure_path_rules() -> Vec<QualityPathRule> {
43
+ vec![path_rule(
44
+ "ios-app-entrypoints",
45
+ &[
46
+ "**/*App.swift",
47
+ "**/AppDelegate.swift",
48
+ "**/SceneDelegate.swift",
49
+ "**/Info.plist",
50
+ "**/*.entitlements",
51
+ ],
52
+ source_limits(300, 220, 140, 80, 20, 10, 0.92),
53
+ &[],
54
+ )]
55
+ }
56
+
57
+ pub(super) fn swift_package_path_rules() -> Vec<QualityPathRule> {
58
+ vec![path_rule(
59
+ "swift-package-layout",
60
+ &["Package.swift", "Sources/**/*.swift", "Tests/**/*.swift"],
61
+ source_limits(450, 300, 180, 100, 30, 10, 0.9),
62
+ &[],
63
+ )]
64
+ }
65
+
66
+ pub(super) fn ios_resource_path_rules() -> Vec<QualityPathRule> {
67
+ vec![path_rule(
68
+ "ios-resources",
69
+ &[
70
+ "**/*.xcassets/**",
71
+ "**/*.strings",
72
+ "**/*.stringsdict",
73
+ "**/*.plist",
74
+ "**/*.entitlements",
75
+ "**/*.storyboard",
76
+ "**/*.xib",
77
+ ],
78
+ source_limits(700, 350, 250, 120, 80, 14, 0.96),
79
+ &["top-level-symbols", "function-length"],
80
+ )]
81
+ }
82
+
83
+ pub(super) fn generated_ios_path_rules() -> Vec<QualityPathRule> {
84
+ vec![path_rule(
85
+ "generated-ios",
86
+ GENERATED_IOS_PATHS,
87
+ source_limits(2_000, 2_000, 2_000, 300, 300, 30, 1.0),
88
+ &[
89
+ "file-length",
90
+ "new-file-length",
91
+ "diff-size",
92
+ "function-length",
93
+ "top-level-symbols",
94
+ "duplicate-blocks",
95
+ "near-duplicate-functions",
96
+ ],
97
+ )]
98
+ }
99
+
100
+ pub(super) const GENERATED_IOS_PATHS: &[&str] = &[
101
+ "Generated/**",
102
+ "**/Generated/**",
103
+ "SwiftGen/**",
104
+ "**/SwiftGen/**",
105
+ "Sourcery/**",
106
+ "**/Sourcery/**",
107
+ "**/*.generated.swift",
108
+ "**/*.pb.swift",
109
+ "**/*.grpc.swift",
110
+ "**/R.generated.swift",
111
+ ];
112
+
113
+ fn source_limits(
114
+ max_file_lines: usize,
115
+ max_new_file_lines: usize,
116
+ max_diff_added_lines: usize,
117
+ max_function_lines: usize,
118
+ max_top_level_symbols: usize,
119
+ duplicate_block_lines: usize,
120
+ near_duplicate_similarity: f64,
121
+ ) -> QualityLimitOverrides {
122
+ QualityLimitOverrides {
123
+ max_file_lines: Some(max_file_lines),
124
+ max_new_file_lines: Some(max_new_file_lines),
125
+ max_diff_added_lines: Some(max_diff_added_lines),
126
+ max_function_lines: Some(max_function_lines),
127
+ max_top_level_symbols: Some(max_top_level_symbols),
128
+ duplicate_block_lines: Some(duplicate_block_lines),
129
+ near_duplicate_similarity: Some(near_duplicate_similarity),
130
+ }
131
+ }
@@ -23,6 +23,25 @@ impl<'a> RepoSignals<'a> {
23
23
  .iter()
24
24
  .any(|path| extensions.iter().any(|extension| path.ends_with(extension)))
25
25
  }
26
+
27
+ pub(crate) fn has_path_containing(&self, fragments: &[&str]) -> bool {
28
+ self.paths.iter().any(|path| {
29
+ let lower = path.to_ascii_lowercase();
30
+ fragments.iter().any(|fragment| lower.contains(fragment))
31
+ })
32
+ }
33
+
34
+ pub(crate) fn has_file_name(&self, names: &[&str]) -> bool {
35
+ self.paths.iter().any(|path| {
36
+ let lower = path.to_ascii_lowercase();
37
+ path.rsplit('/').next().is_some_and(|file_name| {
38
+ names
39
+ .iter()
40
+ .any(|name| file_name.eq_ignore_ascii_case(name))
41
+ || names.iter().any(|name| lower.ends_with(name))
42
+ })
43
+ })
44
+ }
26
45
  }
27
46
 
28
47
  pub(crate) trait AdapterDescriptor {
@@ -87,3 +106,51 @@ pub(crate) fn detects_javascript_typescript_project(signals: &RepoSignals<'_>) -
87
106
  signals.has_manifest("package.json")
88
107
  || signals.has_extension(&[".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"])
89
108
  }
109
+
110
+ pub(crate) fn detects_swift_project(signals: &RepoSignals<'_>) -> bool {
111
+ signals.has_manifest("Package.swift") || signals.has_extension(&[".swift"])
112
+ }
113
+
114
+ pub(crate) fn detects_xcode_project(signals: &RepoSignals<'_>) -> bool {
115
+ signals.has_path_containing(&[".xcodeproj/", ".xcworkspace/"])
116
+ }
117
+
118
+ pub(crate) fn detects_xctest_project(signals: &RepoSignals<'_>) -> bool {
119
+ signals.has_path_containing(&["tests/"])
120
+ && signals.has_file_name(&["tests.swift", "uitests.swift"])
121
+ }
122
+
123
+ pub(crate) fn detects_swiftui_project(signals: &RepoSignals<'_>) -> bool {
124
+ signals.has_file_name(&["view.swift", "app.swift"])
125
+ || signals.has_path_containing(&["preview content/"])
126
+ }
127
+
128
+ pub(crate) fn detects_ios_app_structure_project(signals: &RepoSignals<'_>) -> bool {
129
+ detects_xcode_project(signals)
130
+ || signals.has_file_name(&["appdelegate.swift", "scenedelegate.swift", "info.plist"])
131
+ || signals.has_path_containing(&[".xcassets/"])
132
+ }
133
+
134
+ pub(crate) fn detects_swift_package_project(signals: &RepoSignals<'_>) -> bool {
135
+ signals.has_manifest("Package.swift")
136
+ || signals.has_path_containing(&["sources/", "tests/"])
137
+ && signals.has_extension(&[".swift"])
138
+ }
139
+
140
+ pub(crate) fn detects_ios_resources_project(signals: &RepoSignals<'_>) -> bool {
141
+ signals.has_path_containing(&[".xcassets/"])
142
+ || signals.has_extension(&[
143
+ ".strings",
144
+ ".stringsdict",
145
+ ".plist",
146
+ ".entitlements",
147
+ ".storyboard",
148
+ ".xib",
149
+ ])
150
+ }
151
+
152
+ pub(crate) fn detects_generated_ios_project(signals: &RepoSignals<'_>) -> bool {
153
+ signals.has_path_containing(&["generated/", "swiftgen/", "sourcery/"])
154
+ || signals.has_file_name(&["r.generated.swift"])
155
+ || signals.has_extension(&[".generated.swift", ".pb.swift", ".grpc.swift"])
156
+ }
@@ -1,8 +1,12 @@
1
1
  use crate::models::NaomeError;
2
2
 
3
+ use super::adapter_ios;
3
4
  use super::adapter_support::{
4
- detected_ids, detects_javascript_typescript_project, detects_rust_project, extend_unique,
5
- find_adapter_by_id, validate_ids, AdapterDescriptor, RepoSignals,
5
+ detected_ids, detects_generated_ios_project, detects_ios_app_structure_project,
6
+ detects_ios_resources_project, detects_javascript_typescript_project, detects_rust_project,
7
+ detects_swift_package_project, detects_swift_project, detects_swiftui_project,
8
+ detects_xcode_project, detects_xctest_project, extend_unique, find_adapter_by_id, validate_ids,
9
+ AdapterDescriptor, RepoSignals,
6
10
  };
7
11
  use super::types::{QualityLimitOverrides, QualityPathRule, RepositoryQualityConfig};
8
12
 
@@ -49,21 +53,76 @@ pub(crate) fn validate_adapter_ids(ids: &[String]) -> Result<(), NaomeError> {
49
53
  validate_ids(ids, registry(), CONFIG_PATH)
50
54
  }
51
55
 
56
+ const QUALITY_ADAPTERS: &[QualityAdapter] = &[
57
+ QualityAdapter {
58
+ id: "rust",
59
+ generated_paths: &[],
60
+ detect: detects_rust_project,
61
+ path_rules: rust_path_rules,
62
+ },
63
+ QualityAdapter {
64
+ id: "javascript-typescript",
65
+ generated_paths: &["coverage/**", "**/coverage/**", ".next/**", "**/.next/**"],
66
+ detect: detects_javascript_typescript_project,
67
+ path_rules: javascript_typescript_path_rules,
68
+ },
69
+ QualityAdapter {
70
+ id: "swift",
71
+ generated_paths: &[],
72
+ detect: detects_swift_project,
73
+ path_rules: adapter_ios::swift_path_rules,
74
+ },
75
+ QualityAdapter {
76
+ id: "xcode",
77
+ generated_paths: &[
78
+ "DerivedData/**",
79
+ "**/DerivedData/**",
80
+ "**/xcuserdata/**",
81
+ "**/*.xcuserstate",
82
+ ],
83
+ detect: detects_xcode_project,
84
+ path_rules: empty_path_rules,
85
+ },
86
+ QualityAdapter {
87
+ id: "xctest",
88
+ generated_paths: &[],
89
+ detect: detects_xctest_project,
90
+ path_rules: adapter_ios::xctest_path_rules,
91
+ },
92
+ QualityAdapter {
93
+ id: "swiftui",
94
+ generated_paths: &["**/Preview Content/**"],
95
+ detect: detects_swiftui_project,
96
+ path_rules: adapter_ios::swiftui_path_rules,
97
+ },
98
+ QualityAdapter {
99
+ id: "ios-app-structure",
100
+ generated_paths: &[],
101
+ detect: detects_ios_app_structure_project,
102
+ path_rules: adapter_ios::ios_app_structure_path_rules,
103
+ },
104
+ QualityAdapter {
105
+ id: "swift-package",
106
+ generated_paths: &[],
107
+ detect: detects_swift_package_project,
108
+ path_rules: adapter_ios::swift_package_path_rules,
109
+ },
110
+ QualityAdapter {
111
+ id: "ios-resources",
112
+ generated_paths: &[],
113
+ detect: detects_ios_resources_project,
114
+ path_rules: adapter_ios::ios_resource_path_rules,
115
+ },
116
+ QualityAdapter {
117
+ id: "generated-ios",
118
+ generated_paths: adapter_ios::GENERATED_IOS_PATHS,
119
+ detect: detects_generated_ios_project,
120
+ path_rules: adapter_ios::generated_ios_path_rules,
121
+ },
122
+ ];
123
+
52
124
  fn registry() -> &'static [QualityAdapter] {
53
- &[
54
- QualityAdapter {
55
- id: "rust",
56
- generated_paths: &[],
57
- detect: detects_rust_project,
58
- path_rules: rust_path_rules,
59
- },
60
- QualityAdapter {
61
- id: "javascript-typescript",
62
- generated_paths: &["coverage/**", "**/coverage/**", ".next/**", "**/.next/**"],
63
- detect: detects_javascript_typescript_project,
64
- path_rules: javascript_typescript_path_rules,
65
- },
66
- ]
125
+ QUALITY_ADAPTERS
67
126
  }
68
127
 
69
128
  fn rust_path_rules() -> Vec<QualityPathRule> {
@@ -84,6 +143,10 @@ fn javascript_typescript_path_rules() -> Vec<QualityPathRule> {
84
143
  }]
85
144
  }
86
145
 
146
+ fn empty_path_rules() -> Vec<QualityPathRule> {
147
+ Vec::new()
148
+ }
149
+
87
150
  fn javascript_typescript_test_paths() -> Vec<String> {
88
151
  let mut paths = Vec::new();
89
152
  for marker in ["test", "spec"] {
@@ -100,7 +163,7 @@ fn javascript_typescript_test_paths() -> Vec<String> {
100
163
  paths
101
164
  }
102
165
 
103
- fn test_file_limits(max_top_level_symbols: usize) -> QualityLimitOverrides {
166
+ pub(super) fn test_file_limits(max_top_level_symbols: usize) -> QualityLimitOverrides {
104
167
  QualityLimitOverrides {
105
168
  max_file_lines: Some(650),
106
169
  max_diff_added_lines: Some(220),
@@ -112,7 +175,7 @@ fn test_file_limits(max_top_level_symbols: usize) -> QualityLimitOverrides {
112
175
  }
113
176
  }
114
177
 
115
- fn path_rule(
178
+ pub(super) fn path_rule(
116
179
  id: &str,
117
180
  paths: &[&str],
118
181
  limits: QualityLimitOverrides,
@@ -91,15 +91,13 @@ impl QualityCache {
91
91
  }
92
92
 
93
93
  fn entry_path(&self, path: &str, content_hash: &str) -> PathBuf {
94
- self.root
95
- .join(CACHE_RELATIVE_PATH)
96
- .join(stable_key(&[
97
- env!("CARGO_PKG_VERSION"),
98
- &self.config_hash,
99
- ADAPTER_VERSION,
100
- path,
101
- content_hash,
102
- ]))
94
+ self.root.join(CACHE_RELATIVE_PATH).join(stable_key(&[
95
+ env!("CARGO_PKG_VERSION"),
96
+ &self.config_hash,
97
+ ADAPTER_VERSION,
98
+ path,
99
+ content_hash,
100
+ ]))
103
101
  }
104
102
  }
105
103
 
@@ -18,13 +18,10 @@ impl QualityCheck for DuplicateBlockCheck {
18
18
  return;
19
19
  }
20
20
  let mut occurrences: HashMap<String, Vec<DuplicateOccurrence>> = HashMap::new();
21
- for file in context
22
- .comparison_candidate_files()
23
- .filter(|file| {
24
- is_code_like_path(&file.path)
25
- && context.config.check_enabled_for_path(self.id(), &file.path)
26
- })
27
- {
21
+ for file in context.comparison_candidate_files().filter(|file| {
22
+ is_code_like_path(&file.path)
23
+ && context.config.check_enabled_for_path(self.id(), &file.path)
24
+ }) {
28
25
  let window = context.limits_for(&file.path).duplicate_block_lines;
29
26
  if file.normalized_lines.len() < window {
30
27
  continue;
@@ -15,6 +15,12 @@ pub fn config_relative_path() -> &'static str {
15
15
  }
16
16
 
17
17
  pub fn read_config(root: &Path) -> Result<RepositoryQualityConfig, NaomeError> {
18
+ let config = read_policy_config(root)?;
19
+ validate_config(&config)?;
20
+ apply_enabled_adapters(config)
21
+ }
22
+
23
+ pub(super) fn read_policy_config(root: &Path) -> Result<RepositoryQualityConfig, NaomeError> {
18
24
  let path = root.join(CONFIG_RELATIVE_PATH);
19
25
  let config = if path.is_file() {
20
26
  serde_json::from_str(&fs::read_to_string(path)?)?
@@ -22,7 +28,20 @@ pub fn read_config(root: &Path) -> Result<RepositoryQualityConfig, NaomeError> {
22
28
  generated_config(root)?
23
29
  };
24
30
  validate_config(&config)?;
25
- apply_enabled_adapters(config)
31
+ Ok(config)
32
+ }
33
+
34
+ pub(super) fn write_policy_config(
35
+ root: &Path,
36
+ config: &RepositoryQualityConfig,
37
+ ) -> Result<(), NaomeError> {
38
+ let path = root.join(CONFIG_RELATIVE_PATH);
39
+ if let Some(parent) = path.parent() {
40
+ fs::create_dir_all(parent)?;
41
+ }
42
+ let content = serde_json::to_string_pretty(config)?;
43
+ fs::write(path, format!("{content}\n"))?;
44
+ Ok(())
26
45
  }
27
46
 
28
47
  pub fn write_default_config_if_missing(root: &Path) -> Result<bool, NaomeError> {
@@ -34,8 +53,7 @@ pub fn write_default_config_if_missing(root: &Path) -> Result<bool, NaomeError>
34
53
  if let Some(parent) = path.parent() {
35
54
  fs::create_dir_all(parent)?;
36
55
  }
37
- let content = serde_json::to_string_pretty(&generated_config(root)?)?;
38
- fs::write(path, format!("{content}\n"))?;
56
+ write_policy_config(root, &generated_config(root)?)?;
39
57
  Ok(true)
40
58
  }
41
59