@lamentis/naome 1.1.2 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +2 -2
- package/Cargo.toml +1 -1
- package/LICENSE +180 -21
- package/README.md +49 -6
- package/bin/naome-node.js +2 -1579
- package/bin/naome.js +68 -16
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/check_commands.rs +135 -0
- package/crates/naome-cli/src/cli_args.rs +5 -0
- package/crates/naome-cli/src/dispatcher.rs +37 -0
- package/crates/naome-cli/src/install_bridge.rs +83 -0
- package/crates/naome-cli/src/main.rs +60 -341
- package/crates/naome-cli/src/prompt_commands.rs +68 -0
- package/crates/naome-cli/src/quality_commands.rs +229 -0
- package/crates/naome-cli/src/simple_commands.rs +53 -0
- package/crates/naome-cli/src/workflow_commands.rs +153 -0
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/decision/checks.rs +64 -0
- package/crates/naome-core/src/decision/idle.rs +67 -0
- package/crates/naome-core/src/decision/json.rs +36 -0
- package/crates/naome-core/src/decision/states.rs +165 -0
- package/crates/naome-core/src/decision.rs +131 -353
- package/crates/naome-core/src/harness_health/integrity.rs +96 -0
- package/crates/naome-core/src/harness_health.rs +14 -126
- package/crates/naome-core/src/install_plan.rs +5 -0
- package/crates/naome-core/src/intent/classifier.rs +171 -0
- package/crates/naome-core/src/intent/envelope.rs +108 -0
- package/crates/naome-core/src/intent/legacy.rs +138 -0
- package/crates/naome-core/src/intent/legacy_response.rs +76 -0
- package/crates/naome-core/src/intent/model.rs +71 -0
- package/crates/naome-core/src/intent/patterns.rs +170 -0
- package/crates/naome-core/src/intent/resolver.rs +162 -0
- package/crates/naome-core/src/intent/resolver_active.rs +17 -0
- package/crates/naome-core/src/intent/resolver_baseline.rs +55 -0
- package/crates/naome-core/src/intent/resolver_catalog.rs +167 -0
- package/crates/naome-core/src/intent/resolver_policy.rs +72 -0
- package/crates/naome-core/src/intent/resolver_shared.rs +55 -0
- package/crates/naome-core/src/intent/risk.rs +40 -0
- package/crates/naome-core/src/intent/segment.rs +170 -0
- package/crates/naome-core/src/intent.rs +64 -879
- package/crates/naome-core/src/journal.rs +9 -20
- package/crates/naome-core/src/lib.rs +15 -0
- package/crates/naome-core/src/paths.rs +3 -1
- package/crates/naome-core/src/quality/adapter_support.rs +89 -0
- package/crates/naome-core/src/quality/adapters.rs +131 -0
- package/crates/naome-core/src/quality/baseline.rs +75 -0
- package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +175 -0
- package/crates/naome-core/src/quality/checks/near_duplicates.rs +130 -0
- package/crates/naome-core/src/quality/checks.rs +228 -0
- package/crates/naome-core/src/quality/cleanup.rs +84 -0
- package/crates/naome-core/src/quality/config.rs +102 -0
- package/crates/naome-core/src/quality/config_support.rs +24 -0
- package/crates/naome-core/src/quality/mod.rs +108 -0
- package/crates/naome-core/src/quality/scanner/repo_paths.rs +103 -0
- package/crates/naome-core/src/quality/scanner.rs +379 -0
- package/crates/naome-core/src/quality/structure/adapters.rs +84 -0
- package/crates/naome-core/src/quality/structure/checks/basic.rs +153 -0
- package/crates/naome-core/src/quality/structure/checks/directory.rs +144 -0
- package/crates/naome-core/src/quality/structure/checks/pairing.rs +63 -0
- package/crates/naome-core/src/quality/structure/checks.rs +124 -0
- package/crates/naome-core/src/quality/structure/classify/roles.rs +188 -0
- package/crates/naome-core/src/quality/structure/classify.rs +94 -0
- package/crates/naome-core/src/quality/structure/config.rs +89 -0
- package/crates/naome-core/src/quality/structure/defaults.rs +107 -0
- package/crates/naome-core/src/quality/structure/mod.rs +77 -0
- package/crates/naome-core/src/quality/structure/model.rs +124 -0
- package/crates/naome-core/src/quality/types.rs +292 -0
- package/crates/naome-core/src/route/builtin_checks.rs +155 -0
- package/crates/naome-core/src/route/builtin_context.rs +73 -0
- package/crates/naome-core/src/route/builtin_integrity.rs +49 -0
- package/crates/naome-core/src/route/builtin_require.rs +40 -0
- package/crates/naome-core/src/route/context.rs +180 -0
- package/crates/naome-core/src/route/execution.rs +96 -0
- package/crates/naome-core/src/route/execution_baselines.rs +146 -0
- package/crates/naome-core/src/route/execution_support.rs +57 -0
- package/crates/naome-core/src/route/execution_tasks.rs +71 -0
- package/crates/naome-core/src/route/git_ops.rs +72 -0
- package/crates/naome-core/src/route/quality_gate.rs +73 -0
- package/crates/naome-core/src/route/quality_gate_config.rs +126 -0
- package/crates/naome-core/src/route/quality_gate_snapshot.rs +69 -0
- package/crates/naome-core/src/route/worktree.rs +75 -0
- package/crates/naome-core/src/route/worktree_files.rs +32 -0
- package/crates/naome-core/src/route/worktree_plan.rs +131 -0
- package/crates/naome-core/src/route.rs +44 -1155
- package/crates/naome-core/src/task_state/admission.rs +63 -0
- package/crates/naome-core/src/task_state/admission_proof.rs +72 -0
- package/crates/naome-core/src/task_state/api.rs +130 -0
- package/crates/naome-core/src/task_state/commit_gate.rs +138 -0
- package/crates/naome-core/src/task_state/compact_proof.rs +160 -0
- package/crates/naome-core/src/task_state/completed_refresh.rs +89 -0
- package/crates/naome-core/src/task_state/completion.rs +72 -0
- package/crates/naome-core/src/task_state/deleted_paths.rs +47 -0
- package/crates/naome-core/src/task_state/diff.rs +95 -0
- package/crates/naome-core/src/task_state/evidence.rs +154 -0
- package/crates/naome-core/src/task_state/git_io.rs +86 -0
- package/crates/naome-core/src/task_state/git_parse.rs +86 -0
- package/crates/naome-core/src/task_state/git_refs.rs +37 -0
- package/crates/naome-core/src/task_state/human_review_state.rs +31 -0
- package/crates/naome-core/src/task_state/mod.rs +38 -0
- package/crates/naome-core/src/task_state/process_guard.rs +40 -0
- package/crates/naome-core/src/task_state/progress.rs +123 -0
- package/crates/naome-core/src/task_state/proof.rs +139 -0
- package/crates/naome-core/src/task_state/proof_entry.rs +66 -0
- package/crates/naome-core/src/task_state/proof_model.rs +70 -0
- package/crates/naome-core/src/task_state/proof_sources.rs +76 -0
- package/crates/naome-core/src/task_state/push_gate.rs +49 -0
- package/crates/naome-core/src/task_state/reconcile.rs +7 -0
- package/crates/naome-core/src/task_state/repair.rs +168 -0
- package/crates/naome-core/src/task_state/shape.rs +117 -0
- package/crates/naome-core/src/task_state/task_diff_api.rs +170 -0
- package/crates/naome-core/src/task_state/task_records.rs +131 -0
- package/crates/naome-core/src/task_state/task_references.rs +126 -0
- package/crates/naome-core/src/task_state/types.rs +87 -0
- package/crates/naome-core/src/task_state/util.rs +137 -0
- package/crates/naome-core/src/verification/render.rs +122 -0
- package/crates/naome-core/src/verification.rs +177 -58
- package/crates/naome-core/src/verification_contract.rs +49 -21
- package/crates/naome-core/src/workflow/integrity.rs +123 -0
- package/crates/naome-core/src/workflow/integrity_normalize.rs +7 -0
- package/crates/naome-core/src/workflow/integrity_support.rs +110 -0
- package/crates/naome-core/src/workflow/mod.rs +18 -0
- package/crates/naome-core/src/workflow/mutation.rs +68 -0
- package/crates/naome-core/src/workflow/output.rs +111 -0
- package/crates/naome-core/src/workflow/phase_inference.rs +73 -0
- package/crates/naome-core/src/workflow/phases.rs +169 -0
- package/crates/naome-core/src/workflow/policy.rs +156 -0
- package/crates/naome-core/src/workflow/processes.rs +91 -0
- package/crates/naome-core/src/workflow/types.rs +42 -0
- package/crates/naome-core/tests/decision.rs +24 -118
- package/crates/naome-core/tests/harness_health.rs +5 -0
- package/crates/naome-core/tests/intent.rs +97 -792
- package/crates/naome-core/tests/intent_support/mod.rs +133 -0
- package/crates/naome-core/tests/intent_v2.rs +90 -0
- package/crates/naome-core/tests/quality.rs +319 -0
- package/crates/naome-core/tests/quality_structure.rs +116 -0
- package/crates/naome-core/tests/quality_structure_adapters.rs +98 -0
- package/crates/naome-core/tests/quality_structure_policy.rs +125 -0
- package/crates/naome-core/tests/quality_structure_support/mod.rs +249 -0
- package/crates/naome-core/tests/repo_support/mod.rs +16 -0
- package/crates/naome-core/tests/repo_support/repo.rs +113 -0
- package/crates/naome-core/tests/repo_support/repo_factories.rs +99 -0
- package/crates/naome-core/tests/repo_support/repo_helpers.rs +123 -0
- package/crates/naome-core/tests/repo_support/routes.rs +81 -0
- package/crates/naome-core/tests/repo_support/verification.rs +168 -0
- package/crates/naome-core/tests/repo_support/verification_values.rs +135 -0
- package/crates/naome-core/tests/route.rs +1 -1476
- package/crates/naome-core/tests/route_baseline.rs +86 -0
- package/crates/naome-core/tests/route_completion.rs +141 -0
- package/crates/naome-core/tests/route_harness_refresh.rs +135 -0
- package/crates/naome-core/tests/route_user_diff.rs +198 -0
- package/crates/naome-core/tests/route_worktree.rs +54 -0
- package/crates/naome-core/tests/task_state.rs +60 -429
- package/crates/naome-core/tests/task_state_compact.rs +110 -0
- package/crates/naome-core/tests/task_state_compact_support/mod.rs +5 -0
- package/crates/naome-core/tests/task_state_compact_support/repo.rs +130 -0
- package/crates/naome-core/tests/task_state_compact_support/states.rs +151 -0
- package/crates/naome-core/tests/task_state_support/mod.rs +163 -0
- package/crates/naome-core/tests/task_state_support/states.rs +84 -0
- package/crates/naome-core/tests/verification.rs +4 -45
- package/crates/naome-core/tests/verification_contract.rs +22 -78
- package/crates/naome-core/tests/workflow_integrity.rs +85 -0
- package/crates/naome-core/tests/workflow_policy.rs +139 -0
- package/crates/naome-core/tests/workflow_support/mod.rs +194 -0
- package/installer/agents.js +90 -0
- package/installer/context.js +67 -0
- package/installer/filesystem.js +166 -0
- package/installer/flows.js +84 -0
- package/installer/git-boundary.js +170 -0
- package/installer/git-hook-content.js +36 -0
- package/installer/git-hooks.js +134 -0
- package/installer/git-local.js +2 -0
- package/installer/git-shared.js +35 -0
- package/installer/harness-file-ops.js +140 -0
- package/installer/harness-files.js +56 -0
- package/installer/harness-verification.js +123 -0
- package/installer/install-plan.js +66 -0
- package/installer/main.js +25 -0
- package/installer/manifest-state.js +167 -0
- package/installer/native-build.js +24 -0
- package/installer/native-format.js +6 -0
- package/installer/native.js +162 -0
- package/installer/output.js +131 -0
- package/installer/version.js +32 -0
- package/native/darwin-arm64/naome +0 -0
- package/native/linux-x64/naome +0 -0
- package/package.json +3 -2
- package/templates/naome-root/.naome/bin/check-harness-health.js +66 -85
- package/templates/naome-root/.naome/bin/check-task-state.js +9 -10
- package/templates/naome-root/.naome/bin/naome.js +51 -76
- package/templates/naome-root/.naome/manifest.json +22 -18
- package/templates/naome-root/.naome/repository-quality-baseline.json +5 -0
- package/templates/naome-root/.naome/repository-quality.json +24 -0
- package/templates/naome-root/.naome/repository-structure.json +90 -0
- package/templates/naome-root/.naome/task-contract.schema.json +93 -11
- package/templates/naome-root/.naome/upgrade-state.json +1 -1
- package/templates/naome-root/.naome/verification.json +38 -0
- package/templates/naome-root/AGENTS.md +3 -0
- package/templates/naome-root/docs/naome/agent-workflow.md +25 -12
- package/templates/naome-root/docs/naome/execution.md +25 -21
- package/templates/naome-root/docs/naome/index.md +5 -3
- package/templates/naome-root/docs/naome/repository-quality.md +46 -0
- package/templates/naome-root/docs/naome/repository-structure.md +51 -0
- package/templates/naome-root/docs/naome/testing.md +13 -0
- package/crates/naome-core/src/task_state.rs +0 -2210
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
use std::path::Path;
|
|
2
|
+
|
|
3
|
+
use naome_core::{
|
|
4
|
+
check_repository_quality, explain_repository_structure, init_repository_quality,
|
|
5
|
+
plan_quality_cleanup, route_quality_cleanup, QualityMode,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
use crate::cli_args::option_value;
|
|
9
|
+
|
|
10
|
+
pub fn run_quality_command(root: &Path, args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
|
11
|
+
let Some(subcommand) = args.get(1).map(String::as_str) else {
|
|
12
|
+
return Err("naome quality requires init, check, or report.".into());
|
|
13
|
+
};
|
|
14
|
+
let json = args.iter().any(|arg| arg == "--json");
|
|
15
|
+
|
|
16
|
+
match subcommand {
|
|
17
|
+
"init" => {
|
|
18
|
+
let result = init_repository_quality(root)?;
|
|
19
|
+
if json {
|
|
20
|
+
println!("{}", serde_json::to_string_pretty(&result)?);
|
|
21
|
+
} else {
|
|
22
|
+
println!("NAOME repository quality initialized.");
|
|
23
|
+
println!("Baseline violations: {}", result.baseline_violations);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
"check" => run_quality_check(root, args, json)?,
|
|
27
|
+
"report" => run_quality_report(root, json)?,
|
|
28
|
+
_ => return Err(format!("unknown naome quality command: {subcommand}").into()),
|
|
29
|
+
}
|
|
30
|
+
Ok(())
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub fn run_cleanup_command(root: &Path, args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
|
34
|
+
let Some(subcommand) = args.get(1).map(String::as_str) else {
|
|
35
|
+
return Err("naome cleanup requires plan or route.".into());
|
|
36
|
+
};
|
|
37
|
+
let json = args.iter().any(|arg| arg == "--json");
|
|
38
|
+
|
|
39
|
+
match subcommand {
|
|
40
|
+
"plan" => run_cleanup_plan(root, json)?,
|
|
41
|
+
"route" => run_cleanup_route(root, args, json)?,
|
|
42
|
+
_ => return Err(format!("unknown naome cleanup command: {subcommand}").into()),
|
|
43
|
+
}
|
|
44
|
+
Ok(())
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
pub fn run_structure_command(
|
|
48
|
+
root: &Path,
|
|
49
|
+
args: &[String],
|
|
50
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
51
|
+
let Some(subcommand) = args.get(1).map(String::as_str) else {
|
|
52
|
+
return Err("naome structure requires report or explain.".into());
|
|
53
|
+
};
|
|
54
|
+
let json = args.iter().any(|arg| arg == "--json");
|
|
55
|
+
|
|
56
|
+
match subcommand {
|
|
57
|
+
"report" => run_structure_report(root, json)?,
|
|
58
|
+
"explain" => run_structure_explain(root, args, json)?,
|
|
59
|
+
_ => return Err(format!("unknown naome structure command: {subcommand}").into()),
|
|
60
|
+
}
|
|
61
|
+
Ok(())
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fn run_quality_check(
|
|
65
|
+
root: &Path,
|
|
66
|
+
args: &[String],
|
|
67
|
+
json: bool,
|
|
68
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
69
|
+
if !args.iter().any(|arg| arg == "--changed") {
|
|
70
|
+
return Err("naome quality check requires --changed.".into());
|
|
71
|
+
}
|
|
72
|
+
let report = check_repository_quality(root, QualityMode::Changed)?;
|
|
73
|
+
if json {
|
|
74
|
+
println!("{}", serde_json::to_string_pretty(&report)?);
|
|
75
|
+
} else if report.ok {
|
|
76
|
+
println!("NAOME repository quality OK.");
|
|
77
|
+
} else {
|
|
78
|
+
eprintln!(
|
|
79
|
+
"NAOME repository quality failed with {} violation(s).",
|
|
80
|
+
report.violations.len()
|
|
81
|
+
);
|
|
82
|
+
for violation in report.violations.iter().take(20) {
|
|
83
|
+
print_quality_violation(violation);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if !report.ok {
|
|
87
|
+
std::process::exit(1);
|
|
88
|
+
}
|
|
89
|
+
Ok(())
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fn run_quality_report(root: &Path, json: bool) -> Result<(), Box<dyn std::error::Error>> {
|
|
93
|
+
let report = check_repository_quality(root, QualityMode::Report)?;
|
|
94
|
+
if json {
|
|
95
|
+
println!("{}", serde_json::to_string_pretty(&report)?);
|
|
96
|
+
} else if report.violations.is_empty() {
|
|
97
|
+
println!("NAOME repository quality report: no debt found.");
|
|
98
|
+
} else {
|
|
99
|
+
println!(
|
|
100
|
+
"NAOME repository quality report: {} violation(s) across {} scanned file(s).",
|
|
101
|
+
report.violations.len(),
|
|
102
|
+
report.summary.scanned_files
|
|
103
|
+
);
|
|
104
|
+
for violation in report.violations.iter().take(20) {
|
|
105
|
+
print_quality_violation(violation);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
Ok(())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fn run_cleanup_plan(root: &Path, json: bool) -> Result<(), Box<dyn std::error::Error>> {
|
|
112
|
+
let plan = plan_quality_cleanup(root)?;
|
|
113
|
+
if json {
|
|
114
|
+
println!("{}", serde_json::to_string_pretty(&plan)?);
|
|
115
|
+
} else if plan.tasks.is_empty() {
|
|
116
|
+
println!("NAOME cleanup plan: no repository-quality debt found.");
|
|
117
|
+
} else {
|
|
118
|
+
println!("NAOME cleanup plan:");
|
|
119
|
+
for task in plan.tasks.iter().take(20) {
|
|
120
|
+
println!(
|
|
121
|
+
"- {}: {} violation(s) [{}]",
|
|
122
|
+
task.path,
|
|
123
|
+
task.violation_count,
|
|
124
|
+
task.check_ids.join(", ")
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
Ok(())
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fn run_cleanup_route(
|
|
132
|
+
root: &Path,
|
|
133
|
+
args: &[String],
|
|
134
|
+
json: bool,
|
|
135
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
136
|
+
let Some(path) = option_value(args, "--path") else {
|
|
137
|
+
return Err("naome cleanup route requires --path <path>.".into());
|
|
138
|
+
};
|
|
139
|
+
let route = route_quality_cleanup(root, path)?;
|
|
140
|
+
if json {
|
|
141
|
+
println!("{}", serde_json::to_string_pretty(&route)?);
|
|
142
|
+
} else {
|
|
143
|
+
println!("NAOME cleanup route for {}", route.path);
|
|
144
|
+
println!("{}", route.agent_instructions);
|
|
145
|
+
if !route.related_paths.is_empty() {
|
|
146
|
+
println!("Related paths: {}", route.related_paths.join(", "));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
Ok(())
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fn run_structure_report(root: &Path, json: bool) -> Result<(), Box<dyn std::error::Error>> {
|
|
153
|
+
let mut report = check_repository_quality(root, QualityMode::Report)?;
|
|
154
|
+
report
|
|
155
|
+
.violations
|
|
156
|
+
.retain(|violation| is_structure_check(&violation.check_id));
|
|
157
|
+
report.summary.violation_count = report.violations.len();
|
|
158
|
+
report.summary.blocking_violation_count = report.violations.len();
|
|
159
|
+
report.summary.baseline_violation_count = report
|
|
160
|
+
.violations
|
|
161
|
+
.iter()
|
|
162
|
+
.filter(|violation| violation.baseline)
|
|
163
|
+
.count();
|
|
164
|
+
report.ok = report.violations.is_empty();
|
|
165
|
+
report.schema = "naome.repository-structure-report.v1".to_string();
|
|
166
|
+
|
|
167
|
+
if json {
|
|
168
|
+
println!("{}", serde_json::to_string_pretty(&report)?);
|
|
169
|
+
} else if report.violations.is_empty() {
|
|
170
|
+
println!("NAOME repository structure report: no debt found.");
|
|
171
|
+
} else {
|
|
172
|
+
println!(
|
|
173
|
+
"NAOME repository structure report: {} violation(s).",
|
|
174
|
+
report.violations.len()
|
|
175
|
+
);
|
|
176
|
+
for violation in report.violations.iter().take(20) {
|
|
177
|
+
print_quality_violation(violation);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
Ok(())
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
fn run_structure_explain(
|
|
184
|
+
root: &Path,
|
|
185
|
+
args: &[String],
|
|
186
|
+
json: bool,
|
|
187
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
188
|
+
let Some(path) = option_value(args, "--path") else {
|
|
189
|
+
return Err("naome structure explain requires --path <path>.".into());
|
|
190
|
+
};
|
|
191
|
+
let explanation = explain_repository_structure(root, path)?;
|
|
192
|
+
if json {
|
|
193
|
+
println!("{}", serde_json::to_string_pretty(&explanation)?);
|
|
194
|
+
} else {
|
|
195
|
+
println!(
|
|
196
|
+
"{} role={} layer={} directory={}",
|
|
197
|
+
explanation.path, explanation.role, explanation.layer, explanation.directory
|
|
198
|
+
);
|
|
199
|
+
if let Some(language) = explanation.language {
|
|
200
|
+
println!("language={language}");
|
|
201
|
+
}
|
|
202
|
+
if let Some(module) = explanation.module {
|
|
203
|
+
println!("module={module}");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
Ok(())
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
fn is_structure_check(check_id: &str) -> bool {
|
|
210
|
+
matches!(
|
|
211
|
+
check_id,
|
|
212
|
+
"directory-role-mixing"
|
|
213
|
+
| "misplaced-file-role"
|
|
214
|
+
| "root-file-sprawl"
|
|
215
|
+
| "dumping-ground-directory"
|
|
216
|
+
| "directory-size"
|
|
217
|
+
| "path-depth"
|
|
218
|
+
| "case-collision"
|
|
219
|
+
| "test-source-pairing"
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
fn print_quality_violation(violation: &naome_core::QualityViolation) {
|
|
224
|
+
let location = violation
|
|
225
|
+
.line
|
|
226
|
+
.map(|line| format!("{}:{line}", violation.path))
|
|
227
|
+
.unwrap_or_else(|| violation.path.clone());
|
|
228
|
+
eprintln!("- {location} {}: {}", violation.check_id, violation.message);
|
|
229
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
use std::path::Path;
|
|
2
|
+
|
|
3
|
+
use naome_core::{install_plan, seed_builtin_verification_checks};
|
|
4
|
+
|
|
5
|
+
use crate::cli_args::option_value;
|
|
6
|
+
|
|
7
|
+
pub fn print_install_plan(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
|
8
|
+
let harness_version = option_value(args, "--harness-version")
|
|
9
|
+
.or_else(|| option_value(args, "--version"))
|
|
10
|
+
.unwrap_or_else(|| env!("CARGO_PKG_VERSION").to_string());
|
|
11
|
+
println!(
|
|
12
|
+
"{}",
|
|
13
|
+
serde_json::to_string_pretty(&install_plan(harness_version))?
|
|
14
|
+
);
|
|
15
|
+
Ok(())
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn seed_verification(root: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
|
19
|
+
if seed_builtin_verification_checks(root)? {
|
|
20
|
+
println!("NAOME verification checks updated.");
|
|
21
|
+
} else {
|
|
22
|
+
println!("NAOME verification checks already present.");
|
|
23
|
+
}
|
|
24
|
+
Ok(())
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub fn run_journal_task(root: &Path, args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
|
28
|
+
let outcome =
|
|
29
|
+
option_value(args, "--outcome").unwrap_or_else(|| "naome_commit_baseline".to_string());
|
|
30
|
+
let commit_before = option_value(args, "--commit-before");
|
|
31
|
+
let commit_after = option_value(args, "--commit-after");
|
|
32
|
+
let entry = naome_core::append_task_journal(root, &outcome, commit_before, commit_after)?;
|
|
33
|
+
if args.iter().any(|arg| arg == "--json") {
|
|
34
|
+
println!("{}", serde_json::to_string_pretty(&entry)?);
|
|
35
|
+
} else if entry.is_some() {
|
|
36
|
+
println!("NAOME task journal updated.");
|
|
37
|
+
} else {
|
|
38
|
+
println!("NAOME task journal had no active task to record.");
|
|
39
|
+
}
|
|
40
|
+
Ok(())
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
pub fn run_commit_paths(root: &Path, args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
|
44
|
+
let paths = naome_core::completed_task_commit_paths(root)?;
|
|
45
|
+
if args.iter().any(|arg| arg == "--json") {
|
|
46
|
+
println!("{}", serde_json::to_string_pretty(&paths)?);
|
|
47
|
+
} else {
|
|
48
|
+
for path in paths {
|
|
49
|
+
println!("{path}");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
Ok(())
|
|
53
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
use std::path::Path;
|
|
2
|
+
|
|
3
|
+
use naome_core::{
|
|
4
|
+
classify_mutations, refresh_integrity, safe_rg_args, tracked_process_report,
|
|
5
|
+
validate_search_command, verification_phase_plan,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
use crate::cli_args::option_value;
|
|
9
|
+
|
|
10
|
+
pub fn run_refresh_integrity(
|
|
11
|
+
root: &Path,
|
|
12
|
+
args: &[String],
|
|
13
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
14
|
+
let report = refresh_integrity(root)?;
|
|
15
|
+
if args.iter().any(|arg| arg == "--json") {
|
|
16
|
+
println!("{}", serde_json::to_string_pretty(&report)?);
|
|
17
|
+
} else if report.updated {
|
|
18
|
+
println!(
|
|
19
|
+
"NAOME integrity refreshed: {}.",
|
|
20
|
+
report.changed_paths.join(", ")
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
println!("NAOME integrity already current.");
|
|
24
|
+
}
|
|
25
|
+
Ok(())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub fn run_workflow_command(
|
|
29
|
+
root: &Path,
|
|
30
|
+
args: &[String],
|
|
31
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
32
|
+
let Some(subcommand) = args.get(1).map(String::as_str) else {
|
|
33
|
+
return Err("naome workflow requires search-profile, check-search, phases, processes, or mutations.".into());
|
|
34
|
+
};
|
|
35
|
+
let json = args.iter().any(|arg| arg == "--json");
|
|
36
|
+
|
|
37
|
+
match subcommand {
|
|
38
|
+
"search-profile" => {
|
|
39
|
+
let args = safe_rg_args(root)?;
|
|
40
|
+
if json {
|
|
41
|
+
println!("{}", serde_json::to_string_pretty(&args)?);
|
|
42
|
+
} else {
|
|
43
|
+
println!(
|
|
44
|
+
"{}",
|
|
45
|
+
args.iter()
|
|
46
|
+
.map(|arg| shell_quote(arg))
|
|
47
|
+
.collect::<Vec<_>>()
|
|
48
|
+
.join(" ")
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
"check-search" => run_check_search(root, args, json)?,
|
|
53
|
+
"phases" => {
|
|
54
|
+
let plan = verification_phase_plan(root, &[])?;
|
|
55
|
+
if json {
|
|
56
|
+
println!("{}", serde_json::to_string_pretty(&plan)?);
|
|
57
|
+
} else {
|
|
58
|
+
println!(
|
|
59
|
+
"Recommended checks: {}",
|
|
60
|
+
empty_label(&plan.recommended_check_ids)
|
|
61
|
+
);
|
|
62
|
+
if !plan.withheld_check_ids.is_empty() {
|
|
63
|
+
println!("Withheld checks: {}", plan.withheld_check_ids.join(", "));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
"processes" => {
|
|
68
|
+
let report = tracked_process_report(root)?;
|
|
69
|
+
if json {
|
|
70
|
+
println!("{}", serde_json::to_string_pretty(&report)?);
|
|
71
|
+
} else if report.active.is_empty() {
|
|
72
|
+
println!("NAOME tracked processes OK.");
|
|
73
|
+
} else {
|
|
74
|
+
println!("Active tracked processes:");
|
|
75
|
+
for process in report.active {
|
|
76
|
+
println!("- {} [{}]", process.command, process.cwd);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
"mutations" => run_mutations(root, args, json)?,
|
|
81
|
+
_ => return Err(format!("unknown naome workflow command: {subcommand}").into()),
|
|
82
|
+
}
|
|
83
|
+
Ok(())
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fn run_check_search(
|
|
87
|
+
root: &Path,
|
|
88
|
+
args: &[String],
|
|
89
|
+
json: bool,
|
|
90
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
91
|
+
let Some(command) = option_value(args, "--command") else {
|
|
92
|
+
return Err("naome workflow check-search requires --command <command>.".into());
|
|
93
|
+
};
|
|
94
|
+
let findings = validate_search_command(root, &command)?;
|
|
95
|
+
if !json && findings.is_empty() {
|
|
96
|
+
println!("NAOME search command OK.");
|
|
97
|
+
}
|
|
98
|
+
if json {
|
|
99
|
+
println!("{}", serde_json::to_string_pretty(&findings)?);
|
|
100
|
+
} else {
|
|
101
|
+
for finding in &findings {
|
|
102
|
+
println!("- {}: {}", finding.check_id, finding.message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if !findings.is_empty() {
|
|
106
|
+
std::process::exit(1);
|
|
107
|
+
}
|
|
108
|
+
Ok(())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fn run_mutations(
|
|
112
|
+
root: &Path,
|
|
113
|
+
args: &[String],
|
|
114
|
+
json: bool,
|
|
115
|
+
) -> Result<(), Box<dyn std::error::Error>> {
|
|
116
|
+
let paths = args
|
|
117
|
+
.iter()
|
|
118
|
+
.skip_while(|arg| arg.as_str() != "--path")
|
|
119
|
+
.skip(1)
|
|
120
|
+
.filter(|arg| !arg.starts_with("--"))
|
|
121
|
+
.cloned()
|
|
122
|
+
.collect::<Vec<_>>();
|
|
123
|
+
if paths.is_empty() {
|
|
124
|
+
return Err("naome workflow mutations requires --path <path> [path...]".into());
|
|
125
|
+
}
|
|
126
|
+
let classes = classify_mutations(root, &paths)?;
|
|
127
|
+
if json {
|
|
128
|
+
println!("{}", serde_json::to_string_pretty(&classes)?);
|
|
129
|
+
} else {
|
|
130
|
+
for entry in classes {
|
|
131
|
+
println!("{}: {}", entry.path, entry.mutation_class);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
Ok(())
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
fn empty_label(values: &[String]) -> String {
|
|
138
|
+
if values.is_empty() {
|
|
139
|
+
"none".to_string()
|
|
140
|
+
} else {
|
|
141
|
+
values.join(", ")
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
fn shell_quote(value: &str) -> String {
|
|
146
|
+
if value
|
|
147
|
+
.chars()
|
|
148
|
+
.all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.' | '/' | ':'))
|
|
149
|
+
{
|
|
150
|
+
return value.to_string();
|
|
151
|
+
}
|
|
152
|
+
format!("'{}'", value.replace('\'', "'\\''"))
|
|
153
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
use std::ffi::OsString;
|
|
2
|
+
use std::path::Path;
|
|
3
|
+
use std::process::Command;
|
|
4
|
+
|
|
5
|
+
use crate::models::{CheckDecision, NaomeError};
|
|
6
|
+
|
|
7
|
+
pub(super) fn run_node_check(
|
|
8
|
+
root: &Path,
|
|
9
|
+
script: &str,
|
|
10
|
+
args: &[&str],
|
|
11
|
+
) -> Result<CheckDecision, NaomeError> {
|
|
12
|
+
let mut command_args = vec![script.to_string()];
|
|
13
|
+
command_args.extend(args.iter().map(ToString::to_string));
|
|
14
|
+
let node_bin = std::env::var_os("NAOME_NODE_BIN").unwrap_or_else(|| OsString::from("node"));
|
|
15
|
+
let output = Command::new(&node_bin)
|
|
16
|
+
.args(&command_args)
|
|
17
|
+
.current_dir(root)
|
|
18
|
+
.output()?;
|
|
19
|
+
let mut combined = String::new();
|
|
20
|
+
combined.push_str(&String::from_utf8_lossy(&output.stdout));
|
|
21
|
+
combined.push_str(&String::from_utf8_lossy(&output.stderr));
|
|
22
|
+
|
|
23
|
+
Ok(CheckDecision {
|
|
24
|
+
command: format!(
|
|
25
|
+
"{} {}{}",
|
|
26
|
+
node_bin.to_string_lossy(),
|
|
27
|
+
script,
|
|
28
|
+
if args.is_empty() {
|
|
29
|
+
String::new()
|
|
30
|
+
} else {
|
|
31
|
+
format!(" {}", args.join(" "))
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
exit_code: output.status.code(),
|
|
35
|
+
ok: output.status.success(),
|
|
36
|
+
output: combined.trim().to_string(),
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pub(super) fn extract_known_actions(output: &str) -> Vec<&'static str> {
|
|
41
|
+
const KNOWN: [&str; 11] = [
|
|
42
|
+
"commit_task_baseline",
|
|
43
|
+
"review_task_diff",
|
|
44
|
+
"request_task_changes",
|
|
45
|
+
"cancel_task_changes",
|
|
46
|
+
"commit_upgrade_baseline",
|
|
47
|
+
"review_diff_first",
|
|
48
|
+
"cancel_upgrade_baseline",
|
|
49
|
+
"run_first_run_protocol",
|
|
50
|
+
"run_upgrade_protocol",
|
|
51
|
+
"review_unowned_diff",
|
|
52
|
+
"create_task",
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
let actions: Vec<&'static str> = KNOWN
|
|
56
|
+
.into_iter()
|
|
57
|
+
.filter(|action| output.contains(action))
|
|
58
|
+
.collect();
|
|
59
|
+
if actions.is_empty() {
|
|
60
|
+
vec!["review_task_admission"]
|
|
61
|
+
} else {
|
|
62
|
+
actions
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
use std::path::Path;
|
|
2
|
+
|
|
3
|
+
use crate::models::{Decision, NaomeError};
|
|
4
|
+
use crate::paths;
|
|
5
|
+
use crate::task_state::harness_refresh_diff;
|
|
6
|
+
|
|
7
|
+
pub(super) fn idle_diff_decision(
|
|
8
|
+
root: &Path,
|
|
9
|
+
changed_paths: &[String],
|
|
10
|
+
machine_owned: &[String],
|
|
11
|
+
known_harness_paths: &[String],
|
|
12
|
+
) -> Result<Decision, NaomeError> {
|
|
13
|
+
let all_machine_owned = !machine_owned.is_empty()
|
|
14
|
+
&& changed_paths
|
|
15
|
+
.iter()
|
|
16
|
+
.all(|path| paths::matches_any(path, machine_owned));
|
|
17
|
+
let all_harness_owned = !known_harness_paths.is_empty()
|
|
18
|
+
&& changed_paths
|
|
19
|
+
.iter()
|
|
20
|
+
.all(|path| paths::matches_any(path, known_harness_paths));
|
|
21
|
+
|
|
22
|
+
if harness_refresh_diff(root)?.is_some_and(|diff| diff.unrelated_paths.is_empty()) {
|
|
23
|
+
Ok(harness_repair_decision(
|
|
24
|
+
"Machine-owned NAOME harness refresh files changed outside an active task.",
|
|
25
|
+
"Run NAOME intent for the next natural-language request; deterministic policy can baseline a pure harness refresh automatically.",
|
|
26
|
+
))
|
|
27
|
+
} else if all_machine_owned {
|
|
28
|
+
Ok(harness_repair_decision(
|
|
29
|
+
"Machine-owned NAOME harness files changed outside an active task.",
|
|
30
|
+
"Review and baseline the harness repair or cancel it before feature work.",
|
|
31
|
+
))
|
|
32
|
+
} else if all_harness_owned {
|
|
33
|
+
Ok(Decision::new(
|
|
34
|
+
"install_or_upgrade_unbaselined",
|
|
35
|
+
true,
|
|
36
|
+
"NAOME setup or upgrade files changed outside an active task.",
|
|
37
|
+
vec![
|
|
38
|
+
"commit_upgrade_baseline",
|
|
39
|
+
"review_diff_first",
|
|
40
|
+
"cancel_upgrade_baseline",
|
|
41
|
+
],
|
|
42
|
+
"Resolve the setup or upgrade diff before feature work.",
|
|
43
|
+
))
|
|
44
|
+
} else {
|
|
45
|
+
Ok(Decision::new(
|
|
46
|
+
"dirty_unowned_diff",
|
|
47
|
+
true,
|
|
48
|
+
"The repository has changes not owned by an active NAOME task.",
|
|
49
|
+
vec!["review_unowned_diff"],
|
|
50
|
+
"Review the unowned diff, or route a new task so NAOME can isolate task work without touching it.",
|
|
51
|
+
))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn harness_repair_decision(user_message: &str, next_action: &str) -> Decision {
|
|
56
|
+
Decision::new(
|
|
57
|
+
"harness_repair_unbaselined",
|
|
58
|
+
true,
|
|
59
|
+
user_message,
|
|
60
|
+
vec![
|
|
61
|
+
"commit_upgrade_baseline",
|
|
62
|
+
"review_diff_first",
|
|
63
|
+
"cancel_upgrade_baseline",
|
|
64
|
+
],
|
|
65
|
+
next_action,
|
|
66
|
+
)
|
|
67
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
use std::fs;
|
|
2
|
+
use std::path::Path;
|
|
3
|
+
|
|
4
|
+
use serde_json::Value;
|
|
5
|
+
|
|
6
|
+
use crate::models::NaomeError;
|
|
7
|
+
|
|
8
|
+
pub(super) fn read_json(root: &Path, relative_path: &str) -> Result<Value, NaomeError> {
|
|
9
|
+
let content = fs::read_to_string(root.join(relative_path))?;
|
|
10
|
+
Ok(serde_json::from_str(&content)?)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
pub(super) fn json_bool(value: &Value, key: &str) -> Option<bool> {
|
|
14
|
+
value.get(key).and_then(Value::as_bool)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub(super) fn json_string(value: &Value, key: &str) -> Option<String> {
|
|
18
|
+
value
|
|
19
|
+
.get(key)
|
|
20
|
+
.and_then(Value::as_str)
|
|
21
|
+
.map(ToString::to_string)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
pub(super) fn string_array_at(value: &Value, key: &str) -> Vec<String> {
|
|
25
|
+
value
|
|
26
|
+
.get(key)
|
|
27
|
+
.and_then(Value::as_array)
|
|
28
|
+
.map(|values| {
|
|
29
|
+
values
|
|
30
|
+
.iter()
|
|
31
|
+
.filter_map(Value::as_str)
|
|
32
|
+
.map(ToString::to_string)
|
|
33
|
+
.collect()
|
|
34
|
+
})
|
|
35
|
+
.unwrap_or_default()
|
|
36
|
+
}
|