Skip to content

feat: Phases 4–6 intelligence, retention, and adaptation - #5

Merged
9thLevelSoftware merged 1 commit into
mainfrom
feat/phases-4-5-6
Aug 5, 2026
Merged

feat: Phases 4–6 intelligence, retention, and adaptation#5
9thLevelSoftware merged 1 commit into
mainfrom
feat/phases-4-5-6

Conversation

@9thLevelSoftware

Copy link
Copy Markdown
Owner

Summary

Implements production Phases 4–6 for This Is Fine.

Phase 4 — Intelligence depth

  • Multi-language inspector (JS/TS, Python, Go, Rust) with confident: false on weak evidence
  • Dependency deltas, generated-code heuristics, scoring_version, test-change notes
  • Config [simplicity.exceptions] audit notes

Phase 5 — Audit / privacy / retention

  • tif audit --gc wires audit + isolation GC with rollback retention
  • SQLite WAL + busy_timeout, apply lockfile, expanded redaction, binary skip

Phase 6 — Adaptation

  • Versioned pressure variants (≥2 per family), promotion/demotion stubs
  • Self-apply allowlist only; CLI: tif adaptation status|recommend|reset

Validation

  • cargo fmt
  • cargo clippy --all-features -- -D warnings
  • cargo test --workspace --all-features157 passed

Docs

  • ROADMAP phases 4–6 Done; CHANGELOG and schema/protocol/README updated

Copilot AI lite review requested due to automatic review settings August 5, 2026 04:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gitguardian

gitguardian Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
35799352 Triggered JSON Web Token 26038f0 crates/tif-core/src/audit.rs View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@9thLevelSoftware
9thLevelSoftware merged commit 78af77f into main Aug 5, 2026
7 of 8 checks passed

#[test]
fn redacts_jwt_and_connection_string() {
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signaturepart";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 The Roast: Your "JWT" here is the canonical example token from jwt.io / RFC 7519 — and GitGuardian agreed so loudly it filed Incident #35799352 against your own PR. Nothing says "production-grade security tooling" like triggering a secret scanner with your test fixture. A reviewer running GitGuardian in their CI now has to whitelist this PR or pretend eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 isn't shaped exactly like the kind of token you claim to redact.

🩹 The Fix:

Suggested change
let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signaturepart";
let jwt = "eyJ-TEST-FIXTURE-NOT-A-REAL-TOKEN.sig.placeholder_signature_with_enough_length_for_match";

📏 Severity: critical


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

continue;
}
let new_text = fs::read_to_string(repo_root.join(p)).unwrap_or_default();
let old_text = git_output(repo_root, &["show", &format!("HEAD:{p}")]).unwrap_or_default();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 The Roast: git show HEAD:<path> on an untracked manifest returns empty, so dependency_delta_from_texts(name, "", &new_text) cheerfully reports every single dep in that brand-new Cargo.toml as "added". First commit of any fresh repo suddenly looks like a 12-package dependency explosion — the simplicity score goes feral, OutOfControl fires, and Firebreak wakes up for a greenfield project that literally has no prior baseline to compare to. Bonus points: same wrong result fires for renamed manifests and for manifests present in HEAD but absent from a fresh clone's working tree.

🩹 The Fix: Treat an empty old_text (or a git show failure) as "no prior baseline" rather than "zero deps":

Suggested change
let old_text = git_output(repo_root, &["show", &format!("HEAD:{p}")]).unwrap_or_default();
let old_text = match git_output(repo_root, &["show", &format!("HEAD:{p}")]) {
Ok(t) if !t.is_empty() => t,
_ => continue,
};

📏 Severity: critical


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

if let Ok(age) = modified.elapsed() {
if age.as_secs() > 2 * 60 * 60 {
let _ = fs::remove_file(&path);
return Self::acquire(state_dir);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 The Roast: "Exclusive lock" that, on a stale file, does remove_file and then recursively re-acquires. Two processes spot the same 2-hour-old lock, both call remove_file, both call acquire again, and both walk away thinking they hold the only lock in town. The docstring above promises "Fails if another process holds the lockfile" — it doesn't, and a long-running apply (large repo, slow disk, container with throttled IO) can be silently stomped exactly when it's most fragile.

🩹 The Fix: Use flock(2) via fs2/nix, or at minimum record the original holder's PID inside the lockfile and refuse to take over unless that PID is verifiably dead (kill(pid, 0) == ESRCH). The recursive call also risks unbounded stack on a stubborn stale-lock loop — convert to a loop, max one retry.

📏 Severity: warning


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

for w in weakened {
out.push(TestChange {
path: path.to_string(),
reason: format!("weakened assertion pattern: {w}"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 The Roast: format!("weakened assertion pattern: {w}") stuffs the entire raw source line of a test file into the Damage Assessment. With audit.tier = "full" that line — including any embedded secret, API URL, customer email, or PHI in a fixture — gets persisted into .this-is-fine/audit.db and on-disk artifacts verbatim. The redaction pipeline (redact_secrets) never sees it. You built a secret-redaction subsystem and then immediately routed around it.

🩹 The Fix: Don't echo source. Record the matched pattern token only (e.g. the category like assert!(true) / #[ignore] / t.skip) plus path and a truncated snippet capped at ~40 chars:

Suggested change
reason: format!("weakened assertion pattern: {w}"),
reason: format!("weakened assertion pattern: {}", category_for(&w)),

📏 Severity: warning


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

Code Review Roast 🔥

Verdict: Request changes | Recommendation: Two critical correctness/security findings must be fixed before merge.

Overview

Severity Count
🚨 critical 2
⚠️ warning 2
💡 suggestion 0
🤏 nitpick 0
Issue Details (click to expand)
File Line Roast
crates/tif-core/src/audit.rs 911 JWT test fixture is the canonical jwt.io example — GitGuardian Incident #35799352 fired on your own PR.
crates/tif-core/src/diff.rs 188 dependency_delta_vs_git_head reports every dep as "added" when the manifest is untracked, because git show HEAD:<path> returns empty and empty-vs-new_text diffs as 100% added.
crates/tif-core/src/isolation.rs 757 ApplyLock::acquire recursively retries after remove_file on stale lock — classic TOCTOU; two processes can both "win" and stomping a long-running apply.
crates/tif-core/src/assess.rs 289 format!("weakened assertion pattern: {w}") persists raw source lines into Damage Assessments, bypassing the redaction pipeline.

🏆 Best part: The pressure-engine rewrite. Two versioned variants per family, a real promotion/demotion gate with floor-fail-rate blocking, preferred-template selection, and the self-apply allowlist actually rejects Five-Alarm at the type level. That's how you ship adaptation without making the rest of the system nervous.

💀 Worst part: dependency_delta_vs_git_head turning every greenfield repo into a 12-package "dependency explosion" the first time it inspects the tree. Nothing undermines a "simplicity scorer" like a false positive that puts every fresh project into OutOfControl on sight.

📊 Overall: Like a smoke detector that goes off every time you boil water — the sensing hardware is solid, but somebody calibrated the threshold with a sledgehammer. Fix the two criticals, tighten the lockfile semantics, and this lands clean.


Correctness / Safety Findings

  • critical: crates/tif-core/src/audit.rs:911 — JWT fixture triggers GitGuardian (Incident #35799352). Replace with an obviously-fake prefix that won't match any real token shape.
  • critical: crates/tif-core/src/diff.rs:188dependency_delta_vs_git_head reports all deps as added for untracked manifests, falsifying runtime_dependencies_added on first commit of any repo. Skip manifests with no HEAD version instead of treating empty as "zero prior deps".
  • warning: crates/tif-core/src/isolation.rs:757ApplyLock::acquire stale-recovery uses remove_file + recursive retry, vulnerable to TOCTOU between concurrent acquirers and to stomping a still-running apply. Use OS-level flock or verify holder PID is dead before takeover; bound retries.
  • warning: crates/tif-core/src/assess.rs:289weakened Vec bodies are persisted raw into DamageAssessment.tests_changed[].reason, bypassing redact_secrets. For audit.tier = "full", secrets/PHI embedded in test fixtures end up in audit DB. Record pattern category + truncated snippet instead of full source.

Ponytail Review

  • crates/tif-core/src/diff.rs:175 stdlib: dependency_delta_from_git is a one-line wrapper around dependency_delta_vs_git_head with the same signature. Delete and call dependency_delta_vs_git_head directly from metrics_from_git (line 94). Removes ~3 lines and one needless indirection.
  • crates/tif-core/src/isolation.rs:787 shrink: chrono_now_unix() is named after a C++ library, used exactly once on the line above, and the surrounding chrono import already gives you Utc::now().timestamp(). Inline as std::time::SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs() as i64).unwrap_or(0) or use chrono::Utc::now().timestamp() and drop the helper entirely. ~6 lines removable.
  • crates/tif-core/src/audit.rs:222 shrink: let lower = unified_diff_hunk.to_ascii_lowercase(); is computed, then assigned to _ inside the loop on line 254 (let _ = lower;). Delete both. Pure dead computation. 2 lines removable.
  • crates/tif-core/src/audit.rs:720 native: redact_secret_line flags any line containing the substring "secret" as sensitive and overwrites it with [REDACTED]. Task text like "rotate the kubernetes secret daily" or "audit log shows a secret was leaked" will be mangled. Mirror the token/tokenize discipline already used for looks_like_token_secret: require key/value separator (secret=, secret:) or whole-key form. Keep existing test coverage on password=hunter2 etc.

Ponytail net: -13 lines.

Suggested Minimal Patch

  1. audit.rs:911 — swap the test JWT for one whose first segment starts with eyJ-TEST-... so GitGuardian's regex won't match it.
  2. diff.rs:188 — change git show fallback from unwrap_or_default() to continue (skip the manifest when no HEAD version exists).
  3. isolation.rs:750-758 — replace remove_file + recursive acquire with a single retry loop bounded at 1 attempt, and require the holder PID to be dead (kill(pid, 0) == ESRCH) before takeover.
  4. assess.rs:286-291 — replace format!("weakened assertion pattern: {w}") with a category label + 40-char truncated snippet; do not persist full source.
  5. diff.rs:175 — delete dependency_delta_from_git; call dependency_delta_vs_git_head directly.
  6. audit.rs:222 + 254 — delete the unused lower computation.

Final Merge Guidance

Do not merge until the two critical findings (JWT fixture, dependency-delta false positives) are fixed. The two warnings are strongly recommended but not blocking.

Fix these issues in Kilo Cloud

Files Reviewed (18 files)
  • CHANGELOG.md
  • README.md
  • crates/tif-core/src/adaptation.rs
  • crates/tif-core/src/assess.rs
  • crates/tif-core/src/audit.rs
  • crates/tif-core/src/config.rs
  • crates/tif-core/src/diff.rs
  • crates/tif-core/src/inspector.rs
  • crates/tif-core/src/isolation.rs
  • crates/tif-core/src/lib.rs
  • crates/tif-core/src/orchestrator.rs
  • crates/tif-core/src/pressure.rs
  • crates/tif-core/src/scoring.rs
  • crates/tif/src/cli.rs
  • crates/tif/src/main.rs
  • docs/ROADMAP.md
  • docs/VERSIONING.md
  • docs/config/schema-v1.md
  • docs/protocol/v1.md

Reviewed by minimax-m3 · Input: 122.8K · Output: 12.5K · Cached: 2.4M

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26038f0dec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +99 to 100
apply_generated_code_heuristics(&mut metrics, Some(repo_root));
metrics.changed_paths = paths;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply generated-code heuristics after paths are populated

When metrics_from_git handles the normal --from-git / working-tree path, apply_generated_code_heuristics reads metrics.changed_paths, but this vector is still empty here and is only assigned on the next line. In that scenario generated files and lockfiles never receive the new generated_code_lines penalty for git-based assessments, unlike tree/unified-diff assessments. Move the changed_paths assignment before invoking the heuristic.

Useful? React with 👍 / 👎.

Comment thread crates/tif/src/main.rs
Comment on lines +1711 to +1712
// Explicitly never apply floor / sensitive / verify knobs.
store.save_adaptation_stats(eng.stats())?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wire applied adaptation knobs into policy compilation

When a user runs tif adaptation recommend --apply, this path persists fire-level bias, threshold scale, and pressure template choices in the audit DB, but the policy paths I inspected never read those saved knobs: cmd_run_begin still compiles with adaptive_limit_scale: None, and PolicyCompiler::compile still builds pressure selection only from config without a saved fire-level bias or preferred templates. In that scenario the command reports self-applied successfully while the next tif run begin behaves exactly as before, making the new self-apply feature a no-op.

Useful? React with 👍 / 👎.

@9thLevelSoftware
9thLevelSoftware deleted the feat/phases-4-5-6 branch August 5, 2026 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants