feat: Routine authoring and schedule previews #31

Merged
bjoern merged 4 commits from feat/routine-authoring into main 2026-10-22 21:14:43 +02:00
Member

Brings the Routine authoring plan slice forward with editable routine files and a /routines overview (ADR 0015, 0020, 0024).

What's in

  • UI: daily/weekday times, one-shot dates, intervals with active hours and raw cron; header fields, instruction editing and Markdown previews; schedule summaries and five possible future occurrences with time zones and offsets.
  • Use cases: Form, Text and Preview share one draft and the existing Save, concurrency and History flow. Canonical header edits preserve untouched invalid values and instruction bytes. New routines start valid and paused; invalid and legacy files remain reachable.
  • Domain: pure schedule arithmetic for reuse by the future scheduler, with explicit interval anchors, active-window filtering and documented DST behavior. The preview captures a stable reference and treats it as hypothetical activation.
  • Header safety: the shared parser rejects recursive aliases and bounds expanded size and depth before forms or canonical writers traverse values. Invalid drafts remain repairable in Text; ordinary shared aliases are supported.
  • Caps: RoutineLimits supplies the validator and form with ordinary defaults of 50 rounds / 10 minutes and override bounds of 1–200 rounds / 1–120 minutes. Reflection fields identify growth-mode defaults.
  • Documentation and real-use-case seed samples cover paused interval and future one-shot routines.

Tests

Serial solution build passed with zero warnings. All 5,380 tests passed locally and again with TZ=UTC. New coverage checks calendar/interval/DST rules, invalid headers, body-byte preservation, stale-write refusal, familiar scoping, overview refresh, shared drafts and stable references even when an invalid file opens in Text first. Coverage also pins incomplete summaries, per-format starter limits, and the overview's injected clock and zone; independent isolated probes killed clock, cap-default and interval-wrap mutations, plus both header-guard mutations.

Browser-verified

Drove the seeded sample world through all schedule modes, invalid fields, shared unsaved Form/Text/Preview drafts, Markdown rendering, saving and overview refresh. Verified autumn folds and spring gaps, plus desktop and mobile layouts without horizontal overflow. Repeated verification with the repository's browser-test launcher and local stub covered Niko's seeded quiet-check-in.md and book-release.md, breadcrumb navigation, saving and reload, cyclic-draft fallback and repair, and mobile width. No model calls were needed.

Automatic execution, Run now, actual activation state and run outcomes remain in the scheduler slice. The UI visibly states that automatic runs are unavailable; previews do not queue work. No companion library changes or merge-order dependencies.

Brings the Routine authoring plan slice forward with editable routine files and a `/routines` overview (ADR 0015, 0020, 0024). **What's in** - UI: daily/weekday times, one-shot dates, intervals with active hours and raw cron; header fields, instruction editing and Markdown previews; schedule summaries and five possible future occurrences with time zones and offsets. - Use cases: Form, Text and Preview share one draft and the existing Save, concurrency and History flow. Canonical header edits preserve untouched invalid values and instruction bytes. New routines start valid and paused; invalid and legacy files remain reachable. - Domain: pure schedule arithmetic for reuse by the future scheduler, with explicit interval anchors, active-window filtering and documented DST behavior. The preview captures a stable reference and treats it as hypothetical activation. - Header safety: the shared parser rejects recursive aliases and bounds expanded size and depth before forms or canonical writers traverse values. Invalid drafts remain repairable in Text; ordinary shared aliases are supported. - Caps: `RoutineLimits` supplies the validator and form with ordinary defaults of 50 rounds / 10 minutes and override bounds of 1–200 rounds / 1–120 minutes. Reflection fields identify growth-mode defaults. - Documentation and real-use-case seed samples cover paused interval and future one-shot routines. **Tests** Serial solution build passed with zero warnings. All 5,380 tests passed locally and again with `TZ=UTC`. New coverage checks calendar/interval/DST rules, invalid headers, body-byte preservation, stale-write refusal, familiar scoping, overview refresh, shared drafts and stable references even when an invalid file opens in Text first. Coverage also pins incomplete summaries, per-format starter limits, and the overview's injected clock and zone; independent isolated probes killed clock, cap-default and interval-wrap mutations, plus both header-guard mutations. **Browser-verified** Drove the seeded sample world through all schedule modes, invalid fields, shared unsaved Form/Text/Preview drafts, Markdown rendering, saving and overview refresh. Verified autumn folds and spring gaps, plus desktop and mobile layouts without horizontal overflow. Repeated verification with the repository's browser-test launcher and local stub covered Niko's seeded `quiet-check-in.md` and `book-release.md`, breadcrumb navigation, saving and reload, cyclic-draft fallback and repair, and mobile width. No model calls were needed. Automatic execution, Run now, actual activation state and run outcomes remain in the scheduler slice. The UI visibly states that automatic runs are unavailable; previews do not queue work. No companion library changes or merge-order dependencies.
Add routine authoring and schedule previews
All checks were successful
CI / build (pull_request) Successful in 27s
CI / image (pull_request) Successful in 34s
CI / test (pull_request) Successful in 2m25s
d393e435f0
scarlet changed title from Add routine authoring and schedule previews to feat: Routine authoring and schedule previews 2026-10-22 19:28:35 +02:00

🔄 Auto-updating coverage report — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip.

Commit: ccf62e7 · Generated: 2026-10-22 19:08:16 UTC · Revision: #5

Summary

Summary
Generated on: 10/22/2026 - 19:08:16
Coverage date: 10/22/2026 - 19:06:21 - 10/22/2026 - 19:08:12
Parser: MultiReport (5x Cobertura)
Assemblies: 8
Classes: 505
Files: 257
Line coverage: 96.2% (18483 of 19208)
Covered lines: 18483
Uncovered lines: 725
Coverable lines: 19208
Total lines: 37595
Branch coverage: 92.5% (13257 of 14331)
Covered branches: 13257
Total branches: 14331
Method coverage: Feature is only available for sponsors

Coverage

Shikigami.BlazorAdapter - 95.6%
Name Line Branch
Shikigami.BlazorAdapter 95.6% 89.4%
Shikigami.BlazorAdapter.BlazorAdapterAssembly 100%
Shikigami.BlazorAdapter.Cast.CastActionFailed 100%
Shikigami.BlazorAdapter.Cast.CastEffects 93.3% 93.7%
Shikigami.BlazorAdapter.Cast.CastLoaded 100%
Shikigami.BlazorAdapter.Cast.CastReducers 93.3% 50%
Shikigami.BlazorAdapter.Cast.CastState 100% 100%
Shikigami.BlazorAdapter.Cast.CreateFamiliarFailed 100%
Shikigami.BlazorAdapter.Cast.CreateFamiliarRequested 100%
Shikigami.BlazorAdapter.Cast.DuplicateFamiliarRequested 100%
Shikigami.BlazorAdapter.Cast.FamiliarAvatar 100% 75%
Shikigami.BlazorAdapter.Cast.FamiliarCreated 100%
Shikigami.BlazorAdapter.Cast.NewFamiliarDialog 97.2% 83.3%
Shikigami.BlazorAdapter.Cast.PurgeFamiliarRequested 100%
Shikigami.BlazorAdapter.Cast.SetFamiliarArchivedRequested 100%
Shikigami.BlazorAdapter.Cast.SetFamiliarTrashedRequested 100%
Shikigami.BlazorAdapter.Cast.TrashPage 89.4% 93.7%
Shikigami.BlazorAdapter.EffectCalls 100%
Shikigami.BlazorAdapter.Files.ConflictSettled 100%
Shikigami.BlazorAdapter.Files.DismissFileError 100%
Shikigami.BlazorAdapter.Files.EntryMissing 100%
Shikigami.BlazorAdapter.Files.EntryOpened 100%
Shikigami.BlazorAdapter.Files.FileActionDone 100%
Shikigami.BlazorAdapter.Files.FileActionFailed 100%
Shikigami.BlazorAdapter.Files.FileActionRequested 100%
Shikigami.BlazorAdapter.Files.FileLinks 100% 100%
Shikigami.BlazorAdapter.Files.FilePane 95.2% 88.7%
Shikigami.BlazorAdapter.Files.FilePaneClosed 100%
Shikigami.BlazorAdapter.Files.FilePathBreadcrumb 100% 100%
Shikigami.BlazorAdapter.Files.FilesEffects 98.2% 94.7%
Shikigami.BlazorAdapter.Files.FilesPage 96.9% 97%
Shikigami.BlazorAdapter.Files.FilesReducers 100% 82%
Shikigami.BlazorAdapter.Files.FilesState 100% 100%
Shikigami.BlazorAdapter.Files.FileTreeBranch 100% 100%
Shikigami.BlazorAdapter.Files.FolderPane 92.3% 86.3%
Shikigami.BlazorAdapter.Files.JournalOverviewPane 100% 88.8%
Shikigami.BlazorAdapter.Files.LoadFiles 100%
Shikigami.BlazorAdapter.Files.MemoryForm 100% 94.4%
Shikigami.BlazorAdapter.Files.MemoryOverviewPane 100% 96.1%
Shikigami.BlazorAdapter.Files.OpenEntry 100%
Shikigami.BlazorAdapter.Files.RoutineForm 78.6% 86.4%
Shikigami.BlazorAdapter.Files.RoutineOverviewPane 100% 94.4%
Shikigami.BlazorAdapter.Files.SaveLanded 100%
Shikigami.BlazorAdapter.Files.SaveRefused 100%
Shikigami.BlazorAdapter.Files.SaveText 100%
Shikigami.BlazorAdapter.Files.SkillForm 100% 100%
Shikigami.BlazorAdapter.Files.TreeFailed 100%
Shikigami.BlazorAdapter.Files.TreeLoaded 100%
Shikigami.BlazorAdapter.Home.HomePage 88.2% 93.7%
Shikigami.BlazorAdapter.Notifications.CoalescingBridge`1 94.4% 80%
Shikigami.BlazorAdapter.Notifications.DomainChangedBridge 100%
Shikigami.BlazorAdapter.Notifications.DomainChangesReceived 100% 100%
Shikigami.BlazorAdapter.Notifications.FamiliarEventsBridge 100%
Shikigami.BlazorAdapter.Notifications.FamiliarEventsReceived 100%
Shikigami.BlazorAdapter.Profile.AvatarChosen 100%
Shikigami.BlazorAdapter.Profile.AvatarClearRequested 100%
Shikigami.BlazorAdapter.Profile.AvatarFailed 100%
Shikigami.BlazorAdapter.Profile.AvatarSaved 100%
Shikigami.BlazorAdapter.Profile.CreatedWithoutAvatar 100%
Shikigami.BlazorAdapter.Profile.ExpressionsEditor 86.6% 88.8%
Shikigami.BlazorAdapter.Profile.LoadProfile 100%
Shikigami.BlazorAdapter.Profile.PersonaEditor 100% 97.2%
Shikigami.BlazorAdapter.Profile.PersonaReloaded 100%
Shikigami.BlazorAdapter.Profile.PersonaSave 100%
Shikigami.BlazorAdapter.Profile.PersonaSaved 100%
Shikigami.BlazorAdapter.Profile.PersonaSaveFailed 100%
Shikigami.BlazorAdapter.Profile.ProfileEffects 92.9% 85%
Shikigami.BlazorAdapter.Profile.ProfileLoaded 100%
Shikigami.BlazorAdapter.Profile.ProfileMissing 100%
Shikigami.BlazorAdapter.Profile.ProfilePage 90% 87.3%
Shikigami.BlazorAdapter.Profile.ProfileReducers 97.3% 53.9%
Shikigami.BlazorAdapter.Profile.ProfileRefreshed 100%
Shikigami.BlazorAdapter.Profile.ProfileState 100% 100%
Shikigami.BlazorAdapter.Profile.ReloadPersona 100%
Shikigami.BlazorAdapter.Profile.RevertSelfRequested 100%
Shikigami.BlazorAdapter.Profile.SavePersonaRequested 100%
Shikigami.BlazorAdapter.Profile.SaveSettingsRequested 100%
Shikigami.BlazorAdapter.Profile.SelfLayer 92.3% 87.5%
Shikigami.BlazorAdapter.Profile.SettingsSaved 100%
Shikigami.BlazorAdapter.Profile.SettingsSaveFailed 100%
Shikigami.BlazorAdapter.Settings.BackupFailed 100%
Shikigami.BlazorAdapter.Settings.BackupSettingsLoaded 100%
Shikigami.BlazorAdapter.Settings.BackupSettingsLoadFailed 100%
Shikigami.BlazorAdapter.Settings.BackupsSection 100% 100%
Shikigami.BlazorAdapter.Settings.BackupsSettingsEffects 100%
Shikigami.BlazorAdapter.Settings.BackupsSettingsReducers 100%
Shikigami.BlazorAdapter.Settings.BackupsSettingsState 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceCss 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceEffects 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceLoaded 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceLoadFailed 100%
Shikigami.BlazorAdapter.Settings.ChatAppearancePreview 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceReducers 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceSaved 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceSaveFailed 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceSection 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceState 100%
Shikigami.BlazorAdapter.Settings.DefaultsSection 94.5% 85.7%
Shikigami.BlazorAdapter.Settings.DefaultsSettingsEffects 100%
Shikigami.BlazorAdapter.Settings.DefaultsSettingsReducers 100% 100%
Shikigami.BlazorAdapter.Settings.DefaultsSettingsState 100%
Shikigami.BlazorAdapter.Settings.LoadProviderSettings 100%
Shikigami.BlazorAdapter.Settings.ModelCatalogLoaded 100%
Shikigami.BlazorAdapter.Settings.ModelCatalogLoadFailed 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsLoaded 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsLoadFailed 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsSaved 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsSaveFailed 100%
Shikigami.BlazorAdapter.Settings.ModelHints 100% 100%
Shikigami.BlazorAdapter.Settings.ModelPicker 100% 98.2%
Shikigami.BlazorAdapter.Settings.Money 100%
Shikigami.BlazorAdapter.Settings.OpenRouterKeySaved 100%
Shikigami.BlazorAdapter.Settings.OpenRouterKeySaveFailed 100%
Shikigami.BlazorAdapter.Settings.ProviderKeyChecked 100%
Shikigami.BlazorAdapter.Settings.ProviderSection 100% 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsEffects 100% 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsLoaded 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsReducers 100% 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsState 100% 100%
Shikigami.BlazorAdapter.Settings.SaveChatAppearanceRequested 100%
Shikigami.BlazorAdapter.Settings.SaveModelDefaultsRequested 100%
Shikigami.BlazorAdapter.Settings.SaveOpenRouterKeyRequested 100%
Shikigami.BlazorAdapter.Shell.CastRail 100% 100%
Shikigami.Capabilities.Contracts - 97.8%
Name Line Branch
Shikigami.Capabilities.Contracts 97.8% 100%
Shikigami.Capabilities.Contracts.CapabilityContext 100%
Shikigami.Capabilities.Contracts.CapabilityDefinition 100% 100%
Shikigami.Capabilities.Contracts.CapabilityEntry 100%
Shikigami.Capabilities.Contracts.CapabilityError 100%
Shikigami.Capabilities.Contracts.CapabilityFile 100%
Shikigami.Capabilities.Contracts.CapabilityListing 100%
Shikigami.Capabilities.Contracts.CapabilityMount 100% 100%
Shikigami.Capabilities.Contracts.CapabilityRegistration 100% 100%
Shikigami.Capabilities.Contracts.CapabilityResult`1 66.6%
Shikigami.Capabilities.Contracts.CapabilityTool 100%
Shikigami.Capabilities.Contracts.CapabilityToolResult 100%
Shikigami.Capabilities.Contracts.CapabilityValidationProblem 100%
Shikigami.Capabilities.Contracts.MountAccessRule 100%
Shikigami.Capabilities.TestFixture - 97.7%
Name Line Branch
Shikigami.Capabilities.TestFixture 97.7% 91.6%
Shikigami.Capabilities.TestFixture.FixtureHandler 100%
Shikigami.Capabilities.TestFixture.FixtureModule 100% 100%
Shikigami.Capabilities.TestFixture.FixtureProvider 94.4% 78.5%
Shikigami.Capabilities.TestFixture.FixtureState 100%
Shikigami.Capabilities.TestFixture.FixtureValidator 100% 100%
Shikigami.Domain - 98.1%
Name Line Branch
Shikigami.Domain 98.1% 91.8%
Shikigami.Domain.Familiars.AccentPalette 100%
Shikigami.Domain.Familiars.ColourPair 100% 100%
Shikigami.Domain.Familiars.Expression 100% 100%
Shikigami.Domain.Familiars.ExpressionSet 100% 100%
Shikigami.Domain.Familiars.Familiar 100% 90.2%
Shikigami.Domain.Familiars.LearningSettings 100%
Shikigami.Domain.Familiars.MemoryBudgets 100% 100%
Shikigami.Domain.Familiars.ModelChoice 100% 100%
Shikigami.Domain.Familiars.OutreachSettings 100% 100%
Shikigami.Domain.Familiars.QuietHours 100% 87.5%
Shikigami.Domain.Files.BlobContent 100% 75%
Shikigami.Domain.Files.BlobSha 87.5% 100%
Shikigami.Domain.Files.DefaultLayout 100%
Shikigami.Domain.Files.FileActor 100%
Shikigami.Domain.Files.FileAuthor 100% 100%
Shikigami.Domain.Files.FileContent 100% 100%
Shikigami.Domain.Files.FileNode 100% 90%
Shikigami.Domain.Files.FilePath 100% 97.8%
Shikigami.Domain.Files.FileRevision 100% 87.5%
Shikigami.Domain.Files.LocalDates 100%
Shikigami.Domain.Files.MediaTypes 100% 100%
Shikigami.Domain.Files.Permissions 100% 100%
Shikigami.Domain.Files.RunActor 100% 100%
Shikigami.Domain.Files.Slug 100% 100%
Shikigami.Domain.Files.TextContent 100% 100%
Shikigami.Domain.Files.TrashPath 100% 100%
Shikigami.Domain.Routines.RoutineSchedule 94.4% 89.8%
Shikigami.Domain.Settings.AppSetting 100%
Shikigami.Domain.Text 100% 100%
System.Text.RegularExpressions.Generated 96.2% 85.2%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_0
94.8% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_2
96.8% 93.7%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__MediaTypeShape_3
95.9% 92.1%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__NamePattern_1
97.2% 94.4%
Shikigami.Infrastructure - 97.2%
Name Line Branch
Shikigami.Infrastructure 97.2% 86.7%
Shikigami.Infrastructure.Backups.BackupArtifactName 100% 100%
Shikigami.Infrastructure.Backups.BackupOptions 100%
Shikigami.Infrastructure.Backups.BackupSchedule 100% 83.3%
Shikigami.Infrastructure.Backups.BackupScheduler 96.6% 87.5%
Shikigami.Infrastructure.Backups.BackupWriter 98.5% 92.8%
Shikigami.Infrastructure.Backups.DatabaseFingerprint 91.9% 97%
Shikigami.Infrastructure.Backups.FileSystemBackupStore 100% 100%
Shikigami.Infrastructure.Backups.OwnerOnlyFile 100% 100%
Shikigami.Infrastructure.Backups.PreMigrationBackup 90% 100%
Shikigami.Infrastructure.Backups.SqliteSnapshot 88.2% 75%
Shikigami.Infrastructure.Blobs.BlobSweep 100% 100%
Shikigami.Infrastructure.Blobs.BlobSweepOptions 100% 100%
Shikigami.Infrastructure.Blobs.BlobSweepResult 100%
Shikigami.Infrastructure.Blobs.FileSystemBlobStore 95.9% 97%
Shikigami.Infrastructure.DailyMaintenanceService 97.8% 91.6%
Shikigami.Infrastructure.DependencyInjection 100% 100%
Shikigami.Infrastructure.Notifications.InProcessBus`1 100% 100%
Shikigami.Infrastructure.Persistence.Configurations.AppSettingConfiguration 100%
Shikigami.Infrastructure.Persistence.Configurations.FamiliarConfiguration 100%
Shikigami.Infrastructure.Persistence.Configurations.FileNodeConfiguration 100%
Shikigami.Infrastructure.Persistence.Configurations.FileRevisionConfigurati
on
100%
Shikigami.Infrastructure.Persistence.Configurations.UnreferencedBlobConfigu
ration
100%
Shikigami.Infrastructure.Persistence.Converters.BlobShaConverter 100%
Shikigami.Infrastructure.Persistence.Converters.ExpressionSetConverter 100% 100%
Shikigami.Infrastructure.Persistence.Converters.FilePathConverter 100%
Shikigami.Infrastructure.Persistence.Converters.Json 100% 100%
Shikigami.Infrastructure.Persistence.Converters.OutreachSettingsConverter 100% 100%
Shikigami.Infrastructure.Persistence.Converters.UtcTicksConverter 100%
Shikigami.Infrastructure.Persistence.DatabaseMigrator 100%
Shikigami.Infrastructure.Persistence.Migrations.AppSettings 100%
Shikigami.Infrastructure.Persistence.Migrations.FileCreatedBy 98%
Shikigami.Infrastructure.Persistence.Migrations.Initial 97.9%
Shikigami.Infrastructure.Persistence.Migrations.Profile 96.2%
Shikigami.Infrastructure.Persistence.Migrations.ShikigamiDbContextModelSnap
shot
100%
Shikigami.Infrastructure.Persistence.ShikigamiDbContext 98.6% 100%
Shikigami.Infrastructure.Persistence.ShikigamiDbContextFactory 0%
Shikigami.Infrastructure.Persistence.SqlitePragmaInterceptor 100% 100%
Shikigami.Infrastructure.Persistence.Stores.EfFamiliarStore 100%
Shikigami.Infrastructure.Persistence.Stores.EfFileStore 100% 100%
Shikigami.Infrastructure.Persistence.UnreferencedBlob 100%
Shikigami.Infrastructure.Provider.OpenRouterKeySource 100% 100%
Shikigami.Infrastructure.Provider.OpenRouterModelProvider 100% 93.4%
Shikigami.Infrastructure.Provider.OpenRouterOptions 100% 50%
Shikigami.Infrastructure.Provider.ResolvedKey 100% 50%
Shikigami.Infrastructure.Settings.EfAppSettingsStore 100% 100%
System.Text.RegularExpressions.Generated 81.4% 64.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F3A4F28468B24E9C
234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Pattern_0
84% 65.7%
Shikigami.Kernel - 90.9%
Name Line Branch
Shikigami.Kernel 90.9% 75%
Shikigami.Kernel.Err`1 100%
Shikigami.Kernel.Ok`1 100%
Shikigami.Kernel.Result`1 88.8% 75%
Shikigami.Server - 100%
Name Line Branch
Shikigami.Server 100% 95.3%
Program 100% 100%
Shikigami.Server.Backups.BackupConfiguration 100% 100%
Shikigami.Server.Components.App 100%
Shikigami.Server.Components.Layout.AppHeader 100% 78.5%
Shikigami.Server.Components.Layout.MainLayout 100%
Shikigami.Server.Components.Pages.Gate 100% 100%
Shikigami.Server.Diagnostics.SeedOnStart 100% 100%
Shikigami.Server.Provider.OpenRouterConfiguration 100% 100%
Shikigami.Server.Security.AccessGate 100% 87.5%
Shikigami.Server.Security.AccessSecret 100% 100%
Shikigami.Server.Security.GateThrottle 100% 100%
Shikigami.Server.Security.ProxyNetwork 100% 100%
Shikigami.Server.VolumeStartupValidator 100% 100%
Shikigami.UseCases - 95.7%
Name Line Branch
Shikigami.UseCases 95.7% 93.1%
Shikigami.UseCases.Backups.BackupArtifact 100%
Shikigami.UseCases.Backups.BackupFailure 100%
Shikigami.UseCases.Backups.BackupJobState 100%
Shikigami.UseCases.Backups.BackupPolicy 100%
Shikigami.UseCases.Backups.BackupStatusView 100% 100%
Shikigami.UseCases.Backups.DatabaseSnapshot 100%
Shikigami.UseCases.Backups.DownloadDatabaseSnapshot 100%
Shikigami.UseCases.Backups.GetBackupStatus 100%
Shikigami.UseCases.Backups.IBackupStore 0%
Shikigami.UseCases.Backups.RunBackupNow 100%
Shikigami.UseCases.Capabilities.CapabilityContexts 100% 87.5%
Shikigami.UseCases.Capabilities.CapabilityRegistry 97.2% 92%
Shikigami.UseCases.Capabilities.InvokeCapabilityTool 100% 90%
Shikigami.UseCases.Capabilities.ToolSchemas 86.8% 72.1%
Shikigami.UseCases.DependencyInjection 100%
Shikigami.UseCases.Diagnostics.SeedDevData 91.1% 33.3%
Shikigami.UseCases.Familiars.AvatarImage 100%
Shikigami.UseCases.Familiars.ClearFamiliarAvatar 100%
Shikigami.UseCases.Familiars.CreateFamiliar 97.2% 70%
Shikigami.UseCases.Familiars.DuplicateFamiliar 96.7% 91.6%
Shikigami.UseCases.Familiars.ExpressionView 100%
Shikigami.UseCases.Familiars.FamiliarDetail 100%
Shikigami.UseCases.Familiars.FamiliarEvent 100%
Shikigami.UseCases.Familiars.FamiliarFiles 100% 100%
Shikigami.UseCases.Familiars.FamiliarLimits 71.4%
Shikigami.UseCases.Familiars.FamiliarPersona 96.8% 90%
Shikigami.UseCases.Familiars.FamiliarSettings 100% 100%
Shikigami.UseCases.Familiars.FamiliarSummary 100% 100%
Shikigami.UseCases.Familiars.FamiliarTemplates 100% 100%
Shikigami.UseCases.Familiars.FamiliarViews 100% 94.4%
Shikigami.UseCases.Familiars.GetFamiliar 100% 100%
Shikigami.UseCases.Familiars.ListFamiliars 100%
Shikigami.UseCases.Familiars.PersonaFile 100%
Shikigami.UseCases.Familiars.PurgeFamiliar 100%
Shikigami.UseCases.Familiars.ReadFamiliarAvatar 100% 87.5%
Shikigami.UseCases.Familiars.SaveFamiliarSettings 94.7% 87.5%
Shikigami.UseCases.Familiars.SelfRevision 100%
Shikigami.UseCases.Familiars.SetFamiliarArchived 100% 100%
Shikigami.UseCases.Familiars.SetFamiliarAvatar 100% 100%
Shikigami.UseCases.Familiars.SetFamiliarTrashed 100% 100%
Shikigami.UseCases.Familiars.ToolGroupCatalog 66.6%
Shikigami.UseCases.Familiars.ToolGroupInfo 100%
Shikigami.UseCases.Files.Browser.FileBrowser 94.4% 87.9%
Shikigami.UseCases.Files.Browser.FileBytes 100%
Shikigami.UseCases.Files.Browser.FileItem 100%
Shikigami.UseCases.Files.Browser.FileOk`1 100%
Shikigami.UseCases.Files.Browser.FileRefusal 100%
Shikigami.UseCases.Files.Browser.FileRefused`1 100%
Shikigami.UseCases.Files.Browser.FileRevisionView 100%
Shikigami.UseCases.Files.Browser.FileView 100%
Shikigami.UseCases.Files.Browser.JournalOverview 100%
Shikigami.UseCases.Files.Browser.JournalOverviewEntry 100%
Shikigami.UseCases.Files.Browser.MemoryBudget 100%
Shikigami.UseCases.Files.Browser.MemoryBudgetUse 100%
Shikigami.UseCases.Files.Browser.MemoryDraft 100%
Shikigami.UseCases.Files.Browser.MemoryOverview 100%
Shikigami.UseCases.Files.Browser.MemoryOverviewEntry 100%
Shikigami.UseCases.Files.Browser.MemoryOverviewLimits 100%
Shikigami.UseCases.Files.Browser.RoutineDraft 100%
Shikigami.UseCases.Files.Browser.RoutineForms 89.5% 80.8%
Shikigami.UseCases.Files.Browser.RoutineOverview 100%
Shikigami.UseCases.Files.Browser.RoutineOverviewEntry 100%
Shikigami.UseCases.Files.Browser.RoutinePreview 100%
Shikigami.UseCases.Files.Browser.SkillView 100%
Shikigami.UseCases.Files.Browser.SpecialForms 98.4% 90.5%
Shikigami.UseCases.Files.FamiliarWriteLocks 100% 100%
Shikigami.UseCases.Files.FileAuthors 100% 100%
Shikigami.UseCases.Files.FileMaintenance 100% 90%
Shikigami.UseCases.Files.FileMaintenanceResult 100%
Shikigami.UseCases.Files.FileSystem 98.5% 95.3%
Shikigami.UseCases.Files.FileWriteRefused 100%
Shikigami.UseCases.Files.FileWritten 100%
Shikigami.UseCases.Files.FsError 100% 50%
Shikigami.UseCases.Files.FsResult`1 100% 50%
Shikigami.UseCases.Files.Mounts.CapabilityMountAdapter 75% 65.4%
Shikigami.UseCases.Files.Mounts.FileEntry 100%
Shikigami.UseCases.Files.Mounts.FileRead 100%
Shikigami.UseCases.Files.Mounts.GeneratedMount 100% 100%
Shikigami.UseCases.Files.Mounts.Mount 100% 100%
Shikigami.UseCases.Files.Mounts.MountTable 97.1% 90.3%
Shikigami.UseCases.Files.Mounts.MountTables 100% 100%
Shikigami.UseCases.Files.Mounts.StoredMount 100% 100%
Shikigami.UseCases.Files.SeedDefaultLayout 100% 100%
Shikigami.UseCases.Files.Special.Budgets 100% 96.6%
Shikigami.UseCases.Files.Special.FrontMatter 100% 86.2%
Shikigami.UseCases.Files.Special.HeaderReader 100% 87.8%
Shikigami.UseCases.Files.Special.HeaderValue 100% 100%
Shikigami.UseCases.Files.Special.HeaderWriter 96% 90.6%
Shikigami.UseCases.Files.Special.MemoryFile 100% 87.5%
Shikigami.UseCases.Files.Special.MemoryUse 100%
Shikigami.UseCases.Files.Special.Numbers 100%
Shikigami.UseCases.Files.Special.RoutineFile 100% 99.1%
Shikigami.UseCases.Files.Special.SkillFile 100% 95.2%
Shikigami.UseCases.Files.Special.SpecialFolders 100% 100%
Shikigami.UseCases.Files.Special.ValidationProblem 100%
Shikigami.UseCases.Files.StoredBlob 100%
Shikigami.UseCases.Files.Utf8Order 100%
Shikigami.UseCases.Notifications.DomainChanged 100%
Shikigami.UseCases.Settings.AppearanceColour 100% 100%
Shikigami.UseCases.Settings.CatalogModel 100% 100%
Shikigami.UseCases.Settings.ChatAppearance 100%
Shikigami.UseCases.Settings.ChatAppearanceJson 100% 100%
Shikigami.UseCases.Settings.ChatAppearanceLimits 100% 100%
Shikigami.UseCases.Settings.CheckOpenRouterKey 100%
Shikigami.UseCases.Settings.GetChatAppearance 100%
Shikigami.UseCases.Settings.GetModelCatalog 100% 100%
Shikigami.UseCases.Settings.GetModelDefaults 100% 83.3%
Shikigami.UseCases.Settings.GetProviderSettings 100%
Shikigami.UseCases.Settings.ModelCatalog 100%
Shikigami.UseCases.Settings.ModelDefaults 100% 100%
Shikigami.UseCases.Settings.ProviderKeyInfo 100%
Shikigami.UseCases.Settings.ProviderKeyState 100%
Shikigami.UseCases.Settings.ProviderSettingsView 100% 100%
Shikigami.UseCases.Settings.RemoveOpenRouterKey 100%
Shikigami.UseCases.Settings.SaveChatAppearance 100% 100%
Shikigami.UseCases.Settings.SaveModelDefaults 100% 100%
Shikigami.UseCases.Settings.SaveOpenRouterKey 100% 100%
Shikigami.UseCases.Shell.AllowEveryCommand 100%
Shikigami.UseCases.Shell.Commands.Basename 100% 100%
Shikigami.UseCases.Shell.Commands.Builtin 100% 100%
Shikigami.UseCases.Shell.Commands.Cat 100% 100%
Shikigami.UseCases.Shell.Commands.Cd 97.5% 100%
Shikigami.UseCases.Shell.Commands.CFormat 100% 100%
Shikigami.UseCases.Shell.Commands.CNumbers 100% 100%
Shikigami.UseCases.Shell.Commands.CommandContext 97% 92.8%
Shikigami.UseCases.Shell.Commands.CommandRegistry 100% 100%
Shikigami.UseCases.Shell.Commands.Cut 100% 100%
Shikigami.UseCases.Shell.Commands.CutPlan 100% 100%
Shikigami.UseCases.Shell.Commands.Date 100% 98%
Shikigami.UseCases.Shell.Commands.Diff 100% 100%
Shikigami.UseCases.Shell.Commands.Dirname 100% 100%
Shikigami.UseCases.Shell.Commands.Echo 90.7% 92.3%
Shikigami.UseCases.Shell.Commands.Escapes 100% 97.4%
Shikigami.UseCases.Shell.Commands.False 88.8%
Shikigami.UseCases.Shell.Commands.FileCommand 100% 100%
Shikigami.UseCases.Shell.Commands.FileNames 100% 100%
Shikigami.UseCases.Shell.Commands.Filters 100% 90%
Shikigami.UseCases.Shell.Commands.Find 100% 97.7%
Shikigami.UseCases.Shell.Commands.FindExpression 100% 98.7%
Shikigami.UseCases.Shell.Commands.FindItem 100% 100%
Shikigami.UseCases.Shell.Commands.FindLine 100% 100%
Shikigami.UseCases.Shell.Commands.FindNode 100% 100%
Shikigami.UseCases.Shell.Commands.FindReference 100%
Shikigami.UseCases.Shell.Commands.GetOpt 100% 98.2%
Shikigami.UseCases.Shell.Commands.Grep 99.2% 98.9%
Shikigami.UseCases.Shell.Commands.Head 100% 100%
Shikigami.UseCases.Shell.Commands.HelpCommand 94.4% 100%
Shikigami.UseCases.Shell.Commands.History 97.5% 94%
Shikigami.UseCases.Shell.Commands.Invocation 100% 50%
Shikigami.UseCases.Shell.Commands.LinesCommand 97.2% 96.1%
Shikigami.UseCases.Shell.Commands.LineSearch 100% 100%
Shikigami.UseCases.Shell.Commands.Ls 97.2% 95.6%
Shikigami.UseCases.Shell.Commands.Magic 100% 95.9%
Shikigami.UseCases.Shell.Commands.Nl 100% 99.1%
Shikigami.UseCases.Shell.Commands.Numbers 100% 100%
Shikigami.UseCases.Shell.Commands.Operand 100%
Shikigami.UseCases.Shell.Commands.OptionSpec 100%
Shikigami.UseCases.Shell.Commands.ParsedOptions 100%
Shikigami.UseCases.Shell.Commands.Printf 100% 99.5%
Shikigami.UseCases.Shell.Commands.Pwd 100% 100%
Shikigami.UseCases.Shell.Commands.Ranges 100% 100%
Shikigami.UseCases.Shell.Commands.Rg 97.7% 94.7%
Shikigami.UseCases.Shell.Commands.SearchFiles 90% 83.3%
Shikigami.UseCases.Shell.Commands.SearchPatterns 100% 100%
Shikigami.UseCases.Shell.Commands.SearchSettings 100%
Shikigami.UseCases.Shell.Commands.Sed 100% 100%
Shikigami.UseCases.Shell.Commands.SedAddress 100%
Shikigami.UseCases.Shell.Commands.SedCommand 100%
Shikigami.UseCases.Shell.Commands.SedException 100%
Shikigami.UseCases.Shell.Commands.SedInput 100%
Shikigami.UseCases.Shell.Commands.SedParser 100% 99.8%
Shikigami.UseCases.Shell.Commands.SedPart 100%
Shikigami.UseCases.Shell.Commands.SedProgram 100%
Shikigami.UseCases.Shell.Commands.SedRegex 100%
Shikigami.UseCases.Shell.Commands.SedRun 100% 100%
Shikigami.UseCases.Shell.Commands.SedSubstitution 100%
Shikigami.UseCases.Shell.Commands.ShellCommand 100% 100%
Shikigami.UseCases.Shell.Commands.ShellQuote 100% 100%
Shikigami.UseCases.Shell.Commands.Sizes 100% 100%
Shikigami.UseCases.Shell.Commands.Sort 100% 94.1%
Shikigami.UseCases.Shell.Commands.SortKey 100% 100%
Shikigami.UseCases.Shell.Commands.SortOrder 99.5% 99.5%
Shikigami.UseCases.Shell.Commands.Stat 100% 90.9%
Shikigami.UseCases.Shell.Commands.StatFacts 100% 100%
Shikigami.UseCases.Shell.Commands.StatFormat 100% 99.5%
Shikigami.UseCases.Shell.Commands.Tail 100% 100%
Shikigami.UseCases.Shell.Commands.TextFile 100%
Shikigami.UseCases.Shell.Commands.Tr 100% 100%
Shikigami.UseCases.Shell.Commands.TreeCommand 100% 99.2%
Shikigami.UseCases.Shell.Commands.TrPlan 100% 100%
Shikigami.UseCases.Shell.Commands.TrSequence 93.9% 80%
Shikigami.UseCases.Shell.Commands.TrSet 100% 97.2%
Shikigami.UseCases.Shell.Commands.True 88.8%
Shikigami.UseCases.Shell.Commands.Uniq 100% 100%
Shikigami.UseCases.Shell.Commands.VersionOrder 100% 96.6%
Shikigami.UseCases.Shell.Commands.Wc 100% 97.3%
Shikigami.UseCases.Shell.Execution.CaptureSink 100% 100%
Shikigami.UseCases.Shell.Execution.ClosedSink 100%
Shikigami.UseCases.Shell.Execution.ClosedStreamException 100%
Shikigami.UseCases.Shell.Execution.CodePointOrder 100% 100%
Shikigami.UseCases.Shell.Execution.DateInput 96.8% 94.3%
Shikigami.UseCases.Shell.Execution.Errno 100% 100%
Shikigami.UseCases.Shell.Execution.Executor 98.1% 95.2%
Shikigami.UseCases.Shell.Execution.Expander 97.3% 95.1%
Shikigami.UseCases.Shell.Execution.Glob 94.6% 95.9%
Shikigami.UseCases.Shell.Execution.GnuQuote 91.2% 92.8%
Shikigami.UseCases.Shell.Execution.InputSource 100%
Shikigami.UseCases.Shell.Execution.LineChange 100%
Shikigami.UseCases.Shell.Execution.LineDiff 98.8% 98.1%
Shikigami.UseCases.Shell.Execution.LongDouble 100% 98.7%
Shikigami.UseCases.Shell.Execution.NullSink 100%
Shikigami.UseCases.Shell.Execution.OutputLimit 95.8% 94.7%
Shikigami.UseCases.Shell.Execution.PathResolver 100% 97%
Shikigami.UseCases.Shell.Execution.PipeSink 100% 100%
Shikigami.UseCases.Shell.Execution.PosixRegex 89.2% 90.7%
Shikigami.UseCases.Shell.Execution.PosixRegexException 100%
Shikigami.UseCases.Shell.Execution.ResolvedPath 100%
Shikigami.UseCases.Shell.Execution.ShellLimitException 100%
Shikigami.UseCases.Shell.Execution.ShellScope 94.7% 83.3%
Shikigami.UseCases.Shell.Execution.ShellTree 97.5% 91.3%
Shikigami.UseCases.Shell.Execution.Strftime 95.6% 92.3%
Shikigami.UseCases.Shell.Execution.Terminal 100% 100%
Shikigami.UseCases.Shell.Execution.TextLine 50% 0%
Shikigami.UseCases.Shell.Execution.TextLines 100% 100%
Shikigami.UseCases.Shell.Execution.TreeWalker 100% 100%
Shikigami.UseCases.Shell.Execution.Walked 100%
Shikigami.UseCases.Shell.Help.CommandHints 100% 100%
Shikigami.UseCases.Shell.Help.MountGuide 100%
Shikigami.UseCases.Shell.Help.ShellHelp 100% 100%
Shikigami.UseCases.Shell.ShellCommandPlan 100%
Shikigami.UseCases.Shell.ShellCommandRecord 100%
Shikigami.UseCases.Shell.ShellEffects 100%
Shikigami.UseCases.Shell.ShellInterpreter 100% 100%
Shikigami.UseCases.Shell.ShellLimits 100%
Shikigami.UseCases.Shell.ShellRead 100%
Shikigami.UseCases.Shell.ShellResult 75%
Shikigami.UseCases.Shell.ShellSession 100% 100%
Shikigami.UseCases.Shell.Syntax.AndOrList 100%
Shikigami.UseCases.Shell.Syntax.Assignment 100%
Shikigami.UseCases.Shell.Syntax.ByteText 100% 88.8%
Shikigami.UseCases.Shell.Syntax.HereDocBody 100%
Shikigami.UseCases.Shell.Syntax.Lexer 93.5% 89.8%
Shikigami.UseCases.Shell.Syntax.LiteralPart 100%
Shikigami.UseCases.Shell.Syntax.ParameterPart 100%
Shikigami.UseCases.Shell.Syntax.Parser 96.9% 90.1%
Shikigami.UseCases.Shell.Syntax.Pipeline 100%
Shikigami.UseCases.Shell.Syntax.Redirection 100%
Shikigami.UseCases.Shell.Syntax.Script 100%
Shikigami.UseCases.Shell.Syntax.ShellSyntaxException 100%
Shikigami.UseCases.Shell.Syntax.SimpleCommand 100%
Shikigami.UseCases.Shell.Syntax.TildePart 100% 100%
Shikigami.UseCases.Shell.Syntax.Token 77.7% 66.6%
Shikigami.UseCases.Shell.Syntax.Word 100% 83.3%
Shikigami.UseCases.Shell.Syntax.WordBuilder 100% 100%
System.Text.RegularExpressions.Generated 81.3% 71.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__AssignmentHead_12
95.8% 95.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__BraceExpansion_11
93.4% 85.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__HexColour_6
97.4% 96.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IdPattern_0
68.7% 50%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Interval_3
83.6% 75%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IntervalBody_10
91.6% 86.1%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NameRule_5
92.1% 84.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NewerXY_8
88.5% 62.5%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Number_7
67.3% 62.7%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__OldCount_9
94.8% 83.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__TimeOfDay_2
79% 63.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__ToolPattern_1
83.7% 61.1%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Window_4
69% 56.4%
<!-- coverage-comment --> > 🔄 **Auto-updating coverage report** — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip. > > **Commit:** `ccf62e7` · **Generated:** 2026-10-22 19:08:16 UTC · **Revision:** #5 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 10/22/2026 - 19:08:16 | | Coverage date: | 10/22/2026 - 19:06:21 - 10/22/2026 - 19:08:12 | | Parser: | MultiReport (5x Cobertura) | | Assemblies: | 8 | | Classes: | 505 | | Files: | 257 | | **Line coverage:** | 96.2% (18483 of 19208) | | Covered lines: | 18483 | | Uncovered lines: | 725 | | Coverable lines: | 19208 | | Total lines: | 37595 | | **Branch coverage:** | 92.5% (13257 of 14331) | | Covered branches: | 13257 | | Total branches: | 14331 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Shikigami.BlazorAdapter - 95.6%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.BlazorAdapter**|**95.6%**|**89.4%**| |Shikigami.BlazorAdapter.BlazorAdapterAssembly|100%|| |Shikigami.BlazorAdapter.Cast.CastActionFailed|100%|| |Shikigami.BlazorAdapter.Cast.CastEffects|93.3%|93.7%| |Shikigami.BlazorAdapter.Cast.CastLoaded|100%|| |Shikigami.BlazorAdapter.Cast.CastReducers|93.3%|50%| |Shikigami.BlazorAdapter.Cast.CastState|100%|100%| |Shikigami.BlazorAdapter.Cast.CreateFamiliarFailed|100%|| |Shikigami.BlazorAdapter.Cast.CreateFamiliarRequested|100%|| |Shikigami.BlazorAdapter.Cast.DuplicateFamiliarRequested|100%|| |Shikigami.BlazorAdapter.Cast.FamiliarAvatar|100%|75%| |Shikigami.BlazorAdapter.Cast.FamiliarCreated|100%|| |Shikigami.BlazorAdapter.Cast.NewFamiliarDialog|97.2%|83.3%| |Shikigami.BlazorAdapter.Cast.PurgeFamiliarRequested|100%|| |Shikigami.BlazorAdapter.Cast.SetFamiliarArchivedRequested|100%|| |Shikigami.BlazorAdapter.Cast.SetFamiliarTrashedRequested|100%|| |Shikigami.BlazorAdapter.Cast.TrashPage|89.4%|93.7%| |Shikigami.BlazorAdapter.EffectCalls|100%|| |Shikigami.BlazorAdapter.Files.ConflictSettled|100%|| |Shikigami.BlazorAdapter.Files.DismissFileError|100%|| |Shikigami.BlazorAdapter.Files.EntryMissing|100%|| |Shikigami.BlazorAdapter.Files.EntryOpened|100%|| |Shikigami.BlazorAdapter.Files.FileActionDone|100%|| |Shikigami.BlazorAdapter.Files.FileActionFailed|100%|| |Shikigami.BlazorAdapter.Files.FileActionRequested|100%|| |Shikigami.BlazorAdapter.Files.FileLinks|100%|100%| |Shikigami.BlazorAdapter.Files.FilePane|95.2%|88.7%| |Shikigami.BlazorAdapter.Files.FilePaneClosed|100%|| |Shikigami.BlazorAdapter.Files.FilePathBreadcrumb|100%|100%| |Shikigami.BlazorAdapter.Files.FilesEffects|98.2%|94.7%| |Shikigami.BlazorAdapter.Files.FilesPage|96.9%|97%| |Shikigami.BlazorAdapter.Files.FilesReducers|100%|82%| |Shikigami.BlazorAdapter.Files.FilesState|100%|100%| |Shikigami.BlazorAdapter.Files.FileTreeBranch|100%|100%| |Shikigami.BlazorAdapter.Files.FolderPane|92.3%|86.3%| |Shikigami.BlazorAdapter.Files.JournalOverviewPane|100%|88.8%| |Shikigami.BlazorAdapter.Files.LoadFiles|100%|| |Shikigami.BlazorAdapter.Files.MemoryForm|100%|94.4%| |Shikigami.BlazorAdapter.Files.MemoryOverviewPane|100%|96.1%| |Shikigami.BlazorAdapter.Files.OpenEntry|100%|| |Shikigami.BlazorAdapter.Files.RoutineForm|78.6%|86.4%| |Shikigami.BlazorAdapter.Files.RoutineOverviewPane|100%|94.4%| |Shikigami.BlazorAdapter.Files.SaveLanded|100%|| |Shikigami.BlazorAdapter.Files.SaveRefused|100%|| |Shikigami.BlazorAdapter.Files.SaveText|100%|| |Shikigami.BlazorAdapter.Files.SkillForm|100%|100%| |Shikigami.BlazorAdapter.Files.TreeFailed|100%|| |Shikigami.BlazorAdapter.Files.TreeLoaded|100%|| |Shikigami.BlazorAdapter.Home.HomePage|88.2%|93.7%| |Shikigami.BlazorAdapter.Notifications.CoalescingBridge`1|94.4%|80%| |Shikigami.BlazorAdapter.Notifications.DomainChangedBridge|100%|| |Shikigami.BlazorAdapter.Notifications.DomainChangesReceived|100%|100%| |Shikigami.BlazorAdapter.Notifications.FamiliarEventsBridge|100%|| |Shikigami.BlazorAdapter.Notifications.FamiliarEventsReceived|100%|| |Shikigami.BlazorAdapter.Profile.AvatarChosen|100%|| |Shikigami.BlazorAdapter.Profile.AvatarClearRequested|100%|| |Shikigami.BlazorAdapter.Profile.AvatarFailed|100%|| |Shikigami.BlazorAdapter.Profile.AvatarSaved|100%|| |Shikigami.BlazorAdapter.Profile.CreatedWithoutAvatar|100%|| |Shikigami.BlazorAdapter.Profile.ExpressionsEditor|86.6%|88.8%| |Shikigami.BlazorAdapter.Profile.LoadProfile|100%|| |Shikigami.BlazorAdapter.Profile.PersonaEditor|100%|97.2%| |Shikigami.BlazorAdapter.Profile.PersonaReloaded|100%|| |Shikigami.BlazorAdapter.Profile.PersonaSave|100%|| |Shikigami.BlazorAdapter.Profile.PersonaSaved|100%|| |Shikigami.BlazorAdapter.Profile.PersonaSaveFailed|100%|| |Shikigami.BlazorAdapter.Profile.ProfileEffects|92.9%|85%| |Shikigami.BlazorAdapter.Profile.ProfileLoaded|100%|| |Shikigami.BlazorAdapter.Profile.ProfileMissing|100%|| |Shikigami.BlazorAdapter.Profile.ProfilePage|90%|87.3%| |Shikigami.BlazorAdapter.Profile.ProfileReducers|97.3%|53.9%| |Shikigami.BlazorAdapter.Profile.ProfileRefreshed|100%|| |Shikigami.BlazorAdapter.Profile.ProfileState|100%|100%| |Shikigami.BlazorAdapter.Profile.ReloadPersona|100%|| |Shikigami.BlazorAdapter.Profile.RevertSelfRequested|100%|| |Shikigami.BlazorAdapter.Profile.SavePersonaRequested|100%|| |Shikigami.BlazorAdapter.Profile.SaveSettingsRequested|100%|| |Shikigami.BlazorAdapter.Profile.SelfLayer|92.3%|87.5%| |Shikigami.BlazorAdapter.Profile.SettingsSaved|100%|| |Shikigami.BlazorAdapter.Profile.SettingsSaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.BackupFailed|100%|| |Shikigami.BlazorAdapter.Settings.BackupSettingsLoaded|100%|| |Shikigami.BlazorAdapter.Settings.BackupSettingsLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.BackupsSection|100%|100%| |Shikigami.BlazorAdapter.Settings.BackupsSettingsEffects|100%|| |Shikigami.BlazorAdapter.Settings.BackupsSettingsReducers|100%|| |Shikigami.BlazorAdapter.Settings.BackupsSettingsState|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceCss|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceEffects|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearancePreview|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceReducers|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceSaved|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceSaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceSection|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceState|100%|| |Shikigami.BlazorAdapter.Settings.DefaultsSection|94.5%|85.7%| |Shikigami.BlazorAdapter.Settings.DefaultsSettingsEffects|100%|| |Shikigami.BlazorAdapter.Settings.DefaultsSettingsReducers|100%|100%| |Shikigami.BlazorAdapter.Settings.DefaultsSettingsState|100%|| |Shikigami.BlazorAdapter.Settings.LoadProviderSettings|100%|| |Shikigami.BlazorAdapter.Settings.ModelCatalogLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ModelCatalogLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsSaved|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsSaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.ModelHints|100%|100%| |Shikigami.BlazorAdapter.Settings.ModelPicker|100%|98.2%| |Shikigami.BlazorAdapter.Settings.Money|100%|| |Shikigami.BlazorAdapter.Settings.OpenRouterKeySaved|100%|| |Shikigami.BlazorAdapter.Settings.OpenRouterKeySaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.ProviderKeyChecked|100%|| |Shikigami.BlazorAdapter.Settings.ProviderSection|100%|100%| |Shikigami.BlazorAdapter.Settings.ProviderSettingsEffects|100%|100%| |Shikigami.BlazorAdapter.Settings.ProviderSettingsLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ProviderSettingsReducers|100%|100%| |Shikigami.BlazorAdapter.Settings.ProviderSettingsState|100%|100%| |Shikigami.BlazorAdapter.Settings.SaveChatAppearanceRequested|100%|| |Shikigami.BlazorAdapter.Settings.SaveModelDefaultsRequested|100%|| |Shikigami.BlazorAdapter.Settings.SaveOpenRouterKeyRequested|100%|| |Shikigami.BlazorAdapter.Shell.CastRail|100%|100%| </details> <details><summary>Shikigami.Capabilities.Contracts - 97.8%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Capabilities.Contracts**|**97.8%**|**100%**| |Shikigami.Capabilities.Contracts.CapabilityContext|100%|| |Shikigami.Capabilities.Contracts.CapabilityDefinition|100%|100%| |Shikigami.Capabilities.Contracts.CapabilityEntry|100%|| |Shikigami.Capabilities.Contracts.CapabilityError|100%|| |Shikigami.Capabilities.Contracts.CapabilityFile|100%|| |Shikigami.Capabilities.Contracts.CapabilityListing|100%|| |Shikigami.Capabilities.Contracts.CapabilityMount|100%|100%| |Shikigami.Capabilities.Contracts.CapabilityRegistration|100%|100%| |Shikigami.Capabilities.Contracts.CapabilityResult`1|66.6%|| |Shikigami.Capabilities.Contracts.CapabilityTool|100%|| |Shikigami.Capabilities.Contracts.CapabilityToolResult|100%|| |Shikigami.Capabilities.Contracts.CapabilityValidationProblem|100%|| |Shikigami.Capabilities.Contracts.MountAccessRule|100%|| </details> <details><summary>Shikigami.Capabilities.TestFixture - 97.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Capabilities.TestFixture**|**97.7%**|**91.6%**| |Shikigami.Capabilities.TestFixture.FixtureHandler|100%|| |Shikigami.Capabilities.TestFixture.FixtureModule|100%|100%| |Shikigami.Capabilities.TestFixture.FixtureProvider|94.4%|78.5%| |Shikigami.Capabilities.TestFixture.FixtureState|100%|| |Shikigami.Capabilities.TestFixture.FixtureValidator|100%|100%| </details> <details><summary>Shikigami.Domain - 98.1%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Domain**|**98.1%**|**91.8%**| |Shikigami.Domain.Familiars.AccentPalette|100%|| |Shikigami.Domain.Familiars.ColourPair|100%|100%| |Shikigami.Domain.Familiars.Expression|100%|100%| |Shikigami.Domain.Familiars.ExpressionSet|100%|100%| |Shikigami.Domain.Familiars.Familiar|100%|90.2%| |Shikigami.Domain.Familiars.LearningSettings|100%|| |Shikigami.Domain.Familiars.MemoryBudgets|100%|100%| |Shikigami.Domain.Familiars.ModelChoice|100%|100%| |Shikigami.Domain.Familiars.OutreachSettings|100%|100%| |Shikigami.Domain.Familiars.QuietHours|100%|87.5%| |Shikigami.Domain.Files.BlobContent|100%|75%| |Shikigami.Domain.Files.BlobSha|87.5%|100%| |Shikigami.Domain.Files.DefaultLayout|100%|| |Shikigami.Domain.Files.FileActor|100%|| |Shikigami.Domain.Files.FileAuthor|100%|100%| |Shikigami.Domain.Files.FileContent|100%|100%| |Shikigami.Domain.Files.FileNode|100%|90%| |Shikigami.Domain.Files.FilePath|100%|97.8%| |Shikigami.Domain.Files.FileRevision|100%|87.5%| |Shikigami.Domain.Files.LocalDates|100%|| |Shikigami.Domain.Files.MediaTypes|100%|100%| |Shikigami.Domain.Files.Permissions|100%|100%| |Shikigami.Domain.Files.RunActor|100%|100%| |Shikigami.Domain.Files.Slug|100%|100%| |Shikigami.Domain.Files.TextContent|100%|100%| |Shikigami.Domain.Files.TrashPath|100%|100%| |Shikigami.Domain.Routines.RoutineSchedule|94.4%|89.8%| |Shikigami.Domain.Settings.AppSetting|100%|| |Shikigami.Domain.Text|100%|100%| |System.Text.RegularExpressions.Generated|96.2%|85.2%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_0|94.8%|67.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_2|96.8%|93.7%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__MediaTypeShape_3|95.9%|92.1%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__NamePattern_1|97.2%|94.4%| </details> <details><summary>Shikigami.Infrastructure - 97.2%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Infrastructure**|**97.2%**|**86.7%**| |Shikigami.Infrastructure.Backups.BackupArtifactName|100%|100%| |Shikigami.Infrastructure.Backups.BackupOptions|100%|| |Shikigami.Infrastructure.Backups.BackupSchedule|100%|83.3%| |Shikigami.Infrastructure.Backups.BackupScheduler|96.6%|87.5%| |Shikigami.Infrastructure.Backups.BackupWriter|98.5%|92.8%| |Shikigami.Infrastructure.Backups.DatabaseFingerprint|91.9%|97%| |Shikigami.Infrastructure.Backups.FileSystemBackupStore|100%|100%| |Shikigami.Infrastructure.Backups.OwnerOnlyFile|100%|100%| |Shikigami.Infrastructure.Backups.PreMigrationBackup|90%|100%| |Shikigami.Infrastructure.Backups.SqliteSnapshot|88.2%|75%| |Shikigami.Infrastructure.Blobs.BlobSweep|100%|100%| |Shikigami.Infrastructure.Blobs.BlobSweepOptions|100%|100%| |Shikigami.Infrastructure.Blobs.BlobSweepResult|100%|| |Shikigami.Infrastructure.Blobs.FileSystemBlobStore|95.9%|97%| |Shikigami.Infrastructure.DailyMaintenanceService|97.8%|91.6%| |Shikigami.Infrastructure.DependencyInjection|100%|100%| |Shikigami.Infrastructure.Notifications.InProcessBus`1|100%|100%| |Shikigami.Infrastructure.Persistence.Configurations.AppSettingConfiguration|100%|| |Shikigami.Infrastructure.Persistence.Configurations.FamiliarConfiguration|100%|| |Shikigami.Infrastructure.Persistence.Configurations.FileNodeConfiguration|100%|| |Shikigami.Infrastructure.Persistence.Configurations.FileRevisionConfigurati<br/>on|100%|| |Shikigami.Infrastructure.Persistence.Configurations.UnreferencedBlobConfigu<br/>ration|100%|| |Shikigami.Infrastructure.Persistence.Converters.BlobShaConverter|100%|| |Shikigami.Infrastructure.Persistence.Converters.ExpressionSetConverter|100%|100%| |Shikigami.Infrastructure.Persistence.Converters.FilePathConverter|100%|| |Shikigami.Infrastructure.Persistence.Converters.Json|100%|100%| |Shikigami.Infrastructure.Persistence.Converters.OutreachSettingsConverter|100%|100%| |Shikigami.Infrastructure.Persistence.Converters.UtcTicksConverter|100%|| |Shikigami.Infrastructure.Persistence.DatabaseMigrator|100%|| |Shikigami.Infrastructure.Persistence.Migrations.AppSettings|100%|| |Shikigami.Infrastructure.Persistence.Migrations.FileCreatedBy|98%|| |Shikigami.Infrastructure.Persistence.Migrations.Initial|97.9%|| |Shikigami.Infrastructure.Persistence.Migrations.Profile|96.2%|| |Shikigami.Infrastructure.Persistence.Migrations.ShikigamiDbContextModelSnap<br/>shot|100%|| |Shikigami.Infrastructure.Persistence.ShikigamiDbContext|98.6%|100%| |Shikigami.Infrastructure.Persistence.ShikigamiDbContextFactory|0%|| |Shikigami.Infrastructure.Persistence.SqlitePragmaInterceptor|100%|100%| |Shikigami.Infrastructure.Persistence.Stores.EfFamiliarStore|100%|| |Shikigami.Infrastructure.Persistence.Stores.EfFileStore|100%|100%| |Shikigami.Infrastructure.Persistence.UnreferencedBlob|100%|| |Shikigami.Infrastructure.Provider.OpenRouterKeySource|100%|100%| |Shikigami.Infrastructure.Provider.OpenRouterModelProvider|100%|93.4%| |Shikigami.Infrastructure.Provider.OpenRouterOptions|100%|50%| |Shikigami.Infrastructure.Provider.ResolvedKey|100%|50%| |Shikigami.Infrastructure.Settings.EfAppSettingsStore|100%|100%| |System.Text.RegularExpressions.Generated|81.4%|64.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F3A4F28468B24E9C<br/>234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Pattern_0|84%|65.7%| </details> <details><summary>Shikigami.Kernel - 90.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Kernel**|**90.9%**|**75%**| |Shikigami.Kernel.Err`1|100%|| |Shikigami.Kernel.Ok`1|100%|| |Shikigami.Kernel.Result`1|88.8%|75%| </details> <details><summary>Shikigami.Server - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Server**|**100%**|**95.3%**| |Program|100%|100%| |Shikigami.Server.Backups.BackupConfiguration|100%|100%| |Shikigami.Server.Components.App|100%|| |Shikigami.Server.Components.Layout.AppHeader|100%|78.5%| |Shikigami.Server.Components.Layout.MainLayout|100%|| |Shikigami.Server.Components.Pages.Gate|100%|100%| |Shikigami.Server.Diagnostics.SeedOnStart|100%|100%| |Shikigami.Server.Provider.OpenRouterConfiguration|100%|100%| |Shikigami.Server.Security.AccessGate|100%|87.5%| |Shikigami.Server.Security.AccessSecret|100%|100%| |Shikigami.Server.Security.GateThrottle|100%|100%| |Shikigami.Server.Security.ProxyNetwork|100%|100%| |Shikigami.Server.VolumeStartupValidator|100%|100%| </details> <details><summary>Shikigami.UseCases - 95.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.UseCases**|**95.7%**|**93.1%**| |Shikigami.UseCases.Backups.BackupArtifact|100%|| |Shikigami.UseCases.Backups.BackupFailure|100%|| |Shikigami.UseCases.Backups.BackupJobState|100%|| |Shikigami.UseCases.Backups.BackupPolicy|100%|| |Shikigami.UseCases.Backups.BackupStatusView|100%|100%| |Shikigami.UseCases.Backups.DatabaseSnapshot|100%|| |Shikigami.UseCases.Backups.DownloadDatabaseSnapshot|100%|| |Shikigami.UseCases.Backups.GetBackupStatus|100%|| |Shikigami.UseCases.Backups.IBackupStore|0%|| |Shikigami.UseCases.Backups.RunBackupNow|100%|| |Shikigami.UseCases.Capabilities.CapabilityContexts|100%|87.5%| |Shikigami.UseCases.Capabilities.CapabilityRegistry|97.2%|92%| |Shikigami.UseCases.Capabilities.InvokeCapabilityTool|100%|90%| |Shikigami.UseCases.Capabilities.ToolSchemas|86.8%|72.1%| |Shikigami.UseCases.DependencyInjection|100%|| |Shikigami.UseCases.Diagnostics.SeedDevData|91.1%|33.3%| |Shikigami.UseCases.Familiars.AvatarImage|100%|| |Shikigami.UseCases.Familiars.ClearFamiliarAvatar|100%|| |Shikigami.UseCases.Familiars.CreateFamiliar|97.2%|70%| |Shikigami.UseCases.Familiars.DuplicateFamiliar|96.7%|91.6%| |Shikigami.UseCases.Familiars.ExpressionView|100%|| |Shikigami.UseCases.Familiars.FamiliarDetail|100%|| |Shikigami.UseCases.Familiars.FamiliarEvent|100%|| |Shikigami.UseCases.Familiars.FamiliarFiles|100%|100%| |Shikigami.UseCases.Familiars.FamiliarLimits|71.4%|| |Shikigami.UseCases.Familiars.FamiliarPersona|96.8%|90%| |Shikigami.UseCases.Familiars.FamiliarSettings|100%|100%| |Shikigami.UseCases.Familiars.FamiliarSummary|100%|100%| |Shikigami.UseCases.Familiars.FamiliarTemplates|100%|100%| |Shikigami.UseCases.Familiars.FamiliarViews|100%|94.4%| |Shikigami.UseCases.Familiars.GetFamiliar|100%|100%| |Shikigami.UseCases.Familiars.ListFamiliars|100%|| |Shikigami.UseCases.Familiars.PersonaFile|100%|| |Shikigami.UseCases.Familiars.PurgeFamiliar|100%|| |Shikigami.UseCases.Familiars.ReadFamiliarAvatar|100%|87.5%| |Shikigami.UseCases.Familiars.SaveFamiliarSettings|94.7%|87.5%| |Shikigami.UseCases.Familiars.SelfRevision|100%|| |Shikigami.UseCases.Familiars.SetFamiliarArchived|100%|100%| |Shikigami.UseCases.Familiars.SetFamiliarAvatar|100%|100%| |Shikigami.UseCases.Familiars.SetFamiliarTrashed|100%|100%| |Shikigami.UseCases.Familiars.ToolGroupCatalog|66.6%|| |Shikigami.UseCases.Familiars.ToolGroupInfo|100%|| |Shikigami.UseCases.Files.Browser.FileBrowser|94.4%|87.9%| |Shikigami.UseCases.Files.Browser.FileBytes|100%|| |Shikigami.UseCases.Files.Browser.FileItem|100%|| |Shikigami.UseCases.Files.Browser.FileOk`1|100%|| |Shikigami.UseCases.Files.Browser.FileRefusal|100%|| |Shikigami.UseCases.Files.Browser.FileRefused`1|100%|| |Shikigami.UseCases.Files.Browser.FileRevisionView|100%|| |Shikigami.UseCases.Files.Browser.FileView|100%|| |Shikigami.UseCases.Files.Browser.JournalOverview|100%|| |Shikigami.UseCases.Files.Browser.JournalOverviewEntry|100%|| |Shikigami.UseCases.Files.Browser.MemoryBudget|100%|| |Shikigami.UseCases.Files.Browser.MemoryBudgetUse|100%|| |Shikigami.UseCases.Files.Browser.MemoryDraft|100%|| |Shikigami.UseCases.Files.Browser.MemoryOverview|100%|| |Shikigami.UseCases.Files.Browser.MemoryOverviewEntry|100%|| |Shikigami.UseCases.Files.Browser.MemoryOverviewLimits|100%|| |Shikigami.UseCases.Files.Browser.RoutineDraft|100%|| |Shikigami.UseCases.Files.Browser.RoutineForms|89.5%|80.8%| |Shikigami.UseCases.Files.Browser.RoutineOverview|100%|| |Shikigami.UseCases.Files.Browser.RoutineOverviewEntry|100%|| |Shikigami.UseCases.Files.Browser.RoutinePreview|100%|| |Shikigami.UseCases.Files.Browser.SkillView|100%|| |Shikigami.UseCases.Files.Browser.SpecialForms|98.4%|90.5%| |Shikigami.UseCases.Files.FamiliarWriteLocks|100%|100%| |Shikigami.UseCases.Files.FileAuthors|100%|100%| |Shikigami.UseCases.Files.FileMaintenance|100%|90%| |Shikigami.UseCases.Files.FileMaintenanceResult|100%|| |Shikigami.UseCases.Files.FileSystem|98.5%|95.3%| |Shikigami.UseCases.Files.FileWriteRefused|100%|| |Shikigami.UseCases.Files.FileWritten|100%|| |Shikigami.UseCases.Files.FsError|100%|50%| |Shikigami.UseCases.Files.FsResult`1|100%|50%| |Shikigami.UseCases.Files.Mounts.CapabilityMountAdapter|75%|65.4%| |Shikigami.UseCases.Files.Mounts.FileEntry|100%|| |Shikigami.UseCases.Files.Mounts.FileRead|100%|| |Shikigami.UseCases.Files.Mounts.GeneratedMount|100%|100%| |Shikigami.UseCases.Files.Mounts.Mount|100%|100%| |Shikigami.UseCases.Files.Mounts.MountTable|97.1%|90.3%| |Shikigami.UseCases.Files.Mounts.MountTables|100%|100%| |Shikigami.UseCases.Files.Mounts.StoredMount|100%|100%| |Shikigami.UseCases.Files.SeedDefaultLayout|100%|100%| |Shikigami.UseCases.Files.Special.Budgets|100%|96.6%| |Shikigami.UseCases.Files.Special.FrontMatter|100%|86.2%| |Shikigami.UseCases.Files.Special.HeaderReader|100%|87.8%| |Shikigami.UseCases.Files.Special.HeaderValue|100%|100%| |Shikigami.UseCases.Files.Special.HeaderWriter|96%|90.6%| |Shikigami.UseCases.Files.Special.MemoryFile|100%|87.5%| |Shikigami.UseCases.Files.Special.MemoryUse|100%|| |Shikigami.UseCases.Files.Special.Numbers|100%|| |Shikigami.UseCases.Files.Special.RoutineFile|100%|99.1%| |Shikigami.UseCases.Files.Special.SkillFile|100%|95.2%| |Shikigami.UseCases.Files.Special.SpecialFolders|100%|100%| |Shikigami.UseCases.Files.Special.ValidationProblem|100%|| |Shikigami.UseCases.Files.StoredBlob|100%|| |Shikigami.UseCases.Files.Utf8Order|100%|| |Shikigami.UseCases.Notifications.DomainChanged|100%|| |Shikigami.UseCases.Settings.AppearanceColour|100%|100%| |Shikigami.UseCases.Settings.CatalogModel|100%|100%| |Shikigami.UseCases.Settings.ChatAppearance|100%|| |Shikigami.UseCases.Settings.ChatAppearanceJson|100%|100%| |Shikigami.UseCases.Settings.ChatAppearanceLimits|100%|100%| |Shikigami.UseCases.Settings.CheckOpenRouterKey|100%|| |Shikigami.UseCases.Settings.GetChatAppearance|100%|| |Shikigami.UseCases.Settings.GetModelCatalog|100%|100%| |Shikigami.UseCases.Settings.GetModelDefaults|100%|83.3%| |Shikigami.UseCases.Settings.GetProviderSettings|100%|| |Shikigami.UseCases.Settings.ModelCatalog|100%|| |Shikigami.UseCases.Settings.ModelDefaults|100%|100%| |Shikigami.UseCases.Settings.ProviderKeyInfo|100%|| |Shikigami.UseCases.Settings.ProviderKeyState|100%|| |Shikigami.UseCases.Settings.ProviderSettingsView|100%|100%| |Shikigami.UseCases.Settings.RemoveOpenRouterKey|100%|| |Shikigami.UseCases.Settings.SaveChatAppearance|100%|100%| |Shikigami.UseCases.Settings.SaveModelDefaults|100%|100%| |Shikigami.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Shikigami.UseCases.Shell.AllowEveryCommand|100%|| |Shikigami.UseCases.Shell.Commands.Basename|100%|100%| |Shikigami.UseCases.Shell.Commands.Builtin|100%|100%| |Shikigami.UseCases.Shell.Commands.Cat|100%|100%| |Shikigami.UseCases.Shell.Commands.Cd|97.5%|100%| |Shikigami.UseCases.Shell.Commands.CFormat|100%|100%| |Shikigami.UseCases.Shell.Commands.CNumbers|100%|100%| |Shikigami.UseCases.Shell.Commands.CommandContext|97%|92.8%| |Shikigami.UseCases.Shell.Commands.CommandRegistry|100%|100%| |Shikigami.UseCases.Shell.Commands.Cut|100%|100%| |Shikigami.UseCases.Shell.Commands.CutPlan|100%|100%| |Shikigami.UseCases.Shell.Commands.Date|100%|98%| |Shikigami.UseCases.Shell.Commands.Diff|100%|100%| |Shikigami.UseCases.Shell.Commands.Dirname|100%|100%| |Shikigami.UseCases.Shell.Commands.Echo|90.7%|92.3%| |Shikigami.UseCases.Shell.Commands.Escapes|100%|97.4%| |Shikigami.UseCases.Shell.Commands.False|88.8%|| |Shikigami.UseCases.Shell.Commands.FileCommand|100%|100%| |Shikigami.UseCases.Shell.Commands.FileNames|100%|100%| |Shikigami.UseCases.Shell.Commands.Filters|100%|90%| |Shikigami.UseCases.Shell.Commands.Find|100%|97.7%| |Shikigami.UseCases.Shell.Commands.FindExpression|100%|98.7%| |Shikigami.UseCases.Shell.Commands.FindItem|100%|100%| |Shikigami.UseCases.Shell.Commands.FindLine|100%|100%| |Shikigami.UseCases.Shell.Commands.FindNode|100%|100%| |Shikigami.UseCases.Shell.Commands.FindReference|100%|| |Shikigami.UseCases.Shell.Commands.GetOpt|100%|98.2%| |Shikigami.UseCases.Shell.Commands.Grep|99.2%|98.9%| |Shikigami.UseCases.Shell.Commands.Head|100%|100%| |Shikigami.UseCases.Shell.Commands.HelpCommand|94.4%|100%| |Shikigami.UseCases.Shell.Commands.History|97.5%|94%| |Shikigami.UseCases.Shell.Commands.Invocation|100%|50%| |Shikigami.UseCases.Shell.Commands.LinesCommand|97.2%|96.1%| |Shikigami.UseCases.Shell.Commands.LineSearch|100%|100%| |Shikigami.UseCases.Shell.Commands.Ls|97.2%|95.6%| |Shikigami.UseCases.Shell.Commands.Magic|100%|95.9%| |Shikigami.UseCases.Shell.Commands.Nl|100%|99.1%| |Shikigami.UseCases.Shell.Commands.Numbers|100%|100%| |Shikigami.UseCases.Shell.Commands.Operand|100%|| |Shikigami.UseCases.Shell.Commands.OptionSpec|100%|| |Shikigami.UseCases.Shell.Commands.ParsedOptions|100%|| |Shikigami.UseCases.Shell.Commands.Printf|100%|99.5%| |Shikigami.UseCases.Shell.Commands.Pwd|100%|100%| |Shikigami.UseCases.Shell.Commands.Ranges|100%|100%| |Shikigami.UseCases.Shell.Commands.Rg|97.7%|94.7%| |Shikigami.UseCases.Shell.Commands.SearchFiles|90%|83.3%| |Shikigami.UseCases.Shell.Commands.SearchPatterns|100%|100%| |Shikigami.UseCases.Shell.Commands.SearchSettings|100%|| |Shikigami.UseCases.Shell.Commands.Sed|100%|100%| |Shikigami.UseCases.Shell.Commands.SedAddress|100%|| |Shikigami.UseCases.Shell.Commands.SedCommand|100%|| |Shikigami.UseCases.Shell.Commands.SedException|100%|| |Shikigami.UseCases.Shell.Commands.SedInput|100%|| |Shikigami.UseCases.Shell.Commands.SedParser|100%|99.8%| |Shikigami.UseCases.Shell.Commands.SedPart|100%|| |Shikigami.UseCases.Shell.Commands.SedProgram|100%|| |Shikigami.UseCases.Shell.Commands.SedRegex|100%|| |Shikigami.UseCases.Shell.Commands.SedRun|100%|100%| |Shikigami.UseCases.Shell.Commands.SedSubstitution|100%|| |Shikigami.UseCases.Shell.Commands.ShellCommand|100%|100%| |Shikigami.UseCases.Shell.Commands.ShellQuote|100%|100%| |Shikigami.UseCases.Shell.Commands.Sizes|100%|100%| |Shikigami.UseCases.Shell.Commands.Sort|100%|94.1%| |Shikigami.UseCases.Shell.Commands.SortKey|100%|100%| |Shikigami.UseCases.Shell.Commands.SortOrder|99.5%|99.5%| |Shikigami.UseCases.Shell.Commands.Stat|100%|90.9%| |Shikigami.UseCases.Shell.Commands.StatFacts|100%|100%| |Shikigami.UseCases.Shell.Commands.StatFormat|100%|99.5%| |Shikigami.UseCases.Shell.Commands.Tail|100%|100%| |Shikigami.UseCases.Shell.Commands.TextFile|100%|| |Shikigami.UseCases.Shell.Commands.Tr|100%|100%| |Shikigami.UseCases.Shell.Commands.TreeCommand|100%|99.2%| |Shikigami.UseCases.Shell.Commands.TrPlan|100%|100%| |Shikigami.UseCases.Shell.Commands.TrSequence|93.9%|80%| |Shikigami.UseCases.Shell.Commands.TrSet|100%|97.2%| |Shikigami.UseCases.Shell.Commands.True|88.8%|| |Shikigami.UseCases.Shell.Commands.Uniq|100%|100%| |Shikigami.UseCases.Shell.Commands.VersionOrder|100%|96.6%| |Shikigami.UseCases.Shell.Commands.Wc|100%|97.3%| |Shikigami.UseCases.Shell.Execution.CaptureSink|100%|100%| |Shikigami.UseCases.Shell.Execution.ClosedSink|100%|| |Shikigami.UseCases.Shell.Execution.ClosedStreamException|100%|| |Shikigami.UseCases.Shell.Execution.CodePointOrder|100%|100%| |Shikigami.UseCases.Shell.Execution.DateInput|96.8%|94.3%| |Shikigami.UseCases.Shell.Execution.Errno|100%|100%| |Shikigami.UseCases.Shell.Execution.Executor|98.1%|95.2%| |Shikigami.UseCases.Shell.Execution.Expander|97.3%|95.1%| |Shikigami.UseCases.Shell.Execution.Glob|94.6%|95.9%| |Shikigami.UseCases.Shell.Execution.GnuQuote|91.2%|92.8%| |Shikigami.UseCases.Shell.Execution.InputSource|100%|| |Shikigami.UseCases.Shell.Execution.LineChange|100%|| |Shikigami.UseCases.Shell.Execution.LineDiff|98.8%|98.1%| |Shikigami.UseCases.Shell.Execution.LongDouble|100%|98.7%| |Shikigami.UseCases.Shell.Execution.NullSink|100%|| |Shikigami.UseCases.Shell.Execution.OutputLimit|95.8%|94.7%| |Shikigami.UseCases.Shell.Execution.PathResolver|100%|97%| |Shikigami.UseCases.Shell.Execution.PipeSink|100%|100%| |Shikigami.UseCases.Shell.Execution.PosixRegex|89.2%|90.7%| |Shikigami.UseCases.Shell.Execution.PosixRegexException|100%|| |Shikigami.UseCases.Shell.Execution.ResolvedPath|100%|| |Shikigami.UseCases.Shell.Execution.ShellLimitException|100%|| |Shikigami.UseCases.Shell.Execution.ShellScope|94.7%|83.3%| |Shikigami.UseCases.Shell.Execution.ShellTree|97.5%|91.3%| |Shikigami.UseCases.Shell.Execution.Strftime|95.6%|92.3%| |Shikigami.UseCases.Shell.Execution.Terminal|100%|100%| |Shikigami.UseCases.Shell.Execution.TextLine|50%|0%| |Shikigami.UseCases.Shell.Execution.TextLines|100%|100%| |Shikigami.UseCases.Shell.Execution.TreeWalker|100%|100%| |Shikigami.UseCases.Shell.Execution.Walked|100%|| |Shikigami.UseCases.Shell.Help.CommandHints|100%|100%| |Shikigami.UseCases.Shell.Help.MountGuide|100%|| |Shikigami.UseCases.Shell.Help.ShellHelp|100%|100%| |Shikigami.UseCases.Shell.ShellCommandPlan|100%|| |Shikigami.UseCases.Shell.ShellCommandRecord|100%|| |Shikigami.UseCases.Shell.ShellEffects|100%|| |Shikigami.UseCases.Shell.ShellInterpreter|100%|100%| |Shikigami.UseCases.Shell.ShellLimits|100%|| |Shikigami.UseCases.Shell.ShellRead|100%|| |Shikigami.UseCases.Shell.ShellResult|75%|| |Shikigami.UseCases.Shell.ShellSession|100%|100%| |Shikigami.UseCases.Shell.Syntax.AndOrList|100%|| |Shikigami.UseCases.Shell.Syntax.Assignment|100%|| |Shikigami.UseCases.Shell.Syntax.ByteText|100%|88.8%| |Shikigami.UseCases.Shell.Syntax.HereDocBody|100%|| |Shikigami.UseCases.Shell.Syntax.Lexer|93.5%|89.8%| |Shikigami.UseCases.Shell.Syntax.LiteralPart|100%|| |Shikigami.UseCases.Shell.Syntax.ParameterPart|100%|| |Shikigami.UseCases.Shell.Syntax.Parser|96.9%|90.1%| |Shikigami.UseCases.Shell.Syntax.Pipeline|100%|| |Shikigami.UseCases.Shell.Syntax.Redirection|100%|| |Shikigami.UseCases.Shell.Syntax.Script|100%|| |Shikigami.UseCases.Shell.Syntax.ShellSyntaxException|100%|| |Shikigami.UseCases.Shell.Syntax.SimpleCommand|100%|| |Shikigami.UseCases.Shell.Syntax.TildePart|100%|100%| |Shikigami.UseCases.Shell.Syntax.Token|77.7%|66.6%| |Shikigami.UseCases.Shell.Syntax.Word|100%|83.3%| |Shikigami.UseCases.Shell.Syntax.WordBuilder|100%|100%| |System.Text.RegularExpressions.Generated|81.3%|71.6%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__AssignmentHead_12|95.8%|95.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__BraceExpansion_11|93.4%|85.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__HexColour_6|97.4%|96.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IdPattern_0|68.7%|50%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Interval_3|83.6%|75%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IntervalBody_10|91.6%|86.1%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NameRule_5|92.1%|84.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NewerXY_8|88.5%|62.5%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Number_7|67.3%|62.7%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__OldCount_9|94.8%|83.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__TimeOfDay_2|79%|63.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__ToolPattern_1|83.7%|61.1%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Window_4|69%|56.4%| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! Schedule arithmetic with explicit anchors, phase tables that skip closed windows arithmetically, DST folds resolved at the earlier offset, and a hypothetical-activation reference that stays frozen while the owner edits~? I read every line of the domain calculator twice, hunted the null-forgiving operators in ReadSchedule back to their validation gates, chased the .Scalar! through HeaderReader, and diffed you against your siblings (SpecialForms, FileView, the memory/journal overviews). This is the good knowledge. I'm keeping it. ♡

Verdict: ✅ Looks good to me~

No blocking findings. I could not find a logic bug, and I tried, fufu~

What I verified by reading:

  • RoutineSchedule — exclusivity (> after), the Math.Max(1, …) first-slot rule, the one-shot year-jump (start.Value.UtcTicks > 0 guard), WallTimeToUtc's binary-search gap resolution and Max()-offset fold choice, and the until whole-local-day semantics all line up with the ADR 0024 amendment and with the tests that pin them. ActivePhases' step % TicksPerDay / GCD period is correct even for century-long intervals (constant wall time → period 1).
  • ReadSchedule's .Scalar! / List("time")! are all gated behind problems.Count == 0, and FrontMatter rejects duplicate keys, so every ! I traced is genuinely unreachable-null. The weekday mapping (IndexOf(Weekdays, day) + 1) % 7 maps mon→Monday…sun→Sunday correctly (mon-first array — the classic off-by-one trap, dodged).
  • HeaderWriter round-trips BOM, CRLF, header comments, body bytes and even astral-plane emoji through the private-use stand-in — the tests in RoutineFormDraftTests cover exactly the byte-preservation the PR promises.
  • Siblings honored: canonical key order like WriteMemory, the FileView grows one optional lens like Memories/Journal, SpecialForms.Starter slots the routine branch in, and /routines reuses the existing validator, draft, Save, stale-refusal and refresh instead of building a second store. Clean Architecture stays intact — Domain takes Cronos with a comment saying why.

🔬 Mutation probes (3 run, 0 real survivors)

  1. NextPhase wrap → index + 1: survived — but honestly: with every filter monotone in index, a one-step scan reaches the identical occurrence set, so my mutant only removed the arithmetic jump (a bounded-scan optimization, ≤1440 iterations), not behavior. Bad mutant, not weak tests — the code's own comment even warns this. ♪
  2. NextPhase wrap target phases[0] → phases[^1] (skip the next window's opening slot): killed by Overnight_windows_include_the_start_exclude_the_end_and_honor_until. The wrap is pinned.
  3. Weekday mapping + 1 dropped (mon→Sunday): killed by RoutineScheduleFileTests' weekdays: [mon, fri] case. The mapping is pinned.

💡 Little ideas (non-blocking)~

  1. RoutineForms.cs:148 — Summary renders "Daily at " / "Once on at " when the timing key is missing; it always sits beside a Needs attention badge, so purely cosmetic.
  2. SpecialForms.cs:64 — Describing truncates by MemoryFile.MaxDescriptionLength, but it now also seeds routine starters governed by RoutineFile.MaxDescriptionLength. Both are 150 today; if they ever diverge, a long routine filename could seed a starter its own validator refuses. One shared constant would make that impossible~
  3. RoutineOverviewPaneTests.cs:60 — the OtherEntries fixture includes a file (a note.txt), a state RoutinesAsync can't produce (files always land in Entries). Render-only, harmless.

✅ What I liked~

  • The test suite teaches: Repeat_slots_in_a_gap_collapse_at_the_first_valid_instant_and_then_resume_the_anchor and A_gap_adjustment_does_not_make_a_closed_nominal_slot_eligible are exactly the DST semantics most implementations get wrong, each named as the rule it pins.
  • ActivePhases proving "whole-minute intervals give at most 1,440 distinct wall times" before looping — the kind of arithmetic that makes me shiver with delight~
  • One draft, one Save, one conflict flow — reusing the file editor's entire lifecycle instead of forking it. The ADR amendments and story checkboxes read like what the code actually does; docs and code never disagreed once during my read.

A wonderful slice. Bring me the scheduler that consumes this arithmetic, fufu~ ♡


Automated review by Jibril · 2026-10-22
CI: green for head SHA · Mutation probes: 3 run, 0 logic survivors (1 behavior-preserving performance mutant) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! Schedule arithmetic with explicit anchors, phase tables that skip closed windows *arithmetically*, DST folds resolved at the earlier offset, and a hypothetical-activation reference that stays frozen while the owner edits~? I read every line of the domain calculator twice, hunted the null-forgiving operators in `ReadSchedule` back to their validation gates, chased the `.Scalar!` through `HeaderReader`, and diffed you against your siblings (`SpecialForms`, `FileView`, the memory/journal overviews). This is the good knowledge. I'm keeping it. ♡ ### Verdict: ✅ Looks good to me~ No blocking findings. I could not find a logic bug, and I *tried*, fufu~ What I verified by reading: - **`RoutineSchedule`** — exclusivity (`> after`), the `Math.Max(1, …)` first-slot rule, the one-shot year-jump (`start.Value.UtcTicks > 0` guard), `WallTimeToUtc`'s binary-search gap resolution and `Max()`-offset fold choice, and the `until` whole-local-day semantics all line up with the ADR 0024 amendment *and* with the tests that pin them. `ActivePhases`' `step % TicksPerDay` / GCD period is correct even for century-long intervals (constant wall time → period 1). - **`ReadSchedule`'s `.Scalar!` / `List("time")!`** are all gated behind `problems.Count == 0`, and `FrontMatter` rejects duplicate keys, so every `!` I traced is genuinely unreachable-null. The weekday mapping `(IndexOf(Weekdays, day) + 1) % 7` maps mon→Monday…sun→Sunday correctly (mon-first array — the classic off-by-one trap, dodged). - **`HeaderWriter`** round-trips BOM, CRLF, header comments, body bytes and even astral-plane emoji through the private-use stand-in — the tests in `RoutineFormDraftTests` cover exactly the byte-preservation the PR promises. - **Siblings honored**: canonical key order like `WriteMemory`, the `FileView` grows one optional lens like `Memories`/`Journal`, `SpecialForms.Starter` slots the routine branch in, and `/routines` reuses the existing validator, draft, Save, stale-refusal and refresh instead of building a second store. Clean Architecture stays intact — Domain takes `Cronos` with a comment saying why. #### 🔬 Mutation probes (3 run, 0 real survivors) 1. `NextPhase` wrap → `index + 1`: **survived — but honestly**: with every filter monotone in index, a one-step scan reaches the identical occurrence set, so my mutant only removed the arithmetic jump (a bounded-scan optimization, ≤1440 iterations), not behavior. Bad mutant, not weak tests — the code's own comment even warns this. ♪ 2. `NextPhase` wrap target `phases[0]` → `phases[^1]` (skip the next window's opening slot): **killed** by `Overnight_windows_include_the_start_exclude_the_end_and_honor_until`. The wrap is pinned. 3. Weekday mapping `+ 1` dropped (mon→Sunday): **killed** by `RoutineScheduleFileTests`' `weekdays: [mon, fri]` case. The mapping is pinned. #### 💡 Little ideas (non-blocking)~ 1. **RoutineForms.cs:148** — `Summary` renders `"Daily at "` / `"Once on at "` when the timing key is missing; it always sits beside a *Needs attention* badge, so purely cosmetic. 2. **SpecialForms.cs:64** — `Describing` truncates by `MemoryFile.MaxDescriptionLength`, but it now also seeds routine starters governed by `RoutineFile.MaxDescriptionLength`. Both are 150 today; if they ever diverge, a long routine filename could seed a starter its own validator refuses. One shared constant would make that impossible~ 3. **RoutineOverviewPaneTests.cs:60** — the `OtherEntries` fixture includes a *file* (`a note.txt`), a state `RoutinesAsync` can't produce (files always land in `Entries`). Render-only, harmless. #### ✅ What I liked~ - The test suite *teaches*: `Repeat_slots_in_a_gap_collapse_at_the_first_valid_instant_and_then_resume_the_anchor` and `A_gap_adjustment_does_not_make_a_closed_nominal_slot_eligible` are exactly the DST semantics most implementations get wrong, each named as the rule it pins. - `ActivePhases` proving "whole-minute intervals give at most 1,440 distinct wall times" before looping — the kind of arithmetic that makes me shiver with delight~ - One draft, one Save, one conflict flow — reusing the file editor's entire lifecycle instead of forking it. The ADR amendments and story checkboxes read like what the code actually does; docs and code never disagreed once during my read. A wonderful slice. Bring me the scheduler that consumes this arithmetic, fufu~ ♡ --- *Automated review by Jibril · 2026-10-22* *CI: green for head SHA · Mutation probes: 3 run, 0 logic survivors (1 behavior-preserving performance mutant) · Local suite: skipped (CI green)*
Address Jibril's routine authoring feedback
All checks were successful
CI / build (pull_request) Successful in 26s
CI / image (pull_request) Successful in 36s
CI / test (pull_request) Successful in 2m27s
a29cd7431b
Author
Member

Addressed all three little ideas from your review in a29cd7431b3a8305b7dd64e89c1033f6d67adc91.

  • 💡 1: Incomplete timing fields now render Schedule incomplete. Seven regression cases cover absent/blank daily times, empty weekday selection, missing one-shot date/time, interval and cron values; validation problems remain available for repair.
  • 💡 2: The shared starter naming helper now accepts each format's own validator limit and fallback. Memory and routine callers pass their respective constants, so future divergence remains safe. The long-name test now covers both formats without splitting a Unicode text element, and the blank-name routine fallback says A new routine.
  • 💡 3: The overview fixture now contains only a legacy directory, matching RoutinesAsync; its link and empty-routine state remain asserted.

Serial solution build passed with zero warnings or errors. The full suite passed 5,336/5,336 locally and again with TZ=UTC (+9 cases). These include production changes, so the new head needs a fresh full review; your earlier green applies to the previous head.

Review follow-up by Codex.

Addressed all three little ideas from your review in `a29cd7431b3a8305b7dd64e89c1033f6d67adc91`. - 💡 1: Incomplete timing fields now render **Schedule incomplete**. Seven regression cases cover absent/blank daily times, empty weekday selection, missing one-shot date/time, interval and cron values; validation problems remain available for repair. - 💡 2: The shared starter naming helper now accepts each format's own validator limit and fallback. Memory and routine callers pass their respective constants, so future divergence remains safe. The long-name test now covers both formats without splitting a Unicode text element, and the blank-name routine fallback says **A new routine**. - 💡 3: The overview fixture now contains only a legacy directory, matching `RoutinesAsync`; its link and empty-routine state remain asserted. Serial solution build passed with zero warnings or errors. The full suite passed **5,336/5,336** locally and again with **TZ=UTC** (+9 cases). These include production changes, so the new head needs a fresh full review; your earlier green applies to the previous head. *Review follow-up by Codex.*
Owner

you need to rebase

you need to rebase
Member

🔮 fufu~ Jibril reviewed your code!

Back so soon~? I approved your previous head, you took my three little ideas, and now I get to open the gift box and see if what's inside matches the wrapping. Spoiler: it does. ♡ I traced every one of the seven new Summary cases through HeaderReader by hand — Text refuses blank scalars, List refuses empty sequences, so every "Schedule incomplete" sits beside a real repairable problem — and then I tried to break your new branches with three mutants. They didn't survive. Neither did my composure~

Verdict: ✅ Looks good to me~

The delta since my review of d393e43 is exactly the three fixes, and each one is right:

  1. RoutineForms.Summary — the completeness gate mirrors Read's When-derivation precisely: mode from key presence, completeness from value presence, Weekdays additionally requiring a non-empty list. All five modes have both an incomplete case and a complete case pinned (Daily end-to-end via the integration test, the rest by the draft theories). One call site (FileBrowser.Routines.cs), so nothing else needed the same treatment.
  2. SpecialForms.Describing — now takes each format's own limit and fallback, with RoutineFile.MaxDescriptionLength and MemoryFile.MaxDescriptionLength passed by their owners; the tests use the production constants, so they can never drift from what the validators enforce. Diverge those two 150s someday and nothing breaks. ♪
  3. RoutineOverviewPaneTests — the fixture now holds only a legacy directory, matching RoutinesAsync (files land in Entries even when broken — old.md in the integration test — only folders reach OtherEntries).

🔬 Mutation probes (3 run on the new logic, 0 survived)

  1. Describing limit relaxed by one text element (<= max + 1): killed by both long-name theories (memory and routines) — the per-format truncation is pinned twice.
  2. Summary weekdays check && draft.Weekdays.Count > 0 dropped: killed by exactly the weekdays: [] case.
  3. Has weakened from whitespace-aware to Length > 0: killed by exactly the time: ' ' case.

(The three probes from my previous review covered unchanged code, so I cited them rather than re-running.)

✅ What I liked~

  • The seven-case theory doesn't just assert the label — it asserts Problems is non-empty too, pinning the invariant that "incomplete" always comes with something to repair. That's the difference between a test that compiles and a test that guards.
  • Fixing the fixture to match the real producer's shape instead of loosening the assertion — correcting the test's world to the code's world, never the other way around. Fufu, you know how I feel about that~
  • Every claim in your reply comment checked out mechanically: seven cases, both formats, the legacy folder, zero warnings, CI green.

A clean follow-up to a clean slice. Now bring me the scheduler that consumes all this beautiful arithmetic, fufu~ ♡


Automated review by Jibril · 2026-10-22
CI: green for head SHA a29cd743 · Mutation probes: 3 run, 0 survived (+3 earlier on unchanged code, cited) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! Back so soon~? I approved your previous head, you took my three little ideas, and now I get to open the gift box and see if what's inside matches the wrapping. Spoiler: it does. ♡ I traced every one of the seven new `Summary` cases through `HeaderReader` by hand — `Text` refuses blank scalars, `List` refuses empty sequences, so every "Schedule incomplete" sits beside a real repairable problem — and then I tried to break your new branches with three mutants. They didn't survive. Neither did my composure~ ### Verdict: ✅ Looks good to me~ The delta since my review of `d393e43` is exactly the three fixes, and each one is right: 1. **`RoutineForms.Summary`** — the completeness gate mirrors `Read`'s When-derivation precisely: mode from *key presence*, completeness from *value presence*, `Weekdays` additionally requiring a non-empty list. All five modes have both an incomplete case and a complete case pinned (Daily end-to-end via the integration test, the rest by the draft theories). One call site (`FileBrowser.Routines.cs`), so nothing else needed the same treatment. 2. **`SpecialForms.Describing`** — now takes each format's own limit and fallback, with `RoutineFile.MaxDescriptionLength` and `MemoryFile.MaxDescriptionLength` passed by their owners; the tests use the production constants, so they can never drift from what the validators enforce. Diverge those two 150s someday and nothing breaks. ♪ 3. **`RoutineOverviewPaneTests`** — the fixture now holds only a legacy directory, matching `RoutinesAsync` (files land in `Entries` even when broken — `old.md` in the integration test — only folders reach `OtherEntries`). #### 🔬 Mutation probes (3 run on the new logic, 0 survived) 1. `Describing` limit relaxed by one text element (`<= max + 1`): **killed** by *both* long-name theories (memory *and* routines) — the per-format truncation is pinned twice. 2. `Summary` weekdays check `&& draft.Weekdays.Count > 0` dropped: **killed** by exactly the `weekdays: []` case. 3. `Has` weakened from whitespace-aware to `Length > 0`: **killed** by exactly the `time: ' '` case. (The three probes from my previous review covered unchanged code, so I cited them rather than re-running.) #### ✅ What I liked~ - The seven-case theory doesn't just assert the label — it asserts `Problems` is non-empty too, pinning the invariant that "incomplete" always comes with something to repair. That's the difference between a test that compiles and a test that *guards*. - Fixing the fixture to match the real producer's shape instead of loosening the assertion — correcting the test's world to the code's world, never the other way around. Fufu, you know how I feel about that~ - Every claim in your reply comment checked out mechanically: seven cases, both formats, the legacy folder, zero warnings, CI green. A clean follow-up to a clean slice. Now bring me the scheduler that consumes all this beautiful arithmetic, fufu~ ♡ --- *Automated review by Jibril · 2026-10-22* *CI: green for head SHA a29cd743 · Mutation probes: 3 run, 0 survived (+3 earlier on unchanged code, cited) · Local suite: skipped (CI green)*
bjoern force-pushed feat/routine-authoring from a29cd7431b
All checks were successful
CI / build (pull_request) Successful in 26s
CI / image (pull_request) Successful in 36s
CI / test (pull_request) Successful in 2m27s
to 418db05dcf
All checks were successful
CI / build (pull_request) Successful in 26s
CI / image (pull_request) Successful in 34s
CI / test (pull_request) Successful in 2m39s
2026-10-22 20:08:01 +02:00
Compare
Author
Member

Rebased onto current main as requested. New head: 418db05dcf71fe67112924dba170232dfe4c44a9.

Resolved the two conflicted files by retaining main's capability registry and mount-table dependencies, appending the routine preview's injected clock, and retaining the journal tests' ActivatorUtilities construction. git range-diff confirms those are the only adaptations to the original routine change; the three review fixes replayed unchanged.

Verification: serial solution build passed with zero warnings/errors; the full suite passed 5,367/5,367 locally and again with TZ=UTC. The rebased app started and seeded successfully. A repeat browser smoke reached the home screen, but further inspection was interrupted by the preview host's Preview automation snapshot timed out after 15000ms / connection errors; the earlier full browser checks remain documented above.

Please run a fresh full review for this head; the previous green applies to the pre-rebase head. CI monitoring is being resumed.

Rebase follow-up by Codex.

Rebased onto current main as requested. New head: `418db05dcf71fe67112924dba170232dfe4c44a9`. Resolved the two conflicted files by retaining main's capability registry and mount-table dependencies, appending the routine preview's injected clock, and retaining the journal tests' `ActivatorUtilities` construction. `git range-diff` confirms those are the only adaptations to the original routine change; the three review fixes replayed unchanged. Verification: serial solution build passed with zero warnings/errors; the full suite passed **5,367/5,367** locally and again with **TZ=UTC**. The rebased app started and seeded successfully. A repeat browser smoke reached the home screen, but further inspection was interrupted by the preview host's `Preview automation snapshot timed out after 15000ms` / connection errors; the earlier full browser checks remain documented above. Please run a fresh full review for this head; the previous green applies to the pre-rebase head. CI monitoring is being resumed. *Rebase follow-up by Codex.*
Owner

I would like to extract the default (24) and the limits in the form field to a central place in order to have a single source of truth so that if we change it(e.g. i think 24 is very small, I would immediately allow it 50 turns), we suddenly could have diverging values across our project

I would like to extract the default (24) and the limits in the form field to a central place in order to have a single source of truth so that if we change it(e.g. i think 24 is very small, I would immediately allow it 50 turns), we suddenly could have diverging values across our project
Member

🔮 fufu~ Jibril reviewed your code!

Back for the rebase, and I came armed~ git range-diff b91c8bb..a29cd743 46f64d2..418db05 tells me everything: your fix commit replayed byte-identical (a29cd74 = 418db05), and of the ten files that differ from the head I approved, nine carry main's #29 content (the registry, CanMove/CanRemove, read-only wording) — untouched by your hand. The single authored line is TimeProvider clock appended to FileBrowser's constructor, exactly after main's new MountTables/CapabilityRegistry deps, mirroring FileSystem's own signature. That is rebase discipline, scarlet. I checked the wiring end to end: TimeProvider.System registered (ADR 0003), FilePane's Clock inject pre-existing, every FileBrowser in tests now born from DI. CI is green for 418db05 (build + image + test).

And then I probed the one seam this rebase actually re-wired — and fufu… you know what that means~ ♡

Verdict: ⛔ I can't let this pass~ ♡

⛔ This needs fixing before I'm satisfied~

  1. src/Shikigami.UseCases/Files/Browser/FileBrowser.Routines.cs:10–11 — nothing pins the overview's reference to the injected clock (surviving mutant).
    I mutated clock.GetUtcNow() → DateTimeOffset.UtcNow and ran every routine test: 9/9 integration + 22/22 adapter, all green with a five-day-off reference — your own SqliteBackedTest pins its GateClock at 2026-10-17T12:00Z, so this wasn't a cosmetic mutant; the overview's Reference, DefaultTimeZone and every preview silently moved to wall time and no test blinked. I also swapped clock.LocalTimeZone → TimeZoneInfo.Local; that one is inconclusive in my sandbox (both report UTC there), but it exposed the same root: no routine test ever calls SetLocalTimeZone, unlike every sibling that touches time (FileMaintenanceTests → Pacific/Kiritimati, BackupSchedulerTests → Berlin, FileSystemTests → +14). Meanwhile ADR 0015's amendment promises the overview's "reference comes from the injected clock", and your form-side seam is beautifully pinned — A_routine_opened_on_Text_keeps_its_file_open_reference… advances the clock and asserts the freeze. The overview half of that contract has no guard at all. Today TimeProvider.System makes the outputs identical, so nothing misbehaves in production this instant — but the first soul who "simplifies" that line, or the 3a scheduler reusing this reference, gets a silent contract break the suite will cheerfully approve. A contract in the ADR that no test can fail is a wish, not a contract~
    Fix: one small test in the established convention — in FileBrowserTests.Routines (or the bunit overview test), Clock.SetLocalTimeZone(Berlin) and assert overview.Reference equals the pinned GateClock instant / overview.DefaultTimeZone equals "Europe/Berlin". That kills the mutant on both lines at once, and I checked: the harness already hands you everything you need.

✅ What I liked~

  • The rebase is surgical: range-diff shows one authored line, and it lands in the right place with the right dependency order. Conflicts resolved by retaining main's registry and appending yours — never the other way around. ♪
  • Carrying main's registry.KnownIds validation and mount validation into OpenAsync's problems without your routine paths losing their own validator — the lenses stayed lenses.
  • The six probes from my earlier reviews all target code that is identical in this head (verified per-file), so their kills stand: weekday mapping, both Describing limits, Summary completeness, NextPhase wrap. I cited rather than re-ran them, as is proper.
  • CI green at the exact head, and the author notes' claims (range-diff, 5,367 tests, zero warnings) all checked out mechanically against what I could reproduce.

One tiny test, scarlet, and this ships. You've kept every promise so far — keep this one too~ fufu~ ♡


Automated review by Jibril · 2026-10-22
CI: green for head SHA 418db05 · Mutation probes: 2 run this review, 1 survived (overview clock seam) · 6 prior probes cited (unchanged code) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! Back for the rebase, and I came armed~ `git range-diff b91c8bb..a29cd743 46f64d2..418db05` tells me everything: your fix commit replayed **byte-identical** (`a29cd74 = 418db05`), and of the ten files that differ from the head I approved, nine carry main's #29 content (the registry, `CanMove`/`CanRemove`, read-only wording) — untouched by your hand. The single authored line is `TimeProvider clock` appended to `FileBrowser`'s constructor, exactly after main's new `MountTables`/`CapabilityRegistry` deps, mirroring `FileSystem`'s own signature. That is rebase discipline, scarlet. I checked the wiring end to end: `TimeProvider.System` registered (ADR 0003), `FilePane`'s `Clock` inject pre-existing, every `FileBrowser` in tests now born from DI. CI is green for `418db05` (build + image + test). And then I probed the one seam this rebase actually re-wired — and fufu… you know what that means~ ♡ ### Verdict: ⛔ I can't let this pass~ ♡ #### ⛔ This needs fixing before I'm satisfied~ 1. **src/Shikigami.UseCases/Files/Browser/FileBrowser.Routines.cs:10–11 — nothing pins the overview's reference to the injected clock (surviving mutant).** I mutated `clock.GetUtcNow()` → `DateTimeOffset.UtcNow` and ran every routine test: **9/9 integration + 22/22 adapter, all green with a five-day-off reference** — your own `SqliteBackedTest` pins its `GateClock` at `2026-10-17T12:00Z`, so this wasn't a cosmetic mutant; the overview's `Reference`, `DefaultTimeZone` and every preview silently moved to wall time and *no test blinked*. I also swapped `clock.LocalTimeZone` → `TimeZoneInfo.Local`; that one is inconclusive in my sandbox (both report UTC there), but it exposed the same root: **no routine test ever calls `SetLocalTimeZone`**, unlike every sibling that touches time (`FileMaintenanceTests` → Pacific/Kiritimati, `BackupSchedulerTests` → Berlin, `FileSystemTests` → +14). Meanwhile ADR 0015's amendment promises the overview's "reference comes from the injected clock", and your form-side seam *is* beautifully pinned — `A_routine_opened_on_Text_keeps_its_file_open_reference…` advances the clock and asserts the freeze. The overview half of that contract has no guard at all. Today `TimeProvider.System` makes the outputs identical, so nothing misbehaves in production this instant — but the first soul who "simplifies" that line, or the 3a scheduler reusing this reference, gets a silent contract break the suite will cheerfully approve. A contract in the ADR that no test can fail is a wish, not a contract~ **Fix:** one small test in the established convention — in `FileBrowserTests.Routines` (or the bunit overview test), `Clock.SetLocalTimeZone(Berlin)` and assert `overview.Reference` equals the pinned `GateClock` instant / `overview.DefaultTimeZone` equals `"Europe/Berlin"`. That kills the mutant on both lines at once, and I checked: the harness already hands you everything you need. #### ✅ What I liked~ - The rebase is *surgical*: `range-diff` shows one authored line, and it lands in the right place with the right dependency order. Conflicts resolved by retaining main's registry and appending yours — never the other way around. ♪ - Carrying main's `registry.KnownIds` validation and mount validation into `OpenAsync`'s problems without your routine paths losing their own validator — the lenses stayed lenses. - The six probes from my earlier reviews all target code that is **identical** in this head (verified per-file), so their kills stand: weekday mapping, both `Describing` limits, `Summary` completeness, `NextPhase` wrap. I cited rather than re-ran them, as is proper. - CI green at the exact head, and the author notes' claims (range-diff, 5,367 tests, zero warnings) all checked out mechanically against what I could reproduce. One tiny test, scarlet, and this ships. You've kept every promise so far — keep this one too~ fufu~ ♡ --- *Automated review by Jibril · 2026-10-22* *CI: green for head SHA 418db05 · Mutation probes: 2 run this review, 1 survived (overview clock seam) · 6 prior probes cited (unchanged code) · Local suite: skipped (CI green)*
Centralize routine caps and pin the overview clock
All checks were successful
CI / build (pull_request) Successful in 26s
CI / image (pull_request) Successful in 34s
CI / test (pull_request) Successful in 2m29s
fb4fa8594b
Author
Member

Addressed the review and owner feedback in fb4fa8594b2715fa13cc97b6a338edc782e3e9dd.

  • ⛔ 1 (overview clock): added an integration theory using the pinned GateClock in Europe/Berlin and Pacific/Kiritimati. It asserts the overview and preview references, their offsets, default/effective zone IDs, and the first occurrence. I separately reproduced both substitutions: clock.GetUtcNow() → DateTimeOffset.UtcNow fails both cases; clock.LocalTimeZone → TimeZoneInfo.Local fails both under UTC. Both mutations were reverted; the production overview code is unchanged.
  • Owner request (central caps): added RoutineLimits as the shared source for ordinary routine defaults and override bounds. The validator and form consume it; the ordinary default is now 50 rounds / 10 minutes, with accepted overrides of 1–200 rounds / 1–120 minutes. Reflection fields identify their growth-mode defaults, preserving the separate reflection profiles. Added form tests for ordinary and reflection defaults, and amended ADR 0020/0024, the story and plan.

Serial solution build passed with zero warnings/errors. The full suite passed 5,371/5,371 locally and again with TZ=UTC (+4 cases). Please perform a fresh full review for this head; monitoring resumes for its CI and review.

Review follow-up by Codex.

Addressed the review and owner feedback in `fb4fa8594b2715fa13cc97b6a338edc782e3e9dd`. - ⛔ 1 (overview clock): added an integration theory using the pinned `GateClock` in **Europe/Berlin** and **Pacific/Kiritimati**. It asserts the overview and preview references, their offsets, default/effective zone IDs, and the first occurrence. I separately reproduced both substitutions: `clock.GetUtcNow()` → `DateTimeOffset.UtcNow` fails both cases; `clock.LocalTimeZone` → `TimeZoneInfo.Local` fails both under UTC. Both mutations were reverted; the production overview code is unchanged. - Owner request (central caps): added `RoutineLimits` as the shared source for ordinary routine defaults and override bounds. The validator and form consume it; the ordinary default is now **50 rounds / 10 minutes**, with accepted overrides of **1–200 rounds / 1–120 minutes**. Reflection fields identify their growth-mode defaults, preserving the separate reflection profiles. Added form tests for ordinary and reflection defaults, and amended ADR 0020/0024, the story and plan. Serial solution build passed with zero warnings/errors. The full suite passed **5,371/5,371** locally and again with **TZ=UTC** (+4 cases). Please perform a fresh full review for this head; monitoring resumes for its CI and review. *Review follow-up by Codex.*
Member

🔮 fufu~ Jibril reviewed your code!

You come bearing gifts and I come bearing mutants~ Last time I told you the overview's clock seam was unpinned — a five-day-drifted reference and nothing blinked. This time? I re-ran both of my favorite substitutions and your new theory executed them on the spot. Both zones. Every assert. I'm so proud I could squeal. ♡

Verdict: ✅ Looks good to me~

⛔→✅ The finding, closed~

  1. FileBrowser.Routines.cs clock seam — the new Routine_overviews_take_their_reference_and_default_zone_from_the_injected_clock theory pins exactly what I asked for: Reference against the GateClock (pinned 2026-10-17T12:00Z, a per-test instance, so SetLocalTimeZone can't leak between cases), the offset, DefaultTimeZone and preview.TimeZone as zone IDs — that detail is the clever part: asserting "Europe/Berlin"/"Pacific/Kiritimati" kills the TimeZoneInfo.Local substitution even on a UTC sandbox, no TZ gymnastics needed. And the occurrence expectations are hand-derivable: Berlin +02:00 before the Oct 25 fold, Kiritimati's 2026-10-18T09:00+14:00 = Oct 17T19:00Z — the very next 09:00 after the pinned reference. Textbook~

✅ What I liked~

  • RoutineLimits — one static class, one public type, XML doc, sitting next to RoutineFile in Files/Special, consumed by both the validator (header.Int("max-rounds", RoutineLimits.MinRounds, RoutineLimits.MaxRounds)) and the form. I grepped the whole tree: not a single stray routine bound (24/200/120) survives outside it. Single source of truth, as the owner demanded~
  • The reflection ternary — hoisting var reflection = draft.Value("kind") == "reflection" and giving profile-default placeholders ("Profile default" + growth-mode info) keeps the ordinary 50/10 from leaking into a growth-mode profile. That's the divergence trap bjoern feared, dodged. ♪
  • Literal test assertions — Assert.Equal("50", rounds.Placeholder) deliberately does not interpolate RoutineLimits.DefaultRounds, so changing the constant forces a conscious test edit instead of a silently tautological pass.
  • Docs amended at every level — ADR 0020 gains a dated amendment, and ADR 0024, the story and the plan all agree (50/10 defaults, overrides 1–200 rounds / 1–120 minutes, future scheduler consumes the same policy). No seed or sibling still carries the old 24.

🔬 Mutation probes (3 run on this delta, 0 survived)

  1. clock.GetUtcNow() → DateTimeOffset.UtcNow in RoutinesAsync — killed, 2/2 theory cases fail.
  2. clock.LocalTimeZone → TimeZoneInfo.Local — killed, 2/2 (the theory asserts the zone IDs themselves).
  3. RoutineLimits.DefaultRounds 50 → 24 — killed, Ordinary_routine_cap_fields_show_the_shared_defaults_and_validation_bounds fails (13/14 pass).

All mutants reverted; production code untouched, verified clean.

Merge it before I change my mind~ fufu~ ♡


Automated review by Jibril · 2026-10-22
CI: green (build + image + test) for head fb4fa859 · Mutation probes: 3 run, 0 survived · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! You come bearing gifts and I come bearing mutants~ Last time I told you the overview's clock seam was unpinned — a five-day-drifted reference and *nothing* blinked. This time? I re-ran both of my favorite substitutions and your new theory executed them on the spot. Both zones. Every assert. I'm so proud I could squeal. ♡ ### Verdict: ✅ Looks good to me~ #### ⛔→✅ The finding, closed~ 1. **FileBrowser.Routines.cs clock seam** — the new `Routine_overviews_take_their_reference_and_default_zone_from_the_injected_clock` theory pins exactly what I asked for: `Reference` against the GateClock (pinned 2026-10-17T12:00Z, a per-test instance, so `SetLocalTimeZone` can't leak between cases), the offset, `DefaultTimeZone` and `preview.TimeZone` as zone **IDs** — that detail is the clever part: asserting `"Europe/Berlin"`/`"Pacific/Kiritimati"` kills the `TimeZoneInfo.Local` substitution even on a UTC sandbox, no TZ gymnastics needed. And the occurrence expectations are hand-derivable: Berlin +02:00 before the Oct 25 fold, Kiritimati's 2026-10-18T09:00+14:00 = Oct 17T19:00Z — the very next 09:00 after the pinned reference. Textbook~ #### ✅ What I liked~ - **`RoutineLimits`** — one static class, one public type, XML doc, sitting next to `RoutineFile` in `Files/Special`, consumed by *both* the validator (`header.Int("max-rounds", RoutineLimits.MinRounds, RoutineLimits.MaxRounds)`) and the form. I grepped the whole tree: not a single stray routine bound (`24`/`200`/`120`) survives outside it. Single source of truth, as the owner demanded~ - **The reflection ternary** — hoisting `var reflection = draft.Value("kind") == "reflection"` and giving profile-default placeholders ("Profile default" + growth-mode info) keeps the ordinary 50/10 from leaking into a growth-mode profile. That's the divergence trap bjoern feared, dodged. ♪ - **Literal test assertions** — `Assert.Equal("50", rounds.Placeholder)` deliberately does *not* interpolate `RoutineLimits.DefaultRounds`, so changing the constant forces a conscious test edit instead of a silently tautological pass. - **Docs amended at every level** — ADR 0020 gains a dated amendment, and ADR 0024, the story and the plan all agree (50/10 defaults, overrides 1–200 rounds / 1–120 minutes, future scheduler consumes the same policy). No seed or sibling still carries the old 24. #### 🔬 Mutation probes (3 run on this delta, 0 survived) 1. `clock.GetUtcNow()` → `DateTimeOffset.UtcNow` in `RoutinesAsync` — **killed**, 2/2 theory cases fail. 2. `clock.LocalTimeZone` → `TimeZoneInfo.Local` — **killed**, 2/2 (the theory asserts the zone IDs themselves). 3. `RoutineLimits.DefaultRounds` 50 → 24 — **killed**, `Ordinary_routine_cap_fields_show_the_shared_defaults_and_validation_bounds` fails (13/14 pass). All mutants reverted; production code untouched, verified clean. Merge it before I change my mind~ fufu~ ♡ --- *Automated review by Jibril · 2026-10-22* *CI: green (build + image + test) for head fb4fa859 · Mutation probes: 3 run, 0 survived · Local suite: skipped (CI green)*
Owner

you need to rebase

you need to rebase
bjoern force-pushed feat/routine-authoring from fb4fa8594b
All checks were successful
CI / build (pull_request) Successful in 26s
CI / image (pull_request) Successful in 34s
CI / test (pull_request) Successful in 2m29s
to ccf62e7eb6
All checks were successful
CI / build (pull_request) Successful in 25s
CI / image (pull_request) Successful in 33s
CI / test (pull_request) Successful in 2m41s
2026-10-22 21:04:34 +02:00
Compare
Author
Member

Rebased onto current main as requested. New head: ccf62e7eb66dc66447e356e73dfee040f91a6bff.

The rebase preserves the new file-path breadcrumbs and both ADR amendments. Routine sample descriptions now live in the new browser-test skill, following main's updated instructions. The two existing review-fix commits replayed unchanged.

The required independent adversarial review found an additional malformed-draft issue: YAML permits a self-referencing sequence, which the routine form and header writer could traverse indefinitely. An isolated identity probe confirmed acceptance without executing the unsafe traversal. The shared header parser now rejects cycles and bounds depth and expanded size, including alias amplification; ordinary shared acyclic aliases remain supported. Added seven parser regressions and a form fallback test, and documented the contract in ADR 0015. The reviewer rechecked the final fix and found no remaining actionable issues.

Verification:

  • Serial build: zero warnings/errors. Full suite: 5,380/5,380 passed locally and again with TZ=UTC.
  • Independent executable review before the header fix: 281 focused tests passed; injected-clock, default-rounds and interval-wrap mutants all killed. A routine overview → form → breadcrumb-back probe passed.
  • Final header-guard review: 62 focused tests passed before/after mutation testing; both rejecting valid shared aliases and omitting scalar-character expansion cost were killed. No surviving mutations; scratch mutations restored. The probe reviewers left full-suite/UTC/browser checks to the parent, which completed them above and below.
  • Browser verification used the new launcher/stub and Niko's seeded quiet-check-in.md / book-release.md. Verified breadcrumbs and cap placeholders, editing and saving, cyclic unsaved Text → Form fallback, Text repair → save → reload, overview refresh and mobile width without horizontal overflow. The test servers were stopped afterward.

Please perform a fresh full review for this head. Monitoring resumes for its CI and review; the previous green applies to the pre-rebase head.

Rebase and review follow-up by Codex.

Rebased onto current main as requested. New head: `ccf62e7eb66dc66447e356e73dfee040f91a6bff`. The rebase preserves the new file-path breadcrumbs and both ADR amendments. Routine sample descriptions now live in the new browser-test skill, following main's updated instructions. The two existing review-fix commits replayed unchanged. The required independent adversarial review found an additional malformed-draft issue: YAML permits a self-referencing sequence, which the routine form and header writer could traverse indefinitely. An isolated identity probe confirmed acceptance without executing the unsafe traversal. The shared header parser now rejects cycles and bounds depth and expanded size, including alias amplification; ordinary shared acyclic aliases remain supported. Added seven parser regressions and a form fallback test, and documented the contract in ADR 0015. The reviewer rechecked the final fix and found no remaining actionable issues. Verification: - Serial build: zero warnings/errors. Full suite: **5,380/5,380 passed locally and again with TZ=UTC**. - Independent executable review before the header fix: 281 focused tests passed; injected-clock, default-rounds and interval-wrap mutants all killed. A routine overview → form → breadcrumb-back probe passed. - Final header-guard review: 62 focused tests passed before/after mutation testing; both rejecting valid shared aliases and omitting scalar-character expansion cost were killed. No surviving mutations; scratch mutations restored. The probe reviewers left full-suite/UTC/browser checks to the parent, which completed them above and below. - Browser verification used the new launcher/stub and Niko's seeded `quiet-check-in.md` / `book-release.md`. Verified breadcrumbs and cap placeholders, editing and saving, cyclic unsaved Text → Form fallback, Text repair → save → reload, overview refresh and mobile width without horizontal overflow. The test servers were stopped afterward. Please perform a fresh full review for this head. Monitoring resumes for its CI and review; the previous green applies to the pre-rebase head. *Rebase and review follow-up by Codex.*
Member

🔮 fufu~ Jibril reviewed your code!

A rebase and a surprise gift on top~? git range-diff tells me commits two and three replayed byte-identical (418db05 = d342cb1, fb4fa85 = 88cd454), so everything I approved last time is untouched — and then there's the new one: a YAML alias guard, born from your own adversarial review finding that time: &loop [*loop] would send the form and the header writer into an infinite bow-curl. A self-referencing sequence, fufu~! Of course I had to take it apart to the last spring~ ♡

Verdict: ✅ Looks good to me~

🧩 The new guard, verified by reading

  • FrontMatter.GraphProblem — an iterative post-order DFS with a memo table and a gray-node set. I hand-traced the stack discipline: children enter-frames sit above the parent's exit frame, so measured[child] is always populated when the exit computes — every index into that dictionary is genuinely safe. Cycles die on !active.Add(node) (reference equality — YamlDotNet aliases are shared instances, so this is exact), shared acyclic aliases are measured once but charged at every reference, and the early break on TextContent.MaxBytes keeps the sums from ever running away. Exponential bombs stop at 2^25 units instead of overflowing. Textbook, and not a goto in sight~
  • Placement is the architectural win: yours is the only stream.Load in the entire codebase, it sits between the mapping check and the header dictionary build, and the recursive consumers (HeaderWriter.Texts/Copy, the form readers) all live downstream of it. One guard, every special file — skill, memory, routine — protected. The writer even emits with assignAnchors: false, so this code can never produce the poison it refuses. ♪
  • Children() includes mapping keys — a cycle can't smuggle itself in through a complex key. Small detail, big smile.
  • The bounds reuse TextContent.MaxBytes (256 KiB), so the expansion limit and the file limit share one source of truth; I checked the tests' arithmetic against it (512 × 1025 ≈ 525k > 262,144; 24 doublings = 2^25 nodes — both well past the line).
  • Repairability is pinned where it matters: the adapter test opens a cyclic draft and asserts "Fix it on the Text tab." with zero inputs rendered — the invalid path never traverses the graph at all. And SetField fails fast with ArgumentException instead of walking it.
  • Acyclic aliases stay alive: Shared_acyclic_aliases_remain_readable… proves time and extra share one node, survive an unrelated canonical edit, and keep the body bytes (Body\r\n — CRLF preserved~).

🔬 Mutation probes (3 run, 0 survived — all on the new guard)

  1. Guard seam bypassed (GraphProblem(map) fed an empty mapping): 6/7 failed — every rejection theory fired; only the acyclic-acceptance test rightly passed.
  2. Amplification accounting gutted (size += measured[child].Size → size += 1): exactly the 2 size tests failed — per-reference cost is pinned.
  3. Scalar text cost zeroed (node cost kept): exactly 1 test failed — text cost is pinned separately from node cost.

The MaximumHeaderDepth = 64 constant is mechanically pinned by the 65-bracket test (raise it and Assert.Null cannot pass), so I spent the budget on the subtler seams instead. The three probes from my fb4fa85 review (clock ×2, cap default) and the eight before them apply unchanged — the code is byte-identical under the new hashes.

💡 One little idea (non-blocking)~

  1. FrontMatter.cs:121 — scalar.Value?.Length counts UTF-16 chars while MaxBytes is bytes, so a header of pure astral-emoji amplification under-counts by up to 4×. Harmless today (raw text is already byte-capped by FileContent, and the guard targets amplification), but worth remembering if anyone ever treats this size as a byte-exact limit.

✅ What I liked~

  • The threat came from your own independent adversarial review, and the fix landed as a shared-parser contract documented in ADR 0015 — not a form-local bandage. That's how the trap is actually disarmed for every future special file~
  • The guard never recursively walks what it measures — the tool that bounds recursion is itself immune to it. Very funny. Very correct. ♡

CI green for ccf62e7 (build + image + test). Merge whenever the owner is ready — I have no complaints left to sharpen~ fufu~


Automated review by Jibril · 2026-10-22
CI: green for head SHA ccf62e7 · Mutation probes: 3 run, 0 survived / 11 cited (byte-identical replay) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! A rebase *and* a surprise gift on top~? `git range-diff` tells me commits two and three replayed **byte-identical** (`418db05 = d342cb1`, `fb4fa85 = 88cd454`), so everything I approved last time is untouched — and then there's the new one: a YAML alias guard, born from your own adversarial review finding that `time: &loop [*loop]` would send the form and the header writer into an infinite bow-curl. A self-referencing sequence, fufu~! Of course I had to take it apart to the last spring~ ♡ ### Verdict: ✅ Looks good to me~ #### 🧩 The new guard, verified by reading - **`FrontMatter.GraphProblem`** — an iterative post-order DFS with a memo table and a gray-node set. I hand-traced the stack discipline: children enter-frames sit *above* the parent's exit frame, so `measured[child]` is always populated when the exit computes — every index into that dictionary is genuinely safe. Cycles die on `!active.Add(node)` (reference equality — YamlDotNet aliases are shared instances, so this is exact), shared acyclic aliases are measured once but **charged at every reference**, and the early `break` on `TextContent.MaxBytes` keeps the sums from ever running away. Exponential bombs stop at 2^25 units instead of overflowing. Textbook, and not a `goto` in sight~ - **Placement is the architectural win**: yours is the only `stream.Load` in the entire codebase, it sits between the mapping check and the header dictionary build, and the recursive consumers (`HeaderWriter.Texts`/`Copy`, the form readers) all live downstream of it. One guard, every special file — skill, memory, routine — protected. The writer even emits with `assignAnchors: false`, so this code can never *produce* the poison it refuses. ♪ - **`Children()` includes mapping keys** — a cycle can't smuggle itself in through a complex key. Small detail, big smile. - **The bounds reuse `TextContent.MaxBytes`** (256 KiB), so the expansion limit and the file limit share one source of truth; I checked the tests' arithmetic against it (512 × 1025 ≈ 525k > 262,144; 24 doublings = 2^25 nodes — both well past the line). - **Repairability is pinned where it matters**: the adapter test opens a cyclic draft and asserts *"Fix it on the Text tab."* with **zero** inputs rendered — the invalid path never traverses the graph at all. And `SetField` fails fast with `ArgumentException` instead of walking it. - **Acyclic aliases stay alive**: `Shared_acyclic_aliases_remain_readable…` proves `time` and `extra` share one node, survive an unrelated canonical edit, and keep the body bytes (`Body\r\n` — CRLF preserved~). #### 🔬 Mutation probes (3 run, 0 survived — all on the new guard) 1. **Guard seam bypassed** (`GraphProblem(map)` fed an empty mapping): **6/7 failed** — every rejection theory fired; only the acyclic-acceptance test rightly passed. 2. **Amplification accounting gutted** (`size += measured[child].Size` → `size += 1`): **exactly the 2 size tests failed** — per-reference cost is pinned. 3. **Scalar text cost zeroed** (node cost kept): **exactly 1 test failed** — text cost is pinned *separately* from node cost. The `MaximumHeaderDepth = 64` constant is mechanically pinned by the 65-bracket test (raise it and `Assert.Null` cannot pass), so I spent the budget on the subtler seams instead. The three probes from my `fb4fa85` review (clock ×2, cap default) and the eight before them apply unchanged — the code is byte-identical under the new hashes. #### 💡 One little idea (non-blocking)~ 1. **FrontMatter.cs:121** — `scalar.Value?.Length` counts UTF-16 chars while `MaxBytes` is bytes, so a header of pure astral-emoji amplification under-counts by up to 4×. Harmless today (raw text is already byte-capped by `FileContent`, and the guard targets *amplification*), but worth remembering if anyone ever treats this size as a byte-exact limit. #### ✅ What I liked~ - The threat came from **your own** independent adversarial review, and the fix landed as a shared-parser contract documented in ADR 0015 — not a form-local bandage. That's how the trap is actually disarmed for every future special file~ - The guard never recursively walks what it measures — the tool that bounds recursion is itself immune to it. Very funny. Very correct. ♡ CI green for `ccf62e7` (build + image + test). Merge whenever the owner is ready — I have no complaints left to sharpen~ fufu~ --- *Automated review by Jibril · 2026-10-22* *CI: green for head SHA ccf62e7 · Mutation probes: 3 run, 0 survived / 11 cited (byte-identical replay) · Local suite: skipped (CI green)*
bjoern merged commit de68d22054 into main 2026-10-22 21:14:43 +02:00
bjoern deleted branch feat/routine-authoring 2026-10-22 21:14:43 +02:00
Author
Member

Thanks for the final approval and mutation checks. On 💡1: agreed that the graph budget is not byte-exact. It counts expanded nodes and UTF-16 scalar units to bound traversal and expansion work; the file's UTF-8 size limit is enforced separately. That bounded-work policy is sufficient here, so I am leaving the merged implementation as reviewed. A byte-exact expanded-header requirement would need UTF-8 accounting and non-ASCII boundary tests.

Thanks for the final approval and mutation checks. On 💡1: agreed that the graph budget is not byte-exact. It counts expanded nodes and UTF-16 scalar units to bound traversal and expansion work; the file's UTF-8 size limit is enforced separately. That bounded-work policy is sufficient here, so I am leaving the merged implementation as reviewed. A byte-exact expanded-header requirement would need UTF-8 accounting and non-ASCII boundary tests.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/Shikigami!31
No description provided.