| description | Workflow to create/update package context audit files with Logic-DNA grammar (Kotlin-native). Context files inherit directory name as prefix (e.g., corecontext.md). Single root index.md for project structure. Bottom-up contexting order. |
|---|
A context file is a per-package audit file placed inside source packages (e.g., core/, core/ifs/).
Naming inherits the directory name as prefix: corecontext.md, ifscontext.md.
It acts as a Router and a Map. An AI reads this file FIRST when entering a package.
- Top-level packages (
com.imbric.core.ifs,com.imbric.core.transactions): one context file (e.g.,ifscontext.md,transactionscontext.md) - Sub-packages only get their own if they exceed ~700 lines combined or have complex logic
- No per-file audit blocks for trivial files (<50 lines, no branching)
- Target: 10 files Γ ~70 lines each = worth a context file
- Single
index.mdat project root indexes entire project
- Context files inherit the directory name as prefix
- Pattern:
{dirname}context.md - Examples:
/imbric-kt/coreβcorecontext.md/imbric-kt/core/ifsβifscontext.md/imbric-kt/core/transactionsβtransactionscontext.md
From this file alone, the AI should be able to:
- Understand what this package does and why it exists.
- Identify which specific
.ktfile to open for a given task. - Avoid opening files it does not need.
- NOT a changelog or history file. No dates, no "recently added" prose.
- NOT a TODO list. Use HANDOVER.md or the project board.
- NOT a code generation spec. The audit blocks describe existing code, not desired code.
- NOT a replacement for reading the source. It is a routing layer that tells you WHAT to read, not a substitute for reading it.
- NOT a signal that the code is messy. Good code deserves routing too.
Each audit block should provide enough logical density that an AI can understand and modify the file with 95% accuracy without reading the full source.
When an AI needs to fix a bug or add a feature:
- Read the context file of the package closest to the problem (e.g.,
corecontext.md). - Use the Index section to decide if a sub-directory is relevant.
- Use the Audit blocks to identify which
.ktfile(s) to open. - Only THEN open the actual source file. This prevents unnecessary file reads and reduces context pollution.
Each context file follows this order:
- Identity β 1-2 lines. Package path and why this folder exists.
- Rules β Strict package-specific coding instructions (thread safety, etc). Use sparingly.
- Atomic Notes β Informational patterns (
!Pattern) and architectural choices (!Decision). Do NOT use!Rulefor simple information giving. - Index β 1-line intent per sub-package or key file. Acts as a router.
- Audits β Per-file logical DNA. See Section: Audit Blocks.
For small packages (<3 files), merge Index and Audits into a flat list.
Quick lookup for AI agent to know directory structure. NOT a context file.
| index.md | context file |
|---|---|
| Single root file | Per-directory file |
| Directory structure map | Package logic map |
| "What files exist here" | "What this code does" |
| Self-maintaining registry | Static audit |
| Entry point for navigation | Entry point for understanding |
- Single
index.mdat project root - Indexes entire project structure
- Context files remain per-directory:
{dirname}context.md
- Project root directory tree with 1-line summaries
- Self-maintain instructions at top
- No logic, no DNA, no dependencies β just structure
- Registers all directories and key files
- Registers all context files when created
/imbric-kt/
βββ core/ β Core business logic
β βββ ifs/ β File system operations (GIO backend)
β βββ transactions/ β Transaction management
β βββ models/ β Data classes (FileJob, FileState)
β βββ CoreEngine.kt β Main orchestrator
β βββ Config.kt β App configuration
βββ utils/ β Shared utilities
β βββ Extensions.kt β Kotlin extension functions
β βββ Constants.kt β App-wide constants
βββ build.gradle.kts β Build configuration
βββ index.md β This file (project index)
Every index.md must include this header:
<!-- INDEX MAINTENANCE RULES
1. New file created β add to this index with 1-line summary
2. File deleted β remove from this index
3. File renamed β update entry
4. Context file created β register in this index
-->
- Leaf packages have no dependencies to understand first
- Each context file can reference its sub-packages' context files
- Agent builds understanding from concrete β abstract
- Root context file is LAST, synthesizing everything below
1. /core/ifs/gio/ β giocontext.md
2. /core/ifs/ β ifscontext.md (references giocontext.md)
3. /core/transactions/ β transactionscontext.md
4. /core/ β corecontext.md (references ifs, transactions)
5. / β projectcontext.md (root overview)
- Start at deepest directory
- Read only files in current directory
- Write context file for that directory
- Register context file in root
index.md - Move up one level
- Repeat until root
- Do NOT read all files first
- Do NOT start from root
- Do NOT skip leaf packages
- Do NOT create context files for directories with <3 files (mention in parent's index)
- NO bold text for keys. Use plain
Key: Value. - NO full sentences. Use fragments.
- Fragments must retain technical specificity. "Resets currentIndex if out of bounds" is correct. "Adjusts focus" is too vague.
- NO nested lists deeper than 2 levels.
- NO changelogs, dates, or version numbers.
- NO clustered blocks. Use blank lines between Role, /DNA/, Dependencies, and API.
- Inline code backticks for identifiers:
GioBackend,StateFlow,limitedParallelism.
Compressed notation for mapping causality in code. Optimized for LLM parsing.
Symbols:
->: Causes / Triggers / Leads to=>: Returns / Resolves to++/--: Increments / Decrements stateem:: Emits to Flow / updates StateFlowcall:: Invokes a methodsuspend: Suspending function (coroutine)if(): Conditional branchwait: Pauses for async resolutionC|F: Success (Completed) or Failure[...]: Logic block or grouped operation
Kotlin examples:
[call:backend.copy(job) -> if(cancelled) em:_progress.error | em:_progress.done]
[suspend withContext(IO) -> gfile.queryInfo(attrs, cancellable) => FileInfo]
[em:conflictDetected -> wait channel.receive() -> resume with action]
-
Logical Density: Exactly ONE
/DNA/line per file. If multiple loops exist, merge using[...] + [...]grouping. -
Spacing: Blank line between
/DNA/and Dependencies, another before API section. -
Dependencies: Inline on a single line per key.
-
Kotlin:
kotlinx.coroutines{flow, channel},org.gnome.gio{File, Cancellable} -
Internal:
.ifs.IOBackend,.models.FileJob -
Short lists (1-2 items) skip braces:
.IOBackend,.Cancellable
-
-
Caveats: Use for Kotlin-specific gotchas like backing field quirks, initialization ordering, or FFM memory lifetimes.
Prefix: !Pattern, !Decision, or !Rule
Format: !Category: [X > Y] - Reason: one-line explanation.
Kotlin examples:
!Decision: [sync-on-IO > native async] - Reason: GIO async requires GLib MainLoop; coroutine wrappers not needed for Cancellable-enabled sync ops.!Pattern: [Cancellable per FileJob] - Reason: Shared cancellables cause cross-job cancellation; each job gets a fresh Cancellable injected at submit time.!Pattern: [Flow for progress > callback] - Reason: FileProgressCallback updates MutableStateFlow; Compose observes via collectAsState().!Rule: [Call ensureInitialized before GIO] - Reason: JVM doesn't runfor interface static methods; missing =UnsupportedOperationException.
Authorship Protocol:
- NEVER add a Rule, Atomic Note, or Maintenance entry without explicit user permission.
- To suggest a new note, confirm the pattern exists across 2+ files, present with reasoning.
- A wrong rule is worse than no rule.
Each .kt file gets one block.
Schema:
### [FILE: FileName.kt] [STATUS]
Role: One-line intent.
/DNA/: Compressed causal map of the core logic loops.
- SrcDeps: .ifs.IOBackend, .models.FileJob
- SysDeps: kotlinx.coroutines{flow}, org.gnome.gio{File, Cancellable}
API:
- ClassName:
- fun method(args): ReturnType β technically specific contract
- StateFlow<Type> β observable state
!Caveat: Gotcha or non-obvious behavior.
Status tags: [DONE], [USABLE], [WIP], [STUB], [DEPRECATED]
- [USABLE] = technically complete, not yet reviewed by user
- Never use [DONE] without user confirmation
Deprecated Methods: Keep OUT of API section. Document as !Caveat line.
- Never write prose paragraphs in an audit block.
- Never duplicate information that belongs in HANDOVER.md or AGENTS.md.
- Never audit trivial files (<50 lines, single class, no branching) β mention them in Index, skip the block.
- Never use bold, italic, or decorative markdown.
- Never include coroutine plumbing boilerplate in audit (the LLM already knows how
withContextworks).
When auditing Kotlin files, highlight these if present:
- Explicit backing fields:
val isCancelled: Boolean get() = _isCancelledβ note the_proppattern - Sealed class hierarchies: algebraic types used for state machines
- Flow bridging:
channelFlow { },callbackFlow { },MutableStateFlow - FFI memory lifetimes: Arena usage in generated bindings
- Cancellable injection: per-job vs shared patterns
To verify an audit block hasn't missed public API, use grep to list top-level declarations:
grep -n "^\(fun \|val \|var \|class \|object \|sealed \|data class \|interface \)" src/main/kotlin/com/imbric/core/FILE.ktPrivate/internal declarations (no private or internal modifier) should be in the audit API if they're part of the package's public contract.
To verify context files follow naming convention:
find . -name "*context.md" -type f | sortExpected pattern: {dirname}context.md in each package directory.
- Sync Protocol: When file logic changes, diff the existing audit block against the source. Update ONLY the changed parts. Preserve unchanged wording.
- New Packages: Add a context file BEFORE or during implementation, not after. Use
{dirname}context.mdnaming. - New Files: Register in root
index.mdwith 1-line summary. - Context Files: Register in root
index.mdwhen created. - Pruning: If HANDOVER.md grows too large, migrate file-level detail to the relevant context file.