Repository navigation
task-manager v0.8.0
Upgrading from v0.7.1. The SDK module is released alongside as sdk/v0.8.0.
New: taskmgr config
Configuration is now editable from the command line. Two files are addressable: the
resolved store's .tasks/config.yaml, and your per-user ~/.taskmgr/config.yaml with
--global, which needs no store and works in any directory.
taskmgr config keys # every supported key, both scopes
taskmgr config list # current values, with the file's path
taskmgr config get hook_timeout
taskmgr config set hook_timeout 5m
taskmgr config unset hook_timeoutHooks are managed with taskmgr config hook, which owns the hooks block:
taskmgr config hook add --event pre-close --run make --run test
taskmgr config hook list # in run order, with each effective id
taskmgr config hook rm pre-close#0Global hooks. A hooks block in the per-user config applies to every store on the
machine and runs before the store's own. The per-user file does not travel with a
repository, so it fits personal ergonomics — a reminder, a local lint — and not a rule
the data depends on. Inherited hooks carry a global: prefix on their id wherever they
appear, so a refusal always tells you which file to edit. A store cannot switch them off.
JSON surface: store and health
For anyone driving taskmgr --json across several stores:
issueDTOand thecreateresult carrystore, the central-registry name of the
store the issue came from. Omitted for a local store, which has no registry entry.store listrows carryhealth:ok,dangling(the entry is registered, its
directory is gone) orbroken(a directory with noconfig.yaml). Classification is
onestatper entry, so a listing and a resolution never disagree, and a store
switcher can hide the rows that will not open instead of failing one per selection.
Fixes
- Concurrent
taskmgr configwrites no longer discard each other. Twelve at once
used to leave one edit and report success twelve times. The read now happens inside
the file lock, and per-user writes take one at all (~/.taskmgr/.config.lock). - A malformed hook can be removed again. Two bad entries in the per-user config used
to fail every write on the machine and refuseconfig hook rmfor both ids, leaving
a hand edit as the only way out. A write now validates only what it introduces. - A central store stays writable when its project directory is deleted. A hook now
runs in the store directory when the project root is gone, instead of failing the
spawn and reporting a binary that plainly exists as "could not execute". store listno longer calls an intact storedangling. Astatthat fails for
any reason other than "not found" is reported as itself; only a missing directory is
dangling. Selecting a dangling store by name also gets its own message, since the
repair differs from a broken one.taskmgr -C . initderives the ID prefix from the directory's real name rather than
falling back totask— which mattered, because the prefix cannot be changed later.taskmgr config --global listworks, not onlytaskmgr config list --global.- A denied or failed hook writes its log record to the invocation's stderr.
Changes worth checking before you upgrade
- A declared hook
idmay no longer contain#. The character is reserved for the
defaulted<event>#<index>id, so the two sources can never collide. If an existing
config.yamldeclares one —id: pre-close#1— every write in that store fails
until it is renamed. Edit the id in the file, or remove the entry with
taskmgr config hook rmand add it back with a valid id. taskmgr config set <key> ""now exits 1 and points atconfig unset. It used to
perform the unset and report success, so a script passing an unset shell variable
silently reverted the key.taskmgr store listexits 1 when it cannot read a store directory, instead of
listing it asdangling.
For integrators — sdk/v0.8.0
go get github.com/hk9890/task-manager/sdk@v0.8.0Breaking
Stores() no longer takes ResolveOptions.
entries, err := tasks.Stores(opts) // sdk/v0.7.0
entries, err := tasks.Stores() // sdk/v0.8.0The registry is global, so a working directory and a store-name override selected
nothing; the parameter was accepted and discarded, which made --dir and --store-name
look as though they filtered store list. This is the only signature change, and it is
why the tag is a minor rather than a patch.
Stores() can now return an error where it previously returned rows. A stat that
fails on a store directory is no longer flattened into StoreDangling. Handle the error;
do not treat a failed listing as an empty one.
Resolution reports a dangling named store differently. Resolve with a StoreName
whose directory is gone returns a message about a missing directory rather than the
"not a finished store (no config.yaml)" text. The sentinels are unchanged — only code
matching on message text is affected.
Added
UpdateConfig, UpdateGlobalConfig, LoadGlobalConfig, SaveGlobalConfig,
GlobalConfigPath, GlobalConfig, HookID, DerivePrefix, StoreHealth,
StoreEntry.Health, Store.Name, Store.Config, Store.SetConfig.
InitWithVFS gained variadic options, which existing calls keep compiling through.
Behaviour to be aware of
- Prefer
UpdateConfig/UpdateGlobalConfigoverSetConfig/SaveGlobalConfig.
The pair taking a mutation function does the read, the change and the write inside one
hold of the lock. The setters replace the file from a snapshot read outside it, so they
are last-writer-wins by construction and are documented as such. Store.Config()now returns a deep copy, each hook'sRunargv included. It
previously shared those slices with the compiled hooks, so editing the returned value
changed the gate the next mutation executed.- A hook's working directory falls back to the store directory when the project root
no longer exists.TASKMGR_STOREalways names the data directory. - Writing the per-user config creates
<home>/.config.lock, a separate advisory lock
from the central root's.lock.
Verifying the download
The release carries per-archive SBOMs and a keyless cosign signature over the manifest.
Needs cosign 3.x.
sha256sum -c checksums.txt
cosign verify-blob checksums.txt \
--bundle checksums.txt.bundle \
--certificate-identity-regexp '^https://github\.com/hk9890/task-manager/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com