@lamentis/naome 1.2.1 → 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 (155) hide show
  1. package/Cargo.lock +2 -2
  2. package/README.md +117 -47
  3. package/bin/naome.js +65 -12
  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 +12 -2
  7. package/crates/naome-cli/src/main.rs +78 -29
  8. package/crates/naome-cli/src/quality_commands.rs +238 -34
  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 +120 -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/git.rs +4 -2
  22. package/crates/naome-core/src/install_plan.rs +20 -0
  23. package/crates/naome-core/src/journal.rs +2 -7
  24. package/crates/naome-core/src/lib.rs +35 -8
  25. package/crates/naome-core/src/quality/adapter_ios.rs +131 -0
  26. package/crates/naome-core/src/quality/adapter_support.rs +67 -0
  27. package/crates/naome-core/src/quality/adapters.rs +81 -18
  28. package/crates/naome-core/src/quality/baseline.rs +8 -0
  29. package/crates/naome-core/src/quality/cache.rs +151 -0
  30. package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +19 -8
  31. package/crates/naome-core/src/quality/checks/near_duplicates.rs +4 -2
  32. package/crates/naome-core/src/quality/checks.rs +7 -8
  33. package/crates/naome-core/src/quality/cleanup.rs +36 -3
  34. package/crates/naome-core/src/quality/config.rs +21 -3
  35. package/crates/naome-core/src/quality/mod.rs +189 -10
  36. package/crates/naome-core/src/quality/reconcile.rs +138 -0
  37. package/crates/naome-core/src/quality/reconcile_anchors.rs +64 -0
  38. package/crates/naome-core/src/quality/scanner/analysis/normalize.rs +78 -0
  39. package/crates/naome-core/src/quality/scanner/analysis.rs +175 -0
  40. package/crates/naome-core/src/quality/scanner/repo_paths.rs +39 -3
  41. package/crates/naome-core/src/quality/scanner.rs +235 -217
  42. package/crates/naome-core/src/quality/semantic/checks.rs +151 -0
  43. package/crates/naome-core/src/quality/semantic/extract.rs +158 -0
  44. package/crates/naome-core/src/quality/semantic/model.rs +85 -0
  45. package/crates/naome-core/src/quality/semantic/route.rs +52 -0
  46. package/crates/naome-core/src/quality/semantic.rs +68 -0
  47. package/crates/naome-core/src/quality/structure/adapter_ios.rs +149 -0
  48. package/crates/naome-core/src/quality/structure/adapters.rs +60 -42
  49. package/crates/naome-core/src/quality/structure/checks/directory.rs +13 -21
  50. package/crates/naome-core/src/quality/structure/checks.rs +1 -1
  51. package/crates/naome-core/src/quality/structure/classify/roles.rs +51 -5
  52. package/crates/naome-core/src/quality/structure/classify.rs +52 -0
  53. package/crates/naome-core/src/quality/structure/config.rs +24 -3
  54. package/crates/naome-core/src/quality/structure/mod.rs +5 -2
  55. package/crates/naome-core/src/quality/structure/model.rs +8 -1
  56. package/crates/naome-core/src/quality/types.rs +59 -2
  57. package/crates/naome-core/src/repository_model/detect.rs +188 -0
  58. package/crates/naome-core/src/repository_model/explain.rs +121 -0
  59. package/crates/naome-core/src/repository_model/path_scan.rs +67 -0
  60. package/crates/naome-core/src/repository_model/path_support.rs +59 -0
  61. package/crates/naome-core/src/repository_model/types.rs +152 -0
  62. package/crates/naome-core/src/repository_model/world.rs +48 -0
  63. package/crates/naome-core/src/repository_model/world_adapters.rs +145 -0
  64. package/crates/naome-core/src/repository_model/world_path_facts.rs +55 -0
  65. package/crates/naome-core/src/repository_model/world_paths.rs +168 -0
  66. package/crates/naome-core/src/repository_model.rs +164 -0
  67. package/crates/naome-core/src/route/builtin_checks.rs +41 -16
  68. package/crates/naome-core/src/task_ledger/import.rs +142 -0
  69. package/crates/naome-core/src/task_ledger/model.rs +13 -0
  70. package/crates/naome-core/src/task_ledger/proof_record.rs +52 -0
  71. package/crates/naome-core/src/task_ledger/read.rs +118 -0
  72. package/crates/naome-core/src/task_ledger/render.rs +55 -0
  73. package/crates/naome-core/src/task_ledger/write.rs +38 -0
  74. package/crates/naome-core/src/task_ledger.rs +48 -0
  75. package/crates/naome-core/src/task_state/api.rs +4 -2
  76. package/crates/naome-core/src/task_state/completed_refresh.rs +5 -16
  77. package/crates/naome-core/src/task_state/diff.rs +2 -2
  78. package/crates/naome-core/src/task_state/evidence.rs +8 -3
  79. package/crates/naome-core/src/task_state/mod.rs +1 -1
  80. package/crates/naome-core/src/task_state/progress.rs +13 -0
  81. package/crates/naome-core/src/task_state/proof_model.rs +8 -8
  82. package/crates/naome-core/src/task_state/repair.rs +2 -2
  83. package/crates/naome-core/src/task_state/task_diff_api.rs +9 -18
  84. package/crates/naome-core/src/task_state/types.rs +24 -0
  85. package/crates/naome-core/src/verification.rs +29 -18
  86. package/crates/naome-core/src/workflow/agent/capability.rs +194 -0
  87. package/crates/naome-core/src/workflow/agent/context_delta.rs +42 -0
  88. package/crates/naome-core/src/workflow/agent/decision.rs +32 -0
  89. package/crates/naome-core/src/workflow/agent/execution.rs +80 -0
  90. package/crates/naome-core/src/workflow/agent/proof.rs +24 -0
  91. package/crates/naome-core/src/workflow/agent/support.rs +58 -0
  92. package/crates/naome-core/src/workflow/agent/watchdog.rs +47 -0
  93. package/crates/naome-core/src/workflow/agent.rs +34 -0
  94. package/crates/naome-core/src/workflow/agent_types.rs +105 -0
  95. package/crates/naome-core/src/workflow/doctor.rs +183 -0
  96. package/crates/naome-core/src/workflow/mod.rs +13 -0
  97. package/crates/naome-core/src/workflow/mutation.rs +1 -2
  98. package/crates/naome-core/src/workflow/output.rs +8 -2
  99. package/crates/naome-core/src/workflow/phase_inference.rs +1 -1
  100. package/crates/naome-core/tests/context.rs +99 -0
  101. package/crates/naome-core/tests/harness_health.rs +4 -0
  102. package/crates/naome-core/tests/install_plan.rs +14 -0
  103. package/crates/naome-core/tests/quality.rs +190 -5
  104. package/crates/naome-core/tests/quality_performance.rs +268 -0
  105. package/crates/naome-core/tests/quality_structure_adapters.rs +39 -0
  106. package/crates/naome-core/tests/quality_structure_policy.rs +19 -0
  107. package/crates/naome-core/tests/repo_support/mod.rs +5 -1
  108. package/crates/naome-core/tests/repo_support/verification_values.rs +55 -0
  109. package/crates/naome-core/tests/repository_model.rs +281 -0
  110. package/crates/naome-core/tests/route_user_diff.rs +59 -7
  111. package/crates/naome-core/tests/semantic_legacy.rs +174 -0
  112. package/crates/naome-core/tests/task_ledger.rs +328 -0
  113. package/crates/naome-core/tests/task_state.rs +28 -0
  114. package/crates/naome-core/tests/verification.rs +29 -36
  115. package/crates/naome-core/tests/workflow_agent.rs +233 -0
  116. package/crates/naome-core/tests/workflow_agent_support/mod.rs +159 -0
  117. package/crates/naome-core/tests/workflow_doctor.rs +45 -0
  118. package/crates/naome-core/tests/workflow_policy.rs +6 -1
  119. package/installer/codex-hooks.js +121 -0
  120. package/installer/context.js +10 -0
  121. package/installer/filesystem.js +4 -0
  122. package/installer/flows.js +8 -4
  123. package/installer/git-boundary.js +1 -0
  124. package/installer/harness-files.js +6 -0
  125. package/installer/install-plan.js +4 -0
  126. package/installer/main.js +1 -1
  127. package/installer/native.js +1 -1
  128. package/native/darwin-arm64/naome +0 -0
  129. package/native/linux-x64/naome +0 -0
  130. package/package.json +1 -1
  131. package/templates/naome-root/.codex/config.toml +2 -0
  132. package/templates/naome-root/.codex/hooks.json +70 -0
  133. package/templates/naome-root/.naome/bin/check-harness-health.js +8 -6
  134. package/templates/naome-root/.naome/bin/check-task-state.js +12 -7
  135. package/templates/naome-root/.naome/bin/codex-hook-io.js +122 -0
  136. package/templates/naome-root/.naome/bin/codex-hook-policy.js +180 -0
  137. package/templates/naome-root/.naome/bin/codex-hook-runtime.js +174 -0
  138. package/templates/naome-root/.naome/bin/codex-hook.js +6 -0
  139. package/templates/naome-root/.naome/bin/naome.js +45 -7
  140. package/templates/naome-root/.naome/manifest.json +12 -6
  141. package/templates/naome-root/.naome/repository-model.json +6 -0
  142. package/templates/naome-root/.naome/repository-quality.json +3 -1
  143. package/templates/naome-root/.naome/verification.json +15 -1
  144. package/templates/naome-root/.naomeignore +1 -0
  145. package/templates/naome-root/AGENTS.md +38 -83
  146. package/templates/naome-root/docs/naome/agent-workflow.md +66 -28
  147. package/templates/naome-root/docs/naome/codex-hooks.md +82 -0
  148. package/templates/naome-root/docs/naome/context-economy.md +73 -0
  149. package/templates/naome-root/docs/naome/first-run.md +25 -14
  150. package/templates/naome-root/docs/naome/index.md +18 -10
  151. package/templates/naome-root/docs/naome/repository-model.md +92 -0
  152. package/templates/naome-root/docs/naome/repository-quality.md +104 -5
  153. package/templates/naome-root/docs/naome/repository-structure.md +10 -3
  154. package/templates/naome-root/docs/naome/task-ledger.md +71 -0
  155. package/templates/naome-root/docs/naome/testing.md +16 -3
@@ -0,0 +1,34 @@
1
+ mod capability;
2
+ mod context_delta;
3
+ mod decision;
4
+ mod execution;
5
+ mod proof;
6
+ mod support;
7
+ mod watchdog;
8
+
9
+ use std::path::Path;
10
+
11
+ use crate::models::NaomeError;
12
+
13
+ use super::agent_types::AgentRunPlan;
14
+ use super::phases::CommandCheckResult;
15
+
16
+ pub use capability::repository_capability_graph;
17
+ pub use context_delta::context_delta_report;
18
+ pub use decision::decision_gate;
19
+ pub use execution::execution_plan;
20
+ pub use proof::proof_plan_for_task;
21
+ pub use watchdog::edit_session_watchdog;
22
+
23
+ pub fn agent_run_plan(root: &Path) -> Result<AgentRunPlan, NaomeError> {
24
+ let changed_paths = support::changed_paths(root)?;
25
+ Ok(AgentRunPlan {
26
+ schema: "naome.agent-run-plan.v1".to_string(),
27
+ execution_plan: execution_plan(root, &changed_paths)?,
28
+ context_delta: context_delta_report(root, &[])?,
29
+ proof_plan: proof_plan_for_task(root, &[] as &[CommandCheckResult])?,
30
+ capability_graph: repository_capability_graph(root)?,
31
+ edit_watchdog: edit_session_watchdog(root, &changed_paths)?,
32
+ decision_gate: decision_gate(root)?,
33
+ })
34
+ }
@@ -0,0 +1,105 @@
1
+ use serde::{Deserialize, Serialize};
2
+
3
+ use super::types::WorkflowFinding;
4
+
5
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6
+ #[serde(rename_all = "camelCase")]
7
+ pub struct AgentRunPlan {
8
+ pub schema: String,
9
+ pub execution_plan: ExecutionPlanLedger,
10
+ pub context_delta: ContextDeltaReport,
11
+ pub proof_plan: ProofPlan,
12
+ pub capability_graph: CapabilityGraph,
13
+ pub edit_watchdog: EditSessionWatchdog,
14
+ pub decision_gate: DecisionGate,
15
+ }
16
+
17
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18
+ #[serde(rename_all = "camelCase")]
19
+ pub struct ExecutionPlanLedger {
20
+ pub task_state: String,
21
+ pub changed_paths: Vec<String>,
22
+ pub steps: Vec<ExecutionPlanStep>,
23
+ }
24
+
25
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26
+ #[serde(rename_all = "camelCase")]
27
+ pub struct ExecutionPlanStep {
28
+ pub id: String,
29
+ pub phase: String,
30
+ pub paths: Vec<String>,
31
+ pub commands: Vec<String>,
32
+ pub reason_codes: Vec<String>,
33
+ }
34
+
35
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36
+ #[serde(rename_all = "camelCase")]
37
+ pub struct ContextDeltaReport {
38
+ pub schema: String,
39
+ pub reusable_context: Vec<String>,
40
+ pub stale_context: Vec<String>,
41
+ pub unread_required_context: Vec<String>,
42
+ pub reason_codes: Vec<String>,
43
+ }
44
+
45
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
46
+ #[serde(rename_all = "camelCase")]
47
+ pub struct ProofPlan {
48
+ pub schema: String,
49
+ pub recommended_check_ids: Vec<String>,
50
+ pub withheld_check_ids: Vec<String>,
51
+ pub evidence_paths: Vec<String>,
52
+ pub reason_codes: Vec<String>,
53
+ }
54
+
55
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56
+ #[serde(rename_all = "camelCase")]
57
+ pub struct CapabilityGraph {
58
+ pub schema: String,
59
+ pub capabilities: Vec<RepositoryCapability>,
60
+ pub roots: Vec<CapabilityRoot>,
61
+ pub verification_edges: Vec<VerificationEdge>,
62
+ }
63
+
64
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65
+ #[serde(rename_all = "camelCase")]
66
+ pub struct RepositoryCapability {
67
+ pub id: String,
68
+ pub kind: String,
69
+ pub value: String,
70
+ pub evidence: Vec<String>,
71
+ }
72
+
73
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
74
+ #[serde(rename_all = "camelCase")]
75
+ pub struct CapabilityRoot {
76
+ pub role: String,
77
+ pub path: String,
78
+ }
79
+
80
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
81
+ #[serde(rename_all = "camelCase")]
82
+ pub struct VerificationEdge {
83
+ pub check_id: String,
84
+ pub command: String,
85
+ pub evidence: Vec<String>,
86
+ }
87
+
88
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
89
+ #[serde(rename_all = "camelCase")]
90
+ pub struct EditSessionWatchdog {
91
+ pub schema: String,
92
+ pub touched_paths: Vec<String>,
93
+ pub next_commands: Vec<String>,
94
+ pub findings: Vec<WorkflowFinding>,
95
+ }
96
+
97
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
98
+ #[serde(rename_all = "camelCase")]
99
+ pub struct DecisionGate {
100
+ pub schema: String,
101
+ pub action: String,
102
+ pub reason_codes: Vec<String>,
103
+ pub human_options: Vec<String>,
104
+ pub next_action: String,
105
+ }
@@ -0,0 +1,183 @@
1
+ use std::fs;
2
+ use std::path::Path;
3
+
4
+ use serde::Serialize;
5
+
6
+ use crate::harness_health::{validate_harness_health, HarnessHealthOptions};
7
+ use crate::models::NaomeError;
8
+ use crate::repository_model_drift;
9
+ use crate::task_state::{validate_task_state, TaskStateMode, TaskStateOptions};
10
+ use crate::verification_contract::validate_verification_contract;
11
+
12
+ use super::phases::verification_phase_plan;
13
+
14
+ #[derive(Debug, Clone, Serialize)]
15
+ #[serde(rename_all = "camelCase")]
16
+ pub struct DoctorReport {
17
+ pub schema: String,
18
+ pub ok: bool,
19
+ pub harness_health: DoctorSection,
20
+ pub task_state: DoctorSection,
21
+ pub verification: DoctorSection,
22
+ pub repository_model: RepositoryPolicySection,
23
+ pub repository_quality: RepositoryPolicySection,
24
+ pub repository_structure: RepositoryPolicySection,
25
+ pub recommended_check_ids: Vec<String>,
26
+ pub withheld_check_ids: Vec<String>,
27
+ pub next_action: String,
28
+ }
29
+
30
+ #[derive(Debug, Clone, Serialize)]
31
+ #[serde(rename_all = "camelCase")]
32
+ pub struct DoctorSection {
33
+ pub status: String,
34
+ pub messages: Vec<String>,
35
+ }
36
+
37
+ #[derive(Debug, Clone, Serialize)]
38
+ #[serde(rename_all = "camelCase")]
39
+ pub struct RepositoryPolicySection {
40
+ pub config_present: bool,
41
+ pub baseline_present: bool,
42
+ pub status: String,
43
+ pub messages: Vec<String>,
44
+ }
45
+
46
+ pub fn doctor_report(root: &Path) -> Result<DoctorReport, NaomeError> {
47
+ let harness_errors = validate_harness_health(
48
+ root,
49
+ HarnessHealthOptions {
50
+ allow_missing_integrity: true,
51
+ allow_missing_archive: true,
52
+ ..HarnessHealthOptions::default()
53
+ },
54
+ )?;
55
+ let task_report = validate_task_state(
56
+ root,
57
+ TaskStateOptions {
58
+ mode: TaskStateMode::State,
59
+ harness_health: None,
60
+ },
61
+ )?;
62
+ let verification_errors = validate_verification_contract(root)?;
63
+ let phase_plan = verification_phase_plan(root, &[])?;
64
+
65
+ let repository_model = repository_model_section(root)?;
66
+ let repository_quality = policy_section(
67
+ root,
68
+ ".naome/repository-quality.json",
69
+ ".naome/repository-quality-baseline.json",
70
+ );
71
+ let repository_structure = policy_section(root, ".naome/repository-structure.json", "");
72
+
73
+ let harness_health = section(harness_errors);
74
+ let task_state = section(task_report.errors);
75
+ let verification = section(verification_errors);
76
+ let ok = harness_health.status == "ok"
77
+ && task_state.status == "ok"
78
+ && verification.status == "ok"
79
+ && repository_model.status == "ok"
80
+ && repository_quality.status == "ok"
81
+ && repository_structure.status == "ok";
82
+ let next_action = next_action(
83
+ &harness_health,
84
+ &task_state,
85
+ &verification,
86
+ &repository_model,
87
+ &repository_quality,
88
+ &repository_structure,
89
+ );
90
+
91
+ Ok(DoctorReport {
92
+ schema: "naome.doctor.v1".to_string(),
93
+ ok,
94
+ harness_health,
95
+ task_state,
96
+ verification,
97
+ repository_model,
98
+ repository_quality,
99
+ repository_structure,
100
+ recommended_check_ids: phase_plan.recommended_check_ids,
101
+ withheld_check_ids: phase_plan.withheld_check_ids,
102
+ next_action,
103
+ })
104
+ }
105
+
106
+ fn section(messages: Vec<String>) -> DoctorSection {
107
+ DoctorSection {
108
+ status: if messages.is_empty() { "ok" } else { "blocked" }.to_string(),
109
+ messages,
110
+ }
111
+ }
112
+
113
+ fn policy_section(root: &Path, config_path: &str, baseline_path: &str) -> RepositoryPolicySection {
114
+ let config_present =
115
+ fs::metadata(root.join(config_path)).is_ok_and(|metadata| metadata.is_file());
116
+ let baseline_present = baseline_path.is_empty()
117
+ || fs::metadata(root.join(baseline_path)).is_ok_and(|metadata| metadata.is_file());
118
+ RepositoryPolicySection {
119
+ config_present,
120
+ baseline_present,
121
+ status: if config_present && baseline_present {
122
+ "ok"
123
+ } else {
124
+ "missing"
125
+ }
126
+ .to_string(),
127
+ messages: Vec::new(),
128
+ }
129
+ }
130
+
131
+ fn repository_model_section(root: &Path) -> Result<RepositoryPolicySection, NaomeError> {
132
+ let drift = repository_model_drift(root)?;
133
+ let config_present = drift.model_present;
134
+ let status = if !config_present {
135
+ "missing"
136
+ } else if drift.stale {
137
+ "stale"
138
+ } else {
139
+ "ok"
140
+ };
141
+ let messages = if !config_present {
142
+ vec!["NAOME repository model is missing; run naome repo model --write.".to_string()]
143
+ } else {
144
+ drift.messages
145
+ };
146
+ Ok(RepositoryPolicySection {
147
+ config_present,
148
+ baseline_present: true,
149
+ status: status.to_string(),
150
+ messages,
151
+ })
152
+ }
153
+
154
+ fn next_action(
155
+ harness_health: &DoctorSection,
156
+ task_state: &DoctorSection,
157
+ verification: &DoctorSection,
158
+ repository_model: &RepositoryPolicySection,
159
+ repository_quality: &RepositoryPolicySection,
160
+ repository_structure: &RepositoryPolicySection,
161
+ ) -> String {
162
+ if task_state.status != "ok" {
163
+ return "Finish or resolve the active task before starting new work.".to_string();
164
+ }
165
+ if harness_health.status != "ok" {
166
+ return "Repair the NAOME harness before feature work.".to_string();
167
+ }
168
+ if verification.status != "ok" {
169
+ return "Fix .naome/verification.json before relying on gates.".to_string();
170
+ }
171
+ if repository_model.status == "stale" {
172
+ return "Run naome repo model --write to refresh deterministic repository facts."
173
+ .to_string();
174
+ }
175
+ if repository_model.status != "ok" {
176
+ return "Run naome repo model --write to seed deterministic repository facts.".to_string();
177
+ }
178
+ if repository_quality.status != "ok" || repository_structure.status != "ok" {
179
+ return "Run naome quality init or naome sync to seed repository quality policy."
180
+ .to_string();
181
+ }
182
+ "NAOME is ready for task work; follow the recommended verification phase order.".to_string()
183
+ }
@@ -1,3 +1,6 @@
1
+ mod agent;
2
+ mod agent_types;
3
+ mod doctor;
1
4
  mod integrity;
2
5
  mod integrity_normalize;
3
6
  mod integrity_support;
@@ -9,6 +12,16 @@ mod policy;
9
12
  mod processes;
10
13
  mod types;
11
14
 
15
+ pub use agent::{
16
+ agent_run_plan, context_delta_report, decision_gate, edit_session_watchdog,
17
+ proof_plan_for_task, repository_capability_graph,
18
+ };
19
+ pub use agent_types::{
20
+ AgentRunPlan, CapabilityGraph, CapabilityRoot, ContextDeltaReport, DecisionGate,
21
+ EditSessionWatchdog, ExecutionPlanLedger, ExecutionPlanStep, ProofPlan, RepositoryCapability,
22
+ VerificationEdge,
23
+ };
24
+ pub use doctor::{doctor_report, DoctorReport, DoctorSection, RepositoryPolicySection};
12
25
  pub use integrity::{refresh_integrity, IntegrityRefreshReport};
13
26
  pub use mutation::classify_mutations;
14
27
  pub use output::{summarize_command_output, CommandOutputSummary};
@@ -34,13 +34,12 @@ fn mutation_class(path: &str) -> &'static str {
34
34
  {
35
35
  return "local-only repair";
36
36
  }
37
- if path.starts_with("packages/naome/templates/") || path.starts_with(".naome/bin/") {
37
+ if path.starts_with(".naome/bin/") {
38
38
  return "harness template";
39
39
  }
40
40
  if path.ends_with(".tgz")
41
41
  || path.starts_with("dist/")
42
42
  || path.contains("/dist/")
43
- || path.starts_with("packages/naome/native/")
44
43
  || path.starts_with("native/")
45
44
  {
46
45
  return "release artifact";
@@ -71,6 +71,8 @@ fn is_relevant_line(line: &str) -> bool {
71
71
  "outside allowedpaths",
72
72
  "denied",
73
73
  "missing",
74
+ ".log",
75
+ "artifact",
74
76
  ]
75
77
  .iter()
76
78
  .any(|needle| lower.contains(needle))
@@ -86,8 +88,12 @@ fn collect_paths(lines: &[String]) -> Vec<String> {
86
88
  '"' | '\'' | '`' | ':' | ',' | ';' | '(' | ')' | '[' | ']'
87
89
  )
88
90
  });
89
- if looks_like_path(cleaned) {
90
- paths.insert(cleaned.replace('\\', "/"));
91
+ let path_token = cleaned
92
+ .split_once(':')
93
+ .map(|(path, _)| path)
94
+ .unwrap_or(cleaned);
95
+ if looks_like_path(path_token) {
96
+ paths.insert(path_token.replace('\\', "/"));
91
97
  }
92
98
  }
93
99
  }
@@ -54,7 +54,7 @@ fn inferred_phase<'a>(check: &'a CheckDefinition, release_gate_ids: &HashSet<&st
54
54
  if id == "diff-check" || command.contains("diff --check") {
55
55
  return "diff-check";
56
56
  }
57
- if id.contains("quality") {
57
+ if id.contains("quality") || id.contains("semantic") {
58
58
  return "quality";
59
59
  }
60
60
  if id.contains("health") || id.contains("task-state") || command.contains("check-task-state") {
@@ -0,0 +1,99 @@
1
+ mod repo_support;
2
+
3
+ use naome_core::{select_context_for_changed_paths, select_context_for_prompt};
4
+
5
+ use repo_support::{verification_value, TestRepo};
6
+
7
+ #[test]
8
+ fn changed_context_selects_touched_files_and_compact_quality_capsule() {
9
+ let repo = context_repo("context-changed-quality");
10
+ repo.write_file("packages/tool/src/quality/scanner.rs", "pub fn scan() {}\n");
11
+ repo.write_file("docs/naome/testing.md", "# Testing\n");
12
+ repo.commit_all("baseline");
13
+ repo.write_file(
14
+ "packages/tool/src/quality/scanner.rs",
15
+ "pub fn scan() {}\npub fn changed() {}\n",
16
+ );
17
+ repo.write_file("docs/naome/testing.md", "# Testing\n\nchanged\n");
18
+
19
+ let selection = select_context_for_changed_paths(repo.path()).unwrap();
20
+
21
+ assert_eq!(selection.schema, "naome.context-selection.v1");
22
+ assert_eq!(selection.mode, "changed");
23
+ assert_eq!(selection.capsule.id, "quality-work");
24
+ assert!(selection.required_context.iter().any(|item| {
25
+ item.path == "packages/tool/src/quality/scanner.rs" && item.reason == "changed_path"
26
+ }));
27
+ assert!(selection.commands.iter().any(|command| {
28
+ command == "node .naome/bin/naome.js quality check --path packages/tool/src/quality/scanner.rs"
29
+ }));
30
+ assert!(selection
31
+ .commands
32
+ .contains(&"node .naome/bin/naome.js quality check --changed".to_string()));
33
+ assert!(selection
34
+ .forbidden_context
35
+ .contains(&".naome/archive/**".to_string()));
36
+ assert!(selection.budget_ledger.selected_files < 6);
37
+ assert!(selection.budget_ledger.estimated_tokens > 0);
38
+ }
39
+
40
+ #[test]
41
+ fn prompt_context_uses_file_mentions_without_broad_markdown_context() {
42
+ let repo = context_repo("context-prompt-paths");
43
+ repo.write_file("packages/app/src/lib.rs", "pub fn app() {}\n");
44
+ repo.write_file("docs/naome/repository-quality.md", "# Quality\n");
45
+ repo.commit_all("baseline");
46
+
47
+ let selection = select_context_for_prompt(
48
+ repo.path(),
49
+ "Please update packages/app/src/lib.rs and run a path-scoped quality check.",
50
+ )
51
+ .unwrap();
52
+
53
+ assert_eq!(selection.mode, "prompt");
54
+ assert_eq!(selection.capsule.id, "source-work");
55
+ assert_eq!(
56
+ selection.required_context[0].path,
57
+ "packages/app/src/lib.rs"
58
+ );
59
+ assert!(!selection
60
+ .required_context
61
+ .iter()
62
+ .any(|item| item.path == "docs/naome/repository-quality.md"));
63
+ assert!(selection
64
+ .optional_context
65
+ .iter()
66
+ .any(|item| item.path == "docs/naome/repository-quality.md"));
67
+ }
68
+
69
+ #[test]
70
+ fn context_selection_reports_over_budget_when_many_paths_change() {
71
+ let repo = context_repo("context-budget");
72
+ for index in 0..20 {
73
+ repo.write_file(&format!("src/file_{index}.rs"), "pub fn before() {}\n");
74
+ }
75
+ repo.commit_all("baseline");
76
+ for index in 0..20 {
77
+ repo.write_file(&format!("src/file_{index}.rs"), "pub fn after() {}\n");
78
+ }
79
+
80
+ let selection = select_context_for_changed_paths(repo.path()).unwrap();
81
+
82
+ assert_eq!(selection.budget_ledger.selected_files, 12);
83
+ assert!(selection.budget_ledger.avoided_files >= 8);
84
+ assert!(selection
85
+ .budget_ledger
86
+ .reason_codes
87
+ .contains(&"context_file_budget_reached".to_string()));
88
+ }
89
+
90
+ fn context_repo(name: &str) -> TestRepo {
91
+ let repo = TestRepo::new(name);
92
+ repo.init_git();
93
+ repo.write_file(".naomeignore", ".naome/archive/\n.naome/cache/\n");
94
+ repo.write_naome_json(
95
+ "verification.json",
96
+ verification_value("ready", vec![], vec![]),
97
+ );
98
+ repo
99
+ }
@@ -18,7 +18,9 @@ const MACHINE_OWNED_PATHS: &[&str] = &[
18
18
  "docs/naome/index.md",
19
19
  "docs/naome/first-run.md",
20
20
  "docs/naome/agent-workflow.md",
21
+ "docs/naome/context-economy.md",
21
22
  "docs/naome/execution.md",
23
+ "docs/naome/task-ledger.md",
22
24
  "docs/naome/upgrade.md",
23
25
  ];
24
26
 
@@ -29,12 +31,14 @@ const PROJECT_OWNED_PATHS: &[&str] = &[
29
31
  ".naome/task-state.json",
30
32
  ".naome/upgrade-state.json",
31
33
  ".naome/verification.json",
34
+ ".naome/repository-model.json",
32
35
  ".naome/repository-quality.json",
33
36
  ".naome/repository-structure.json",
34
37
  ".naome/repository-quality-baseline.json",
35
38
  "docs/naome/architecture.md",
36
39
  "docs/naome/decisions.md",
37
40
  "docs/naome/repo-profile.md",
41
+ "docs/naome/repository-model.md",
38
42
  "docs/naome/repository-quality.md",
39
43
  "docs/naome/repository-structure.md",
40
44
  "docs/naome/security.md",
@@ -8,6 +8,7 @@ fn install_plan_marks_machine_docs_and_bins_local_only() {
8
8
  assert_eq!(plan.harness_version, "1.0.0");
9
9
  assert!(plan.machine_owned.contains(&"docs/naome/execution.md"));
10
10
  assert!(plan.project_owned.contains(&"docs/naome/architecture.md"));
11
+ assert!(!plan.project_owned.contains(&".naome/tasks/**"));
11
12
  assert!(plan
12
13
  .local_only_machine_owned
13
14
  .contains(&".naome/bin/check-task-state.js"));
@@ -18,6 +19,17 @@ fn install_plan_marks_machine_docs_and_bins_local_only() {
18
19
  assert!(!plan
19
20
  .local_only_machine_owned
20
21
  .contains(&"docs/naome/architecture.md"));
22
+ assert!(plan
23
+ .optional_codex_hook_paths
24
+ .contains(&".codex/hooks.json"));
25
+ assert!(plan
26
+ .optional_codex_hook_paths
27
+ .contains(&".codex/config.toml"));
28
+ assert!(plan
29
+ .optional_codex_hook_paths
30
+ .contains(&".naome/bin/codex-hook.js"));
31
+ assert!(!plan.machine_owned.contains(&".naome/bin/codex-hook.js"));
32
+ assert!(!plan.project_owned.contains(&".codex/hooks.json"));
21
33
  }
22
34
 
23
35
  #[test]
@@ -28,6 +40,7 @@ fn install_plan_includes_git_exclude_and_untrack_policy() {
28
40
  .gitignore_entries
29
41
  .contains(&".naome/task-journal.jsonl"));
30
42
  assert!(plan.git_exclude_entries.contains(&".naome/archive/"));
43
+ assert!(plan.git_exclude_entries.contains(&".naome/cache/"));
31
44
  assert!(plan.git_exclude_entries.contains(&".naome/bin/naome-rust*"));
32
45
  assert!(plan
33
46
  .git_exclude_entries
@@ -36,6 +49,7 @@ fn install_plan_includes_git_exclude_and_untrack_policy() {
36
49
  .git_exclude_entries
37
50
  .contains(&".naome/bin/check-harness-health.js"));
38
51
  assert!(plan.git_untrack_paths.contains(&".naome/archive"));
52
+ assert!(plan.git_untrack_paths.contains(&".naome/cache"));
39
53
  assert!(plan.git_untrack_paths.contains(&".naome/bin/naome-rust"));
40
54
  assert!(plan
41
55
  .git_untrack_paths