Skip to content

fix: instinct promote leaves orphaned project-scoped copy#2549

Open
wouterschoonees wants to merge 2 commits into
affaan-m:mainfrom
wouterschoonees:fix/instinct-promote-orphaned-project-copy
Open

fix: instinct promote leaves orphaned project-scoped copy#2549
wouterschoonees wants to merge 2 commits into
affaan-m:mainfrom
wouterschoonees:fix/instinct-promote-orphaned-project-copy

Conversation

@wouterschoonees

Copy link
Copy Markdown

Summary

  • instinct promote <id> (and the auto cross-project variant) writes the promoted instinct into the global personal dir but never removes it from the project-scoped source file it came from.
  • load_all_instincts() dedupes by ID with project-scope taking precedence over global on collision, so the leftover project copy silently shadows the new global entry - status under-reports the global count (and shows the instinct as still project-scoped) until the stale file is deleted by hand.
  • Reproduced by importing a multi-instinct file, promoting one ID by hand, and diffing status output before/after manually removing the stale source file.

Fix

  • Adds _remove_instinct_from_source(): re-parses the instinct's source file, strips just the promoted block, rewrites the remaining blocks in the same frontmatter format, or deletes the file outright if it was the only instinct in it.
  • Wired into _promote_specific (single-ID promote).
  • Wired into _promote_auto as well - it iterates every project entry that contributed to the cross-project candidate, not just the highest-confidence one used for the merged output content, since each project's copy independently shadows the same global ID.

Test plan

  • py_compile on the patched file
  • Isolated smoke test (CLV2_HOMUNCULUS_DIR pointed at a temp dir): imported a 2-instinct file into a scratch git repo, promoted one ID, confirmed the promoted instinct disappears from project scope and appears under global in status, while the un-promoted sibling in the same source file survives untouched
  • Maintainers: no existing automated test coverage found for _promote_specific/_promote_auto; happy to add one if there's a preferred harness/location for instinct-cli.py tests

promote (both by-ID and auto) wrote the instinct to the global
personal dir but never touched the project-scoped source file. Since
load_all_instincts() dedupes by ID with project taking precedence over
global, the leftover project copy silently shadowed the new global
entry - `status` under-reported the global count until the stale file
was removed by hand.

Adds _remove_instinct_from_source(), which strips just the promoted
instinct's block from its (possibly multi-instinct) source file,
deleting the file only if it was the sole entry. Wired into both
_promote_specific and _promote_auto (the latter cleans every
project's copy that fed the promotion, not just the highest-confidence
one used for the merged content).
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Promoted instincts are now removed from their original project-scoped source files after promotion.
    • Prevented stale project copies from overriding newly promoted global instincts during later status and loading operations.
    • Preserved remaining instinct entries when a source file contains multiple entries, removing the file only if nothing remains.

Walkthrough

Promotion now removes promoted instincts from project-scoped source files. The cleanup helper removes matching blocks, deletes empty files, and preserves remaining entries. Both specific and automatic promotion paths invoke the helper when source metadata is available.

Changes

Instinct promotion cleanup

Layer / File(s) Summary
Source cleanup and promotion integration
skills/continuous-learning-v2/scripts/instinct-cli.py
Adds source-file block removal and connects it to specific and automatic promotion flows.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: affaan-m

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It clearly summarizes the main change: cleaning up orphaned project-scoped instincts during promotion.
Description check ✅ Passed The description directly matches the changeset and explains the bug, fix, and validation steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR cleans up project-scoped instincts after promotion. The main changes are:

  • Adds a helper to remove a promoted instinct from its source file.
  • Preserves other parsed instincts when rewriting a shared source file.
  • Applies cleanup to both specific and automatic promotion flows.

Confidence Score: 5/5

The latest update looks safe to merge.

  • The updated guard avoids deleting a source file when the promoted instinct is not found.
  • No additional blocking issue met the scope for this follow-up review.

Important Files Changed

Filename Overview
skills/continuous-learning-v2/scripts/instinct-cli.py Adds project-source cleanup after global promotion and avoids deleting a source when the target instinct is absent from the parsed result.

Reviews (2): Last reviewed commit: "fix: don't delete source file on failed ..." | Re-trigger Greptile

Comment thread skills/continuous-learning-v2/scripts/instinct-cli.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/continuous-learning-v2/scripts/instinct-cli.py`:
- Around line 1333-1347: The promotion flow is not transactional and can leave
source and global files inconsistent after failures. In
skills/continuous-learning-v2/scripts/instinct-cli.py lines 1333-1347, stage
remaining-source content in a temporary file and atomically replace the source
instead of unlinking or directly rewriting it; in lines 1411-1415, publish the
global copy only after specific-source cleanup succeeds or roll back on failure;
and in lines 1489-1494, apply the same per-candidate transaction for automatic
promotion. Handle and propagate filesystem errors explicitly at each level, and
do not report partial cleanup as success.
- Around line 1333-1347: The remaining-instincts persistence flow must avoid
direct unlink/write_text mutations and handle failures explicitly. Update the
surrounding function that processes remaining instincts to stage serialized
content in a temporary file within source_file’s directory, atomically replace
the source only after a successful write, and coordinate the empty-result
deletion with promotion rollback. Preserve the existing output format and ensure
cleanup and errors are handled at each operation level.
- Around line 1340-1345: Update the instinct block serialization loop around the
`for key, value in inst.items()` logic to serialize every retained field with
the existing schema-aware YAML serializer, not only `trigger` via `_yaml_quote`.
Preserve the exclusions for `content` and underscore-prefixed keys, while
ensuring all remaining values are safely serialized according to the schema
before appending them to `block`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5ba35339-d084-40db-8da3-c4823ed20976

📥 Commits

Reviewing files that changed from the base of the PR and between a3130f9 and f4b6f07.

📒 Files selected for processing (1)
  • skills/continuous-learning-v2/scripts/instinct-cli.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}

📄 CodeRabbit inference engine (.cursor/rules/common-coding-style.md)

**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}: Always create new objects, never mutate existing ones. Use immutable patterns to prevent hidden side effects and enable safe concurrency
Organize code into many small files (200-400 lines typical, 800 lines max) organized by feature/domain rather than by type
Always handle errors explicitly at every level and never silently swallow errors
Always validate all user input before processing at system boundaries
Use schema-based validation where available
Fail fast with clear error messages when validation fails
Never trust external data (API responses, user input, file content)
Ensure code is readable and well-named
Keep functions small (less than 50 lines)
Keep files focused (less than 800 lines)
Avoid deep nesting (more than 4 levels)
Do not use hardcoded values; use constants or configuration instead

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

No hardcoded secrets (API keys, passwords, tokens) - validate before any commit

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}: All user inputs must be validated
Enable CSRF protection on all state-changing endpoints
Verify authentication and authorization for all protected endpoints
Implement rate limiting on all endpoints to prevent abuse
Ensure error messages do not leak sensitive data in responses

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,sql}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

Use parameterized queries to prevent SQL injection

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp,properties,yml,yaml,json,env,config}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

NEVER hardcode secrets in source code - ALWAYS use environment variables or a secret manager

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{py,pyi}

📄 CodeRabbit inference engine (.cursor/rules/python-coding-style.md)

**/*.{py,pyi}: Follow PEP 8 conventions in Python code
Use type annotations on all function signatures in Python
Prefer immutable data structures such as frozen dataclasses and NamedTuple in Python

**/*.{py,pyi}: Auto-format Python files using black/ruff after edit
Run type checking using mypy/pyright after editing Python files

**/*.{py,pyi}: Use Protocol from typing module for duck typing and defining object shapes in Python
Use dataclasses with @dataclass decorator for DTOs (Data Transfer Objects) in Python
Use context managers (with statement) for resource management in Python
Use generators for lazy evaluation and memory-efficient iteration in Python

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/python-coding-style.md)

**/*.py: Use black for code formatting in Python
Use isort for import sorting in Python
Use ruff for linting Python code

Avoid using print() statements in Python code; use the logging module instead

**/*.py: Retrieve secrets and API keys from environment variables using os.environ with error handling (raise KeyError if missing) rather than hardcoding credentials
Use bandit for static security analysis in Python projects

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
skills/**

📄 CodeRabbit inference engine (AGENTS.md)

New workflow contributions should land in skills/ first; skills/ is the canonical workflow surface.

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
skills/**/scripts/**

⚙️ CodeRabbit configuration file

skills/**/scripts/**: Review generated or imported scripts as untrusted-input tooling. Flag RCE, path traversal, network fetches without validation, and writes outside the expected workspace.

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
{skills,commands,agents,rules}/**

⚙️ CodeRabbit configuration file

{skills,commands,agents,rules}/**: Focus on prompt-injection resilience, tool-permission scope, destructive action guards, and secret exfiltration risks.

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
🧠 Learnings (1)
📚 Learning: 2026-06-27T15:41:48.588Z
Learnt from: gaurav0107
Repo: affaan-m/ECC PR: 2369
File: skills/continuous-learning-v2/scripts/test_parse_instinct.py:1056-1082
Timestamp: 2026-06-27T15:41:48.588Z
Learning: In this repo, the Ruff configuration for Python files under `skills/continuous-learning-v2/scripts/` selects only `E/F/I/N/W/UP`, and `flake8-pytest-style` (e.g., `PT018`) is not enabled. During code review for files in this directory, don’t assume `PT018` will be enforced by CI/ruff; only raise/test for issues that are covered by the enabled Ruff rules (or confirm the relevant rule is enabled before relying on it).

Applied to files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py

Comment on lines +1333 to +1347
if not remaining:
source_file.unlink()
return

blocks = []
for inst in remaining:
block = "---\n"
for key, value in inst.items():
if key == 'content' or key.startswith('_'):
continue
block += f"{key}: {_yaml_quote(value) if key == 'trigger' else value}\n"
block += "---\n\n"
block += inst.get('content', '') + "\n"
blocks.append(block)
source_file.write_text("\n".join(blocks), encoding="utf-8")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Promotion is not transactional across global and source files.

The current sequence can lose remaining source data or leave stale project copies after a crash or filesystem error.

  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1333-L1347: stage source replacements and atomically replace them instead of directly unlinking or truncating files.
  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1411-L1415: do not publish the global copy until specific-source cleanup succeeds, or roll back on failure.
  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1489-L1494: apply the same transaction per automatic-promotion candidate so partial multi-project cleanup cannot be reported as success.

As per coding guidelines, errors must be handled explicitly at every level.

📍 Affects 1 file
  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1333-L1347 (this comment)
  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1411-L1415
  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1489-L1494
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/continuous-learning-v2/scripts/instinct-cli.py` around lines 1333 -
1347, The promotion flow is not transactional and can leave source and global
files inconsistent after failures. In
skills/continuous-learning-v2/scripts/instinct-cli.py lines 1333-1347, stage
remaining-source content in a temporary file and atomically replace the source
instead of unlinking or directly rewriting it; in lines 1411-1415, publish the
global copy only after specific-source cleanup succeeds or roll back on failure;
and in lines 1489-1494, apply the same per-candidate transaction for automatic
promotion. Handle and propagate filesystem errors explicitly at each level, and
do not report partial cleanup as success.

Source: Coding guidelines


🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make source cleanup atomic.

unlink() and write_text() mutate the source directly. A crash or short write can delete or truncate the remaining instincts, and callers have already published the global copy by this point. Stage replacements in the same directory and atomically replace them; coordinate deletion with promotion rollback.

As per coding guidelines, errors must be handled explicitly at every level.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/continuous-learning-v2/scripts/instinct-cli.py` around lines 1333 -
1347, The remaining-instincts persistence flow must avoid direct
unlink/write_text mutations and handle failures explicitly. Update the
surrounding function that processes remaining instincts to stage serialized
content in a temporary file within source_file’s directory, atomically replace
the source only after a successful write, and coordinate the empty-result
deletion with promotion rollback. Preserve the existing output format and ensure
cleanup and errors are handled at each operation level.

Source: Coding guidelines

Comment on lines +1340 to +1345
for key, value in inst.items():
if key == 'content' or key.startswith('_'):
continue
block += f"{key}: {_yaml_quote(value) if key == 'trigger' else value}\n"
block += "---\n\n"
block += inst.get('content', '') + "\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use YAML-safe serialization for every retained field.

Only trigger passes through _yaml_quote; every other value is inserted with Python string interpolation. A surviving value containing YAML syntax, a newline, or a non-scalar type can change content or type on the next parse, so cleanup does not reliably preserve the remaining instincts. Use the existing schema-aware serializer for every field.

As per coding guidelines, external data must be treated as untrusted and schema-based validation/serialization should be used.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/continuous-learning-v2/scripts/instinct-cli.py` around lines 1340 -
1345, Update the instinct block serialization loop around the `for key, value in
inst.items()` logic to serialize every retained field with the existing
schema-aware YAML serializer, not only `trigger` via `_yaml_quote`. Preserve the
exclusions for `content` and underscore-prefixed keys, while ensuring all
remaining values are safely serialized according to the schema before appending
them to `block`.

Source: Coding guidelines

Address review feedback on affaan-m#2549 (Greptile): _remove_instinct_from_source
treated an empty parse_instinct_file() result as proof the source file
was safe to delete. A malformed file or one modified concurrently by
another session would also parse to [], so the guard was deleting content
it never actually read.

Now bails out unless the target ID is found in a successful parse -
a parse failure is never treated as "nothing left to keep".

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
skills/continuous-learning-v2/scripts/instinct-cli.py (1)

1418-1422: ⚠️ Potential issue | 🟠 Major

Promotion is still not transactional across global and source files.

Both paths publish the global copy before source cleanup completes, so filesystem or parsing failures can leave stale project copies and partial promotion state.

  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1418-L1422: commit source cleanup before publishing the specific global copy, or roll back on failure.
  • skills/continuous-learning-v2/scripts/instinct-cli.py#L1496-L1501: apply the same per-candidate transaction across every automatic-promotion source.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/continuous-learning-v2/scripts/instinct-cli.py` around lines 1418 -
1422, Make promotion transactional in the per-instinct flow around
_remove_instinct_from_source: complete and validate source cleanup before
publishing the corresponding global copy, or restore both locations if either
operation fails. Apply the same per-candidate transaction semantics to the
automatic-promotion loop at
skills/continuous-learning-v2/scripts/instinct-cli.py lines 1496-1501, ensuring
every source leaves either both updates committed or the original state intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/continuous-learning-v2/scripts/instinct-cli.py`:
- Around line 1330-1335: Strengthen the removal flow around
parse_instinct_file() so source files are fully and losslessly validated before
modification. Do not rely solely on finding instinct_id, since filtered or
malformed blocks may be discarded; either strictly validate every source block
and abort on any unknown/malformed content, or preserve unknown/raw blocks when
rewriting. Ensure remaining being empty cannot delete the file unless the
complete source was safely parsed.

---

Outside diff comments:
In `@skills/continuous-learning-v2/scripts/instinct-cli.py`:
- Around line 1418-1422: Make promotion transactional in the per-instinct flow
around _remove_instinct_from_source: complete and validate source cleanup before
publishing the corresponding global copy, or restore both locations if either
operation fails. Apply the same per-candidate transaction semantics to the
automatic-promotion loop at
skills/continuous-learning-v2/scripts/instinct-cli.py lines 1496-1501, ensuring
every source leaves either both updates committed or the original state intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5cbdfa2c-b7c1-4e14-bdd7-e843d90018a5

📥 Commits

Reviewing files that changed from the base of the PR and between f4b6f07 and 85da3db.

📒 Files selected for processing (1)
  • skills/continuous-learning-v2/scripts/instinct-cli.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}

📄 CodeRabbit inference engine (.cursor/rules/common-coding-style.md)

**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}: Always create new objects, never mutate existing ones. Use immutable patterns to prevent hidden side effects and enable safe concurrency
Organize code into many small files (200-400 lines typical, 800 lines max) organized by feature/domain rather than by type
Always handle errors explicitly at every level and never silently swallow errors
Always validate all user input before processing at system boundaries
Use schema-based validation where available
Fail fast with clear error messages when validation fails
Never trust external data (API responses, user input, file content)
Ensure code is readable and well-named
Keep functions small (less than 50 lines)
Keep files focused (less than 800 lines)
Avoid deep nesting (more than 4 levels)
Do not use hardcoded values; use constants or configuration instead

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

No hardcoded secrets (API keys, passwords, tokens) - validate before any commit

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}: All user inputs must be validated
Enable CSRF protection on all state-changing endpoints
Verify authentication and authorization for all protected endpoints
Implement rate limiting on all endpoints to prevent abuse
Ensure error messages do not leak sensitive data in responses

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,sql}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

Use parameterized queries to prevent SQL injection

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp,properties,yml,yaml,json,env,config}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

NEVER hardcode secrets in source code - ALWAYS use environment variables or a secret manager

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.{py,pyi}

📄 CodeRabbit inference engine (.cursor/rules/python-coding-style.md)

**/*.{py,pyi}: Follow PEP 8 conventions in Python code
Use type annotations on all function signatures in Python
Prefer immutable data structures such as frozen dataclasses and NamedTuple in Python

**/*.{py,pyi}: Auto-format Python files using black/ruff after edit
Run type checking using mypy/pyright after editing Python files

**/*.{py,pyi}: Use Protocol from typing module for duck typing and defining object shapes in Python
Use dataclasses with @dataclass decorator for DTOs (Data Transfer Objects) in Python
Use context managers (with statement) for resource management in Python
Use generators for lazy evaluation and memory-efficient iteration in Python

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/python-coding-style.md)

**/*.py: Use black for code formatting in Python
Use isort for import sorting in Python
Use ruff for linting Python code

Avoid using print() statements in Python code; use the logging module instead

**/*.py: Retrieve secrets and API keys from environment variables using os.environ with error handling (raise KeyError if missing) rather than hardcoding credentials
Use bandit for static security analysis in Python projects

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
skills/**

📄 CodeRabbit inference engine (AGENTS.md)

New workflow contributions should land in skills/ first; skills/ is the canonical workflow surface.

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
skills/**/scripts/**

⚙️ CodeRabbit configuration file

skills/**/scripts/**: Review generated or imported scripts as untrusted-input tooling. Flag RCE, path traversal, network fetches without validation, and writes outside the expected workspace.

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
{skills,commands,agents,rules}/**

⚙️ CodeRabbit configuration file

{skills,commands,agents,rules}/**: Focus on prompt-injection resilience, tool-permission scope, destructive action guards, and secret exfiltration risks.

Files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py
🧠 Learnings (1)
📚 Learning: 2026-06-27T15:41:48.588Z
Learnt from: gaurav0107
Repo: affaan-m/ECC PR: 2369
File: skills/continuous-learning-v2/scripts/test_parse_instinct.py:1056-1082
Timestamp: 2026-06-27T15:41:48.588Z
Learning: In this repo, the Ruff configuration for Python files under `skills/continuous-learning-v2/scripts/` selects only `E/F/I/N/W/UP`, and `flake8-pytest-style` (e.g., `PT018`) is not enabled. During code review for files in this directory, don’t assume `PT018` will be enforced by CI/ruff; only raise/test for issues that are covered by the enabled Ruff rules (or confirm the relevant rule is enabled before relying on it).

Applied to files:

  • skills/continuous-learning-v2/scripts/instinct-cli.py

Comment on lines +1330 to +1335
parsed = parse_instinct_file(source_file.read_text(encoding="utf-8"))
if not any(i.get('id') == instinct_id for i in parsed):
# Target not found in a successful parse - either already removed, or the
# file is malformed/foreign content. Either way, don't touch it: a parse
# failure must never be treated as proof the file is safe to delete.
return

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Require a complete, lossless parse before modifying the source.

Checking that one parsed block has the target ID is insufficient: parse_instinct_file() filters out blocks without id and tolerates malformed content. A file containing the target plus unreadable/foreign content can therefore pass this guard; remaining may be empty and Line 1340 can delete the whole file, or the rewrite can drop those blocks. Require strict validation of every source block, or preserve unknown/raw blocks during removal.

As per coding guidelines, external data must be treated as untrusted and schema-validated before processing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/continuous-learning-v2/scripts/instinct-cli.py` around lines 1330 -
1335, Strengthen the removal flow around parse_instinct_file() so source files
are fully and losslessly validated before modification. Do not rely solely on
finding instinct_id, since filtered or malformed blocks may be discarded; either
strictly validate every source block and abort on any unknown/malformed content,
or preserve unknown/raw blocks when rewriting. Ensure remaining being empty
cannot delete the file unless the complete source was safely parsed.

Source: Coding guidelines

@daltino daltino 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.

This PR addresses a significant issue where project-scoped copies of instincts remain after promotion, causing problems with global instinct recognition. The added function _remove_instinct_from_source appears to handle the cleanup effectively but could benefit from clarifications in its documentation and potentially additional safeguards. Consider adding a description of what happens if the instinct ID isn't found and test coverage to validate edge cases.

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