Docs & rules

obra/laceGitHub

This is a public, read-only report. Striff reads this repository's docs, turns each sentence that makes a claim about the code into a rule, and checks the rule against the code on the default branch. How this works

maina040e95Last read 9h ago

Is this yours? Install to manage it

Once installed, Striff checks every pull request.

Documents
Rules
61
58
13
13
12
1
11
18
18
9
9
3
3
3
6
3
3
3
3
3
154 docs

obra/lace — documented rules

61 of 61 rules, printed October 12, 2026.

The sentence in your docs
Read Oct 11
registers lifecycle/progress subscriptions through JobManager.subscribe().
JobManager has a subscribe method
Holds
Read Oct 11
reads status and output for an in-memory running job via JobManager.getJob() and JobManager.getJobOutput();
JobManager has a getJob method
Holds
Read Oct 11
lists durable job records through JobManager.listJobs() with status/type/limit filters.
JobManager has a listJobs method
Holds
Read Oct 11
cancels running jobs through JobManager.cancelJob() and optionally disposes tracked per-invocation delegate workspaces through WorkspaceReaper.
JobManager has a cancelJob method
Holds
Read Oct 11
These tools require a jobManager in ToolContext;
ToolContext has jobManager
Holds
Read Oct 11
JobManager.createJob(type, options) performs the main current creation flow (packages/agent/src/jobs/job-manager.ts):
JobManager has a createJob method
Holds
Read Oct 11
DelegateTool.executeValidated() (packages/agent/src/tools/implementations/delegate.ts) resolves delegate-specific inputs before calling JobManager.createJob('delegate', ...):
2 rules from this sentence
DelegateTool depends on JobManager
Holds
DelegateTool has an executeValidated method
checks “DelegateTool.executeValidated()”
Holds
Read Oct 11
jobStreaming/JobManager.streamingMode supports 'full' | 'coalesced' | 'none';
JobManager has streamingMode
Holds
Read Oct 11
JobManager.getJobOutput(jobId) reads the full output file for the active session and returns an empty string if there is no active session or the file is missing.
JobManager has a getJobOutput method
Holds
Read Oct 11
notifications are composed and injected by packages/agent/src/jobs/job-notifications.ts and routed through JobManager.fanoutToInject().
JobManager has a fanoutToInject method
Holds
Read Oct 11
JobManager.finalizeJob() in packages/agent/src/jobs/job-manager.ts is an internal manager path.
JobManager has a finalizeJob method
Holds
Read Oct 11
workspaceReaper.dispose() routes through the container manager/shim release path, destroying the per-invocation container and removing /work.
WorkspaceReaper depends on ContainerManager
Holds
Read Oct 11
CompactionStrategy interface for extensibility
CompactionStrategy is a contract
Holds
Read Oct 11
All tools extend the abstract Tool class from src/tools/tool.ts:
11 rules from this sentence
BashTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
DelegateTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
FileEditTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
FileReadTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
FileWriteTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
ManageRemindersTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
RecallTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
UseSkillTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
ScanFileTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
ScanTextTool extends Tool
checks “All tools extend the abstract Tool class”
Holds
Tool is declared abstract
checks “abstract Tool class”
Holds
Read Oct 11
assertVersion(major) throws PluginVersionError unless major equals the kernel's plugin-contract major version (KERNEL_PLUGIN_VERSION, currently 1.0.0 → major 1).
PluginApi has an assertVersion method
Holds
Read Oct 11
Extend the abstract Tool class:
Tool is declared abstract
Holds
Read Oct 11
ToolContext.persona is the authoritative session identity, stamped server-side from the session's persona.
ToolContext has persona
Holds
Read Oct 11
To invoke a tool directly (e.g. in a test), call its public execute (not the protected executeValidated): tool.execute(args: unknown, ctx: ToolContext).
2 rules from this sentence
Tool has an execute method
checks “its public execute”
Holds
Tool has executeValidated
checks “the protected executeValidated”
Holds
Read Oct 11
the only required one is signal: AbortSignal.
ToolContext has signal
Holds
Read Oct 11
Field workingDirectory string, Use session cwd — resolve relative paths against it, fall back to process.cwd()
ToolContext has a workingDirectory field
Holds
Read Oct 11
Field threadId / projectId, Use session/project identity metadata
2 rules from this sentence
ToolContext has a threadId field
Holds
ToolContext has a projectId field
Holds
Read Oct 11
Field toolTempDir string, Use per-call scratch dir (via getToolTempDir(ctx) )
ToolContext has a toolTempDir field
Holds
Read Oct 11
Field processEnv NodeJS.ProcessEnv, Use env for subprocess execution
ToolContext has a processEnv field
Holds
Read Oct 11
A PreservedEntry is { role: string; content: string | Block[]; toolCalls?: unknown[]; toolResults?: unknown[] } where Block = { type: string; [k: string]: unknown }.
4 rules from this sentence
PreservedEntry has role
Holds
PreservedEntry has content
Holds
PreservedEntry has toolCalls
Holds
PreservedEntry has toolResults
Holds
Read Oct 11
PreservedEntry is exported from @lace/agent/compaction/toolkit — import the type rather than re-declaring it.
PreservedEntry is exported
Holds
Read Oct 11
inspect reads the in-process cache (and may be synchronous);
ContainerRuntime has inspect
Holds
Read Oct 11
daemonInspect hits the daemon and returns null when the container does not exist — that null case is how ContainerManager adopts boxes after a parent restart.
ContainerRuntime has daemonInspect
Holds
Read Oct 11
The CompactionContext.sessionDir parameter is what the strategy uses to call appendDurableEvent(sessionDir, readSessionState(sessionDir), event) directly.
CompactionContext has sessionDir
Holds
Read Oct 11
Method name is compact, not runCompaction (Important 6). The existing strategy interface (compaction/types.ts — CompactionStrategy.compact(events, ctx)) names this method compact;
CompactionStrategy has a compact method
Holds
Read Oct 11
The existing strategy interface (compaction/types.ts — CompactionStrategy.compact(events, ctx)) names this method compact;
CompactionStrategy is a contract
Holds
Read Oct 11
injectNotification() writes a context_injected durable event (<notification> wrapper, priority immediate), and optionally idle-wakes the session to run an internal turn (IdleWakeHooks: isActive / hasActiveTurn / triggerInternalTurn).
3 rules from this sentence
IdleWakeHooks has isActive
Holds
IdleWakeHooks has hasActiveTurn
Holds
IdleWakeHooks has triggerInternalTurn
Holds
Read Oct 11
RPC surface is unaffected — ent/personas/list → PersonaRegistry.listAvailablePersonas() → PersonaInfo[], which Part 0 preserves.
PersonaRegistry has a listAvailablePersonas method
Holds
Read Oct 11
Name-seam. ExecToolAdapter currently hard-sets this.name = descriptor.name with no override (exec-tool-adapter.ts).
ExecToolAdapter has name
Holds
Read Oct 11
the per-session SkillRegistry still feeds use_skill and SkillVariableProvider (the prompt skill list).
SkillVariableProvider depends on SkillRegistry
Holds
Read Oct 11
A plugin exports register(api) and (recommended) meta.
2 rules from this sentence
PluginModule has a register method
checks “A plugin exports register(api)”
Holds
PluginModule has meta
checks “and (recommended) meta”
Holds
Read Oct 11
extends Tool gives you input validation (your Zod schema is enforced before executeValidated runs) and result helpers (createResult, createError).
3 rules from this sentence
Tool has createResult
Holds
Tool has createError
Holds
Tool has executeValidated
Holds
Read Oct 11
ContainerRuntime is the heaviest contract (lifecycle + exec + inspect + adopt).
ContainerRuntime is a contract
Holds
Read Oct 11
The single registration site is ToolExecutor.registerAllAvailableTools in packages/agent/src/tools/executor.ts:283-311.
ToolExecutor has registerAllAvailableTools
Holds
Read Oct 11
The single registration site is ToolExecutor.registerAllAvailableTools in packages/agent/src/tools/executor.ts:283-311. The instance list lives at lines 287–303 — new BashTool(), new FileReadTool(), …, new ManageRemindersTool() — with UseSkillTool conditionally appended at 306–308 when a SkillRegistry is wired in.
ToolExecutor depends on UseSkillTool
Holds
Read Oct 11
All instances are then handed to this.registerTools(tools) at line 310.
ToolExecutor has a registerTools method
Holds
61 rules from 9 docs

See these where the change is. The browser extension puts a pull request's doc findings, and a diagram of what it changed, on the GitHub page itself, so the code and what your docs say about it are side by side.