@lamentis/naome 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +2 -2
- package/Cargo.toml +1 -1
- package/LICENSE +180 -21
- package/README.md +49 -6
- package/bin/naome.js +54 -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 +36 -0
- package/crates/naome-cli/src/install_bridge.rs +83 -0
- package/crates/naome-cli/src/main.rs +57 -341
- package/crates/naome-cli/src/prompt_commands.rs +68 -0
- package/crates/naome-cli/src/quality_commands.rs +141 -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/harness_health/integrity.rs +96 -0
- package/crates/naome-core/src/harness_health.rs +14 -126
- package/crates/naome-core/src/install_plan.rs +3 -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 +13 -0
- package/crates/naome-core/src/quality/adapters.rs +178 -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 +72 -0
- package/crates/naome-core/src/quality/config.rs +109 -0
- package/crates/naome-core/src/quality/mod.rs +90 -0
- package/crates/naome-core/src/quality/scanner/repo_paths.rs +103 -0
- package/crates/naome-core/src/quality/scanner.rs +367 -0
- package/crates/naome-core/src/quality/types.rs +289 -0
- package/crates/naome-core/src/route.rs +62 -0
- 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 +176 -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/harness_health.rs +3 -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 +425 -0
- package/crates/naome-core/tests/route.rs +88 -188
- package/crates/naome-core/tests/task_state.rs +3 -0
- 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/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/native/darwin-arm64/naome +0 -0
- package/native/linux-x64/naome +0 -0
- package/package.json +2 -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 +34 -63
- package/templates/naome-root/.naome/manifest.json +20 -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/task-contract.schema.json +93 -11
- package/templates/naome-root/.naome/upgrade-state.json +1 -1
- package/templates/naome-root/.naome/verification.json +37 -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 +4 -3
- package/templates/naome-root/docs/naome/repository-quality.md +43 -0
- package/templates/naome-root/docs/naome/testing.md +12 -0
- package/crates/naome-core/src/task_state.rs +0 -2210
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
use super::model::IntentKind;
|
|
2
|
+
|
|
3
|
+
pub(crate) fn normalized(text: &str) -> String {
|
|
4
|
+
text.to_lowercase()
|
|
5
|
+
.chars()
|
|
6
|
+
.map(|ch| if ch.is_alphanumeric() { ch } else { ' ' })
|
|
7
|
+
.collect::<String>()
|
|
8
|
+
.split_whitespace()
|
|
9
|
+
.collect::<Vec<_>>()
|
|
10
|
+
.join(" ")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
pub(crate) fn lexical_tokens(text: &str) -> Vec<String> {
|
|
14
|
+
text.split_whitespace()
|
|
15
|
+
.map(|token| {
|
|
16
|
+
token
|
|
17
|
+
.trim_matches(|ch: char| !ch.is_alphanumeric() && ch != '_' && ch != '-')
|
|
18
|
+
.to_lowercase()
|
|
19
|
+
})
|
|
20
|
+
.filter(|token| !token.is_empty())
|
|
21
|
+
.collect()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
pub(crate) fn structured_workflow_intents(text: &str) -> Vec<IntentKind> {
|
|
25
|
+
let tokens = lexical_tokens(text);
|
|
26
|
+
let mut intents = Vec::new();
|
|
27
|
+
|
|
28
|
+
if let Some(intent) = structured_action(&tokens) {
|
|
29
|
+
intents.push(intent);
|
|
30
|
+
}
|
|
31
|
+
if let Some(intent) = legacy_v1_short_action_request(&tokens) {
|
|
32
|
+
intents.push(intent);
|
|
33
|
+
}
|
|
34
|
+
if legacy_v1_no_commit(&tokens) {
|
|
35
|
+
intents.push(IntentKind::NoCommitRequest);
|
|
36
|
+
}
|
|
37
|
+
if has_structured_token(&tokens, &["no_commit", "without_commit"]) {
|
|
38
|
+
intents.push(IntentKind::NoCommitRequest);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
intents.sort_by_key(|kind| kind.as_str());
|
|
42
|
+
intents.dedup();
|
|
43
|
+
intents
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
pub(crate) fn command_workflow_intents(text: &str) -> Vec<IntentKind> {
|
|
47
|
+
let tokens = lexical_tokens(text);
|
|
48
|
+
let mut intents = Vec::new();
|
|
49
|
+
if let Some(intent) = cli_action(&tokens) {
|
|
50
|
+
intents.push(intent);
|
|
51
|
+
}
|
|
52
|
+
intents
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pub(crate) fn explicit_task_intent(text: &str) -> Option<IntentKind> {
|
|
56
|
+
let tokens = lexical_tokens(text);
|
|
57
|
+
if has_structured_token(&tokens, &["task_revision", "current_task", "active_task"]) {
|
|
58
|
+
return Some(IntentKind::TaskRevision);
|
|
59
|
+
}
|
|
60
|
+
if has_structured_token(&tokens, &["new_task", "create_new_task", "separate_task"]) {
|
|
61
|
+
return Some(IntentKind::NewTask);
|
|
62
|
+
}
|
|
63
|
+
None
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
pub(crate) fn is_generic_work_request(text: &str) -> bool {
|
|
67
|
+
!lexical_tokens(text).is_empty()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fn structured_action(tokens: &[String]) -> Option<IntentKind> {
|
|
71
|
+
policy_action(tokens)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fn policy_action(tokens: &[String]) -> Option<IntentKind> {
|
|
75
|
+
for token in tokens {
|
|
76
|
+
let intent = match token.as_str() {
|
|
77
|
+
"commit_task_baseline" | "commit_user_diff" | "commit_upgrade_baseline" => {
|
|
78
|
+
IntentKind::CommitRequest
|
|
79
|
+
}
|
|
80
|
+
"review_task_diff" | "review_current_task_diff" | "review_unowned_diff" => {
|
|
81
|
+
IntentKind::ReviewRequest
|
|
82
|
+
}
|
|
83
|
+
"repair_harness" | "repair_harness_only" => IntentKind::RepairRequest,
|
|
84
|
+
"cancel_task_changes" | "cancel_current_task" => IntentKind::CancelRequest,
|
|
85
|
+
"continue_current_task" | "task_complete" | "complete_task" => {
|
|
86
|
+
IntentKind::TaskCompletion
|
|
87
|
+
}
|
|
88
|
+
"answer_status_only" => IntentKind::StatusQuestion,
|
|
89
|
+
"clear_or_commit_unowned_diff" => IntentKind::Ambiguous,
|
|
90
|
+
_ => continue,
|
|
91
|
+
};
|
|
92
|
+
return Some(intent);
|
|
93
|
+
}
|
|
94
|
+
None
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fn cli_action(tokens: &[String]) -> Option<IntentKind> {
|
|
98
|
+
match (
|
|
99
|
+
tokens.first().map(String::as_str),
|
|
100
|
+
tokens.get(1).map(String::as_str),
|
|
101
|
+
) {
|
|
102
|
+
(Some("naome"), Some("commit")) => Some(IntentKind::CommitRequest),
|
|
103
|
+
(Some("naome"), Some("status")) => Some(IntentKind::StatusQuestion),
|
|
104
|
+
(Some("naome"), Some("sync" | "update" | "install")) => Some(IntentKind::RepairRequest),
|
|
105
|
+
(Some("git"), Some("commit")) => Some(IntentKind::CommitRequest),
|
|
106
|
+
_ => None,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Kept only so pre-v2 route callers keep their existing conservative behavior.
|
|
111
|
+
// A naome-intent-v2 envelope clears these candidates before policy resolution.
|
|
112
|
+
fn legacy_v1_short_action_request(tokens: &[String]) -> Option<IntentKind> {
|
|
113
|
+
let action_index = tokens
|
|
114
|
+
.iter()
|
|
115
|
+
.position(|token| legacy_v1_action_intent(token).is_some())?;
|
|
116
|
+
if action_index > 1 || tokens.len() > 6 {
|
|
117
|
+
return None;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let intent = legacy_v1_action_intent(&tokens[action_index])?;
|
|
121
|
+
if intent == IntentKind::StatusQuestion || tokens.len() <= 3 {
|
|
122
|
+
return Some(intent);
|
|
123
|
+
}
|
|
124
|
+
if tokens.len() <= 2 || legacy_v1_has_action_scope(tokens) {
|
|
125
|
+
return Some(intent);
|
|
126
|
+
}
|
|
127
|
+
None
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fn legacy_v1_no_commit(tokens: &[String]) -> bool {
|
|
131
|
+
tokens
|
|
132
|
+
.windows(3)
|
|
133
|
+
.any(|window| window[0] == "do" && window[1] == "not" && window[2] == "commit")
|
|
134
|
+
|| tokens
|
|
135
|
+
.windows(2)
|
|
136
|
+
.any(|window| matches!(window[0].as_str(), "no" | "without") && window[1] == "commit")
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fn legacy_v1_action_intent(token: &str) -> Option<IntentKind> {
|
|
140
|
+
match token {
|
|
141
|
+
"commit" | "baseline" => Some(IntentKind::CommitRequest),
|
|
142
|
+
"review" => Some(IntentKind::ReviewRequest),
|
|
143
|
+
"repair" | "sync" => Some(IntentKind::RepairRequest),
|
|
144
|
+
"cancel" => Some(IntentKind::CancelRequest),
|
|
145
|
+
"complete" | "completion" => Some(IntentKind::TaskCompletion),
|
|
146
|
+
"status" => Some(IntentKind::StatusQuestion),
|
|
147
|
+
_ => None,
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
fn legacy_v1_has_action_scope(tokens: &[String]) -> bool {
|
|
152
|
+
has_structured_token(
|
|
153
|
+
tokens,
|
|
154
|
+
&[
|
|
155
|
+
"task",
|
|
156
|
+
"diff",
|
|
157
|
+
"harness",
|
|
158
|
+
"baseline",
|
|
159
|
+
"state",
|
|
160
|
+
"current_task",
|
|
161
|
+
"active_task",
|
|
162
|
+
],
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
fn has_structured_token(tokens: &[String], accepted: &[&str]) -> bool {
|
|
167
|
+
tokens
|
|
168
|
+
.iter()
|
|
169
|
+
.any(|token| accepted.iter().any(|accepted| token == accepted))
|
|
170
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
use crate::models::Decision;
|
|
2
|
+
|
|
3
|
+
use super::classifier::winning_intent;
|
|
4
|
+
use super::model::{CanonicalIntent, IntentKind};
|
|
5
|
+
use super::resolver_policy::state_policy;
|
|
6
|
+
use super::resolver_shared::{ambiguous_conflict, ambiguous_empty, unsafe_policy, Policy};
|
|
7
|
+
|
|
8
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
9
|
+
pub(crate) enum CompletedTaskReadiness {
|
|
10
|
+
Valid,
|
|
11
|
+
ValidAfterHarnessRefresh,
|
|
12
|
+
ValidWithUnrelatedDirty,
|
|
13
|
+
Invalid,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
17
|
+
pub(crate) enum DirtyDiffReadiness {
|
|
18
|
+
Unclassified,
|
|
19
|
+
HarnessRefreshOnly,
|
|
20
|
+
HarnessRefreshWithUnrelatedDirty,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
24
|
+
pub(crate) struct ResolvedIntent {
|
|
25
|
+
pub prompt_intent: IntentKind,
|
|
26
|
+
pub certainty: String,
|
|
27
|
+
pub policy_action: String,
|
|
28
|
+
pub allowed: bool,
|
|
29
|
+
pub summary: String,
|
|
30
|
+
pub next_action: String,
|
|
31
|
+
pub reason_codes: Vec<String>,
|
|
32
|
+
pub risk_codes: Vec<String>,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub(crate) fn resolve_intent(
|
|
36
|
+
decision: &Decision,
|
|
37
|
+
canonical: &CanonicalIntent,
|
|
38
|
+
completed_task_readiness: CompletedTaskReadiness,
|
|
39
|
+
dirty_diff_readiness: DirtyDiffReadiness,
|
|
40
|
+
) -> ResolvedIntent {
|
|
41
|
+
let prompt_intent = winning_intent(canonical);
|
|
42
|
+
let mut reason_codes = reason_codes(decision, canonical, prompt_intent);
|
|
43
|
+
let mut risk_codes = canonical.risk.risk_codes.clone();
|
|
44
|
+
if canonical.risk.has_risky_terms
|
|
45
|
+
&& !risk_codes
|
|
46
|
+
.iter()
|
|
47
|
+
.any(|code| code == "prompt_contains_risky_terms")
|
|
48
|
+
{
|
|
49
|
+
risk_codes.push("prompt_contains_risky_terms".to_string());
|
|
50
|
+
}
|
|
51
|
+
if completed_task_readiness == CompletedTaskReadiness::Invalid {
|
|
52
|
+
risk_codes.push("completed_task_proof_invalid".to_string());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let policy = resolve_policy(
|
|
56
|
+
decision,
|
|
57
|
+
canonical,
|
|
58
|
+
prompt_intent,
|
|
59
|
+
completed_task_readiness,
|
|
60
|
+
dirty_diff_readiness,
|
|
61
|
+
&mut reason_codes,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
ResolvedIntent {
|
|
65
|
+
prompt_intent,
|
|
66
|
+
certainty: certainty(prompt_intent, &policy.0, &risk_codes),
|
|
67
|
+
policy_action: policy.0.to_string(),
|
|
68
|
+
allowed: policy.1,
|
|
69
|
+
summary: policy.2.to_string(),
|
|
70
|
+
next_action: policy.3.to_string(),
|
|
71
|
+
reason_codes,
|
|
72
|
+
risk_codes,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fn resolve_policy(
|
|
77
|
+
decision: &Decision,
|
|
78
|
+
canonical: &CanonicalIntent,
|
|
79
|
+
prompt_intent: IntentKind,
|
|
80
|
+
completed_task_readiness: CompletedTaskReadiness,
|
|
81
|
+
dirty_diff_readiness: DirtyDiffReadiness,
|
|
82
|
+
reason_codes: &mut Vec<String>,
|
|
83
|
+
) -> Policy {
|
|
84
|
+
if canonical.is_empty {
|
|
85
|
+
ambiguous_empty()
|
|
86
|
+
} else if canonical.has_workflow_conflict {
|
|
87
|
+
reason_codes.push("winning_rule:workflow_intent_conflict".to_string());
|
|
88
|
+
ambiguous_conflict()
|
|
89
|
+
} else if prompt_intent == IntentKind::Unsafe {
|
|
90
|
+
reason_codes.push("winning_rule:unsafe_intent_precedence".to_string());
|
|
91
|
+
unsafe_policy()
|
|
92
|
+
} else if prompt_intent == IntentKind::StatusQuestion {
|
|
93
|
+
(
|
|
94
|
+
"answer_status_only",
|
|
95
|
+
true,
|
|
96
|
+
"The prompt asks for status or explanation, so no task mutation is needed.",
|
|
97
|
+
"Answer from the current NAOME status without editing files.",
|
|
98
|
+
)
|
|
99
|
+
} else {
|
|
100
|
+
state_policy(
|
|
101
|
+
decision,
|
|
102
|
+
prompt_intent,
|
|
103
|
+
completed_task_readiness,
|
|
104
|
+
dirty_diff_readiness,
|
|
105
|
+
canonical.risk.has_risky_terms,
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fn reason_codes(
|
|
111
|
+
decision: &Decision,
|
|
112
|
+
canonical: &CanonicalIntent,
|
|
113
|
+
prompt_intent: IntentKind,
|
|
114
|
+
) -> Vec<String> {
|
|
115
|
+
let mut codes = vec![format!("repo_state:{}", decision.state)];
|
|
116
|
+
if canonical.references_current_task {
|
|
117
|
+
codes.push("prompt_references_current_task".to_string());
|
|
118
|
+
}
|
|
119
|
+
for (kind, code) in [
|
|
120
|
+
(IntentKind::NewTask, "prompt_requests_new_goal"),
|
|
121
|
+
(IntentKind::TaskRevision, "prompt_requests_correction"),
|
|
122
|
+
(IntentKind::CommitRequest, "prompt_requests_commit"),
|
|
123
|
+
(IntentKind::NoCommitRequest, "prompt_blocks_commit"),
|
|
124
|
+
(IntentKind::ReviewRequest, "prompt_requests_review"),
|
|
125
|
+
(IntentKind::RepairRequest, "prompt_requests_repair"),
|
|
126
|
+
(IntentKind::CancelRequest, "prompt_requests_cancel"),
|
|
127
|
+
] {
|
|
128
|
+
if prompt_intent == kind
|
|
129
|
+
|| canonical
|
|
130
|
+
.candidates
|
|
131
|
+
.iter()
|
|
132
|
+
.any(|candidate| candidate.kind == kind)
|
|
133
|
+
{
|
|
134
|
+
codes.push(code.to_string());
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
codes
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
fn certainty(intent: IntentKind, policy_action: &str, risk_codes: &[String]) -> String {
|
|
141
|
+
if !risk_codes.is_empty() && policy_action == "block_unsafe_intent" {
|
|
142
|
+
"unsafe"
|
|
143
|
+
} else if policy_action == "block_ambiguous_intent"
|
|
144
|
+
|| policy_action == "block_auto_baseline_due_to_no_commit"
|
|
145
|
+
|| intent == IntentKind::Ambiguous
|
|
146
|
+
{
|
|
147
|
+
"ambiguous"
|
|
148
|
+
} else if matches!(
|
|
149
|
+
intent,
|
|
150
|
+
IntentKind::CommitRequest
|
|
151
|
+
| IntentKind::StatusQuestion
|
|
152
|
+
| IntentKind::ReviewRequest
|
|
153
|
+
| IntentKind::RepairRequest
|
|
154
|
+
| IntentKind::NoCommitRequest
|
|
155
|
+
| IntentKind::CancelRequest
|
|
156
|
+
) {
|
|
157
|
+
"exact"
|
|
158
|
+
} else {
|
|
159
|
+
"likely"
|
|
160
|
+
}
|
|
161
|
+
.to_string()
|
|
162
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
use super::model::IntentKind;
|
|
2
|
+
use super::resolver_catalog::{
|
|
3
|
+
POLICY_ACTIVE_CANCEL, POLICY_ACTIVE_CONTINUE, POLICY_ACTIVE_NEW_BLOCK, POLICY_ACTIVE_NO_COMMIT,
|
|
4
|
+
POLICY_ACTIVE_REVIEW,
|
|
5
|
+
};
|
|
6
|
+
use super::resolver_shared::{ambiguous_policy, Policy};
|
|
7
|
+
|
|
8
|
+
pub(crate) fn active_policy(intent: IntentKind) -> Policy {
|
|
9
|
+
match intent {
|
|
10
|
+
IntentKind::ReviewRequest => POLICY_ACTIVE_REVIEW,
|
|
11
|
+
IntentKind::CancelRequest => POLICY_ACTIVE_CANCEL,
|
|
12
|
+
IntentKind::NoCommitRequest => POLICY_ACTIVE_NO_COMMIT,
|
|
13
|
+
IntentKind::TaskRevision | IntentKind::TaskCompletion => POLICY_ACTIVE_CONTINUE,
|
|
14
|
+
IntentKind::NewTask => POLICY_ACTIVE_NEW_BLOCK,
|
|
15
|
+
_ => ambiguous_policy(),
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
use super::model::IntentKind;
|
|
2
|
+
use super::resolver::DirtyDiffReadiness;
|
|
3
|
+
use super::resolver_catalog::{
|
|
4
|
+
POLICY_BASELINE_BLOCK, POLICY_BASELINE_CANCEL, POLICY_BASELINE_COMMIT_UPGRADE,
|
|
5
|
+
POLICY_BASELINE_NEW_REFRESH, POLICY_BASELINE_NEW_UPGRADE, POLICY_BASELINE_NO_COMMIT,
|
|
6
|
+
POLICY_BASELINE_REVIEW, POLICY_DIRTY_BLOCK, POLICY_DIRTY_COMMIT_USER,
|
|
7
|
+
POLICY_DIRTY_NEW_ISOLATED, POLICY_DIRTY_NEW_REFRESH, POLICY_DIRTY_NEW_WORKTREE,
|
|
8
|
+
};
|
|
9
|
+
use super::resolver_shared::{harness_refresh_policy, unsafe_policy, Policy};
|
|
10
|
+
|
|
11
|
+
pub(crate) fn dirty_policy(intent: IntentKind, dirty: DirtyDiffReadiness, risky: bool) -> Policy {
|
|
12
|
+
match (intent, dirty, risky) {
|
|
13
|
+
(IntentKind::RepairRequest, DirtyDiffReadiness::HarnessRefreshOnly, false) => {
|
|
14
|
+
harness_refresh_policy()
|
|
15
|
+
}
|
|
16
|
+
(
|
|
17
|
+
IntentKind::RepairRequest,
|
|
18
|
+
DirtyDiffReadiness::HarnessRefreshWithUnrelatedDirty,
|
|
19
|
+
false,
|
|
20
|
+
) => harness_refresh_policy(),
|
|
21
|
+
(IntentKind::NewTask, DirtyDiffReadiness::HarnessRefreshOnly, false) => {
|
|
22
|
+
POLICY_DIRTY_NEW_REFRESH
|
|
23
|
+
}
|
|
24
|
+
(IntentKind::NewTask, DirtyDiffReadiness::HarnessRefreshWithUnrelatedDirty, false) => {
|
|
25
|
+
POLICY_DIRTY_NEW_ISOLATED
|
|
26
|
+
}
|
|
27
|
+
(IntentKind::NewTask, _, false) => POLICY_DIRTY_NEW_WORKTREE,
|
|
28
|
+
(IntentKind::CommitRequest, _, false) => POLICY_DIRTY_COMMIT_USER,
|
|
29
|
+
_ => POLICY_DIRTY_BLOCK,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub(crate) fn baseline_policy(
|
|
34
|
+
intent: IntentKind,
|
|
35
|
+
dirty: DirtyDiffReadiness,
|
|
36
|
+
risky: bool,
|
|
37
|
+
) -> Policy {
|
|
38
|
+
match intent {
|
|
39
|
+
IntentKind::NoCommitRequest => POLICY_BASELINE_NO_COMMIT,
|
|
40
|
+
IntentKind::ReviewRequest => POLICY_BASELINE_REVIEW,
|
|
41
|
+
IntentKind::CancelRequest => POLICY_BASELINE_CANCEL,
|
|
42
|
+
IntentKind::CommitRequest | IntentKind::RepairRequest
|
|
43
|
+
if dirty == DirtyDiffReadiness::HarnessRefreshOnly =>
|
|
44
|
+
{
|
|
45
|
+
harness_refresh_policy()
|
|
46
|
+
}
|
|
47
|
+
IntentKind::CommitRequest | IntentKind::RepairRequest => POLICY_BASELINE_COMMIT_UPGRADE,
|
|
48
|
+
IntentKind::NewTask if dirty == DirtyDiffReadiness::HarnessRefreshOnly && !risky => {
|
|
49
|
+
POLICY_BASELINE_NEW_REFRESH
|
|
50
|
+
}
|
|
51
|
+
IntentKind::NewTask if !risky => POLICY_BASELINE_NEW_UPGRADE,
|
|
52
|
+
IntentKind::NewTask => unsafe_policy(),
|
|
53
|
+
_ => POLICY_BASELINE_BLOCK,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
use super::resolver_shared::Policy;
|
|
2
|
+
|
|
3
|
+
pub(crate) const POLICY_ACTIVE_BLOCKED: Policy = (
|
|
4
|
+
"block_unowned_diff",
|
|
5
|
+
false,
|
|
6
|
+
"The active task is blocked by out-of-scope changes.",
|
|
7
|
+
"Resolve the scope blocker before interpreting new work.",
|
|
8
|
+
);
|
|
9
|
+
pub(crate) const POLICY_ACTIVE_CANCEL: Policy = (
|
|
10
|
+
"cancel_current_task",
|
|
11
|
+
false,
|
|
12
|
+
"The prompt asks to cancel the active task.",
|
|
13
|
+
"Cancel or review the active task before starting another.",
|
|
14
|
+
);
|
|
15
|
+
pub(crate) const POLICY_ACTIVE_CONTINUE: Policy = (
|
|
16
|
+
"continue_current_task",
|
|
17
|
+
true,
|
|
18
|
+
"A task is active and the prompt appears to continue or finish it.",
|
|
19
|
+
"Continue the current task and keep proof current.",
|
|
20
|
+
);
|
|
21
|
+
pub(crate) const POLICY_ACTIVE_NEW_BLOCK: Policy = (
|
|
22
|
+
"block_ambiguous_intent",
|
|
23
|
+
false,
|
|
24
|
+
"A task is already active and the prompt appears to ask for a distinct new goal.",
|
|
25
|
+
"Complete, revise, or cancel the active task before starting another.",
|
|
26
|
+
);
|
|
27
|
+
pub(crate) const POLICY_ACTIVE_NO_COMMIT: Policy = (
|
|
28
|
+
"continue_current_task_without_commit",
|
|
29
|
+
true,
|
|
30
|
+
"A task is active and the prompt blocks committing.",
|
|
31
|
+
"Continue the active task without baselining.",
|
|
32
|
+
);
|
|
33
|
+
pub(crate) const POLICY_ACTIVE_REVIEW: Policy = (
|
|
34
|
+
"review_current_task_diff",
|
|
35
|
+
false,
|
|
36
|
+
"The prompt asks to review the active task diff.",
|
|
37
|
+
"Review the active task before mutating it further.",
|
|
38
|
+
);
|
|
39
|
+
pub(crate) const POLICY_BASELINE_BLOCK: Policy = (
|
|
40
|
+
"block_unowned_diff",
|
|
41
|
+
false,
|
|
42
|
+
"Setup, upgrade, or repair changes must be resolved before task routing.",
|
|
43
|
+
"Resolve the harness baseline decision before accepting feature work.",
|
|
44
|
+
);
|
|
45
|
+
pub(crate) const POLICY_BASELINE_CANCEL: Policy = (
|
|
46
|
+
"cancel_upgrade_baseline",
|
|
47
|
+
false,
|
|
48
|
+
"The prompt explicitly asks to cancel setup, upgrade, or repair changes.",
|
|
49
|
+
"Cancel or review the NAOME diff before feature work.",
|
|
50
|
+
);
|
|
51
|
+
pub(crate) const POLICY_BASELINE_COMMIT_UPGRADE: Policy = (
|
|
52
|
+
"commit_upgrade_baseline",
|
|
53
|
+
true,
|
|
54
|
+
"The prompt asks to baseline pending setup, upgrade, or repair changes.",
|
|
55
|
+
"Run the appropriate NAOME baseline flow before feature work.",
|
|
56
|
+
);
|
|
57
|
+
pub(crate) const POLICY_BASELINE_NEW_REFRESH: Policy = ("auto_commit_harness_refresh_then_create_new_task", true, "The prompt asks for a new goal and the only blocker is a deterministic harness refresh.", "Baseline the harness refresh automatically, rerun admission, then create the new task in the same worktree.");
|
|
58
|
+
pub(crate) const POLICY_BASELINE_NEW_UPGRADE: Policy = ("auto_commit_upgrade_baseline_then_create_new_task", true, "The prompt asks for a new goal and the only blocker is a completed NAOME setup, upgrade, or repair diff.", "Baseline the NAOME diff automatically, rerun admission, then create the new task.");
|
|
59
|
+
pub(crate) const POLICY_BASELINE_NO_COMMIT: Policy = ("block_auto_baseline_due_to_no_commit", false, "The prompt explicitly blocks committing, so NAOME will not auto-baseline setup or repair changes.", "Review, cancel, or manually resolve the setup diff before feature work.");
|
|
60
|
+
pub(crate) const POLICY_BASELINE_REVIEW: Policy = (
|
|
61
|
+
"review_diff_first",
|
|
62
|
+
false,
|
|
63
|
+
"The prompt explicitly asks to review setup, upgrade, or repair changes.",
|
|
64
|
+
"Review the NAOME diff before any baseline or new task.",
|
|
65
|
+
);
|
|
66
|
+
pub(crate) const POLICY_COMPLETED_CANCEL: Policy = (
|
|
67
|
+
"cancel_task_changes",
|
|
68
|
+
false,
|
|
69
|
+
"The prompt explicitly asks to cancel the completed task changes.",
|
|
70
|
+
"Cancel or review the completed task diff before any new task.",
|
|
71
|
+
);
|
|
72
|
+
pub(crate) const POLICY_COMPLETED_COMMIT: Policy = (
|
|
73
|
+
"commit_task_baseline",
|
|
74
|
+
true,
|
|
75
|
+
"The prompt asks to baseline the completed task diff.",
|
|
76
|
+
"Run the NAOME commit baseline flow for the completed task.",
|
|
77
|
+
);
|
|
78
|
+
pub(crate) const POLICY_COMPLETED_NEW_INVALID: Policy = (
|
|
79
|
+
"block_unsafe_intent",
|
|
80
|
+
false,
|
|
81
|
+
"The prompt asks for a new task, but the current completed task is not safe to auto-baseline.",
|
|
82
|
+
"Review the completed diff and proof before starting new work.",
|
|
83
|
+
);
|
|
84
|
+
pub(crate) const POLICY_COMPLETED_NEW_ISOLATED: Policy = ("auto_commit_completed_task_then_create_isolated_task_worktree", true, "The completed task is valid, and unrelated user edits are present.", "Baseline only the completed task paths, preserve unrelated user edits, and create an isolated worktree for the next task.");
|
|
85
|
+
pub(crate) const POLICY_COMPLETED_NEW_REFRESH: Policy = ("auto_commit_harness_refresh_then_completed_task_then_create_new_task", true, "The completed task is valid after separating deterministic harness refresh changes.", "Baseline the harness refresh first, then baseline the completed task and create the next task.");
|
|
86
|
+
pub(crate) const POLICY_COMPLETED_NEW_VALID: Policy = (
|
|
87
|
+
"auto_commit_completed_task_then_create_new_task",
|
|
88
|
+
true,
|
|
89
|
+
"The completed task is valid and the prompt asks for a distinct new goal.",
|
|
90
|
+
"Baseline the completed task first, then create the next task.",
|
|
91
|
+
);
|
|
92
|
+
pub(crate) const POLICY_COMPLETED_NO_COMMIT: Policy = (
|
|
93
|
+
"block_auto_baseline_due_to_no_commit",
|
|
94
|
+
false,
|
|
95
|
+
"The prompt explicitly blocks committing, so NAOME will not auto-baseline the completed task.",
|
|
96
|
+
"Review, revise, cancel, or manually resolve the completed task diff.",
|
|
97
|
+
);
|
|
98
|
+
pub(crate) const POLICY_COMPLETED_REVIEW: Policy = (
|
|
99
|
+
"review_task_diff",
|
|
100
|
+
false,
|
|
101
|
+
"The prompt explicitly asks to review the completed task diff.",
|
|
102
|
+
"Review the completed task diff before any baseline or new task.",
|
|
103
|
+
);
|
|
104
|
+
pub(crate) const POLICY_COMPLETED_REVISION: Policy = (
|
|
105
|
+
"reopen_completed_task_revision",
|
|
106
|
+
true,
|
|
107
|
+
"The prompt refers to follow-up correction on the unbaselined completed task.",
|
|
108
|
+
"Reopen the same task as a revision and mark proof stale before editing.",
|
|
109
|
+
);
|
|
110
|
+
pub(crate) const POLICY_DIRTY_BLOCK: Policy = ("block_unowned_diff", false, "The repository has unowned changes that must be resolved first.", "NAOME will not commit unowned changes. Review them, or route a new task so NAOME can isolate task work in a separate worktree.");
|
|
111
|
+
pub(crate) const POLICY_DIRTY_COMMIT_USER: Policy = ("commit_user_diff_with_quality_gate", true, "The prompt asks to commit unowned user changes.", "Run NAOME's user-diff quality gate, then commit only the current changed paths if every required check passes.");
|
|
112
|
+
pub(crate) const POLICY_DIRTY_NEW_ISOLATED: Policy = ("auto_commit_harness_refresh_then_create_isolated_task_worktree", true, "The repository has deterministic harness refresh changes plus unrelated user edits.", "Baseline only the harness refresh first, then create an isolated task worktree without touching user edits.");
|
|
113
|
+
pub(crate) const POLICY_DIRTY_NEW_REFRESH: Policy = (
|
|
114
|
+
"auto_commit_harness_refresh_then_create_new_task",
|
|
115
|
+
true,
|
|
116
|
+
"The repository has only deterministic harness refresh changes.",
|
|
117
|
+
"Baseline the harness refresh first, then create the next task in the same worktree.",
|
|
118
|
+
);
|
|
119
|
+
pub(crate) const POLICY_DIRTY_NEW_WORKTREE: Policy = ("create_isolated_task_worktree", true, "The repository has unrelated user changes, and the prompt asks for a new task.", "Create an isolated NAOME task worktree so the new task can proceed without touching those user changes.");
|
|
120
|
+
pub(crate) const POLICY_FIRST_RUN: Policy = (
|
|
121
|
+
"run_first_run_protocol",
|
|
122
|
+
false,
|
|
123
|
+
"First-run intake must finish before feature work.",
|
|
124
|
+
"Run the NAOME first-run protocol.",
|
|
125
|
+
);
|
|
126
|
+
pub(crate) const POLICY_HARNESS_UNHEALTHY: Policy = (
|
|
127
|
+
"repair_harness_only",
|
|
128
|
+
false,
|
|
129
|
+
"The harness is unhealthy, so normal task work is blocked.",
|
|
130
|
+
"Repair or review the harness before accepting feature work.",
|
|
131
|
+
);
|
|
132
|
+
pub(crate) const POLICY_READY_COMMIT_BLOCK: Policy = (
|
|
133
|
+
"block_ambiguous_intent",
|
|
134
|
+
false,
|
|
135
|
+
"The repository is already ready for work; there is no open task diff to baseline.",
|
|
136
|
+
"Ask for the next concrete task or inspect status.",
|
|
137
|
+
);
|
|
138
|
+
pub(crate) const POLICY_READY_NEW: Policy = (
|
|
139
|
+
"create_new_task",
|
|
140
|
+
true,
|
|
141
|
+
"The repository is clean and the prompt asks for a new goal.",
|
|
142
|
+
"Create a NAOME task for the new request.",
|
|
143
|
+
);
|
|
144
|
+
pub(crate) const POLICY_READY_NO_COMMIT: Policy = (
|
|
145
|
+
"create_new_task_without_auto_baseline",
|
|
146
|
+
true,
|
|
147
|
+
"The repository is clean, so no commit is needed before the new task.",
|
|
148
|
+
"Create a NAOME task for the new request.",
|
|
149
|
+
);
|
|
150
|
+
pub(crate) const POLICY_READY_REVIEW_STATUS: Policy = (
|
|
151
|
+
"answer_status_only",
|
|
152
|
+
true,
|
|
153
|
+
"The prompt asks for review, but there is no open task diff.",
|
|
154
|
+
"Answer from the current NAOME status without editing files.",
|
|
155
|
+
);
|
|
156
|
+
pub(crate) const POLICY_READY_REVISION_BLOCK: Policy = (
|
|
157
|
+
"block_ambiguous_intent",
|
|
158
|
+
false,
|
|
159
|
+
"The prompt sounds like a correction, but there is no open task diff.",
|
|
160
|
+
"Ask whether this is a new task or a status question.",
|
|
161
|
+
);
|
|
162
|
+
pub(crate) const POLICY_UPGRADE: Policy = (
|
|
163
|
+
"run_upgrade_protocol",
|
|
164
|
+
false,
|
|
165
|
+
"A NAOME upgrade is pending before feature work.",
|
|
166
|
+
"Run the NAOME upgrade protocol.",
|
|
167
|
+
);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
use crate::models::Decision;
|
|
2
|
+
|
|
3
|
+
use super::model::IntentKind;
|
|
4
|
+
use super::resolver::{CompletedTaskReadiness, DirtyDiffReadiness};
|
|
5
|
+
use super::resolver_active::active_policy;
|
|
6
|
+
use super::resolver_baseline::{baseline_policy, dirty_policy};
|
|
7
|
+
use super::resolver_catalog::{
|
|
8
|
+
POLICY_ACTIVE_BLOCKED, POLICY_COMPLETED_CANCEL, POLICY_COMPLETED_COMMIT,
|
|
9
|
+
POLICY_COMPLETED_NEW_INVALID, POLICY_COMPLETED_NEW_ISOLATED, POLICY_COMPLETED_NEW_REFRESH,
|
|
10
|
+
POLICY_COMPLETED_NEW_VALID, POLICY_COMPLETED_NO_COMMIT, POLICY_COMPLETED_REVIEW,
|
|
11
|
+
POLICY_COMPLETED_REVISION, POLICY_FIRST_RUN, POLICY_HARNESS_UNHEALTHY,
|
|
12
|
+
POLICY_READY_COMMIT_BLOCK, POLICY_READY_NEW, POLICY_READY_NO_COMMIT,
|
|
13
|
+
POLICY_READY_REVIEW_STATUS, POLICY_READY_REVISION_BLOCK, POLICY_UPGRADE,
|
|
14
|
+
};
|
|
15
|
+
use super::resolver_shared::{ambiguous_policy, Policy};
|
|
16
|
+
|
|
17
|
+
pub(crate) fn state_policy(
|
|
18
|
+
decision: &Decision,
|
|
19
|
+
prompt_intent: IntentKind,
|
|
20
|
+
completed: CompletedTaskReadiness,
|
|
21
|
+
dirty: DirtyDiffReadiness,
|
|
22
|
+
risky: bool,
|
|
23
|
+
) -> Policy {
|
|
24
|
+
match decision.state.as_str() {
|
|
25
|
+
"harness_unhealthy" => POLICY_HARNESS_UNHEALTHY,
|
|
26
|
+
"first_run_required" => POLICY_FIRST_RUN,
|
|
27
|
+
"upgrade_required" => POLICY_UPGRADE,
|
|
28
|
+
"ready_for_task" => ready_policy(prompt_intent),
|
|
29
|
+
"completed_task_unbaselined" => completed_policy(prompt_intent, completed, risky),
|
|
30
|
+
"active_task_in_progress" => active_policy(prompt_intent),
|
|
31
|
+
"active_task_blocked" => POLICY_ACTIVE_BLOCKED,
|
|
32
|
+
"dirty_unowned_diff" | "task_admission_blocked" => {
|
|
33
|
+
dirty_policy(prompt_intent, dirty, risky)
|
|
34
|
+
}
|
|
35
|
+
"install_or_upgrade_unbaselined" | "harness_repair_unbaselined" => {
|
|
36
|
+
baseline_policy(prompt_intent, dirty, risky)
|
|
37
|
+
}
|
|
38
|
+
_ => ambiguous_policy(),
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
fn ready_policy(intent: IntentKind) -> Policy {
|
|
43
|
+
match intent {
|
|
44
|
+
IntentKind::NewTask => POLICY_READY_NEW,
|
|
45
|
+
IntentKind::CommitRequest => POLICY_READY_COMMIT_BLOCK,
|
|
46
|
+
IntentKind::ReviewRequest => POLICY_READY_REVIEW_STATUS,
|
|
47
|
+
IntentKind::NoCommitRequest => POLICY_READY_NO_COMMIT,
|
|
48
|
+
IntentKind::TaskRevision => POLICY_READY_REVISION_BLOCK,
|
|
49
|
+
_ => ambiguous_policy(),
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fn completed_policy(intent: IntentKind, completed: CompletedTaskReadiness, risky: bool) -> Policy {
|
|
54
|
+
match intent {
|
|
55
|
+
IntentKind::NoCommitRequest => POLICY_COMPLETED_NO_COMMIT,
|
|
56
|
+
IntentKind::ReviewRequest => POLICY_COMPLETED_REVIEW,
|
|
57
|
+
IntentKind::CancelRequest => POLICY_COMPLETED_CANCEL,
|
|
58
|
+
IntentKind::CommitRequest => POLICY_COMPLETED_COMMIT,
|
|
59
|
+
IntentKind::TaskRevision => POLICY_COMPLETED_REVISION,
|
|
60
|
+
IntentKind::NewTask => completed_new_task_policy(completed, risky),
|
|
61
|
+
_ => ambiguous_policy(),
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fn completed_new_task_policy(completed: CompletedTaskReadiness, risky: bool) -> Policy {
|
|
66
|
+
match (completed, risky) {
|
|
67
|
+
(CompletedTaskReadiness::Valid, false) => POLICY_COMPLETED_NEW_VALID,
|
|
68
|
+
(CompletedTaskReadiness::ValidAfterHarnessRefresh, false) => POLICY_COMPLETED_NEW_REFRESH,
|
|
69
|
+
(CompletedTaskReadiness::ValidWithUnrelatedDirty, false) => POLICY_COMPLETED_NEW_ISOLATED,
|
|
70
|
+
_ => POLICY_COMPLETED_NEW_INVALID,
|
|
71
|
+
}
|
|
72
|
+
}
|