taskops-cli 0.5.2__tar.gz → 0.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ARCHITECTURE.md +14 -3
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/CHANGELOG.md +37 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/PKG-INFO +1 -1
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/smoke.sh +74 -14
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_version.py +1 -1
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/stale.py +22 -3
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/ui/app.js +9 -9
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_topology.py +99 -0
- taskops_cli-0.5.4/ui/smoke/sections/card-diff-range.tsx +119 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/git-diff.tsx +1 -1
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/Patch.tsx +34 -21
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/Sections.tsx +16 -18
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/links.tsx +73 -34
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/pages/WorktreeDiff.tsx +5 -2
- taskops_cli-0.5.2/ui/smoke/sections/card-head-sha.tsx +0 -84
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.claude/settings.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.gitattributes +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.github/workflows/ci.yml +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.github/workflows/workflow.yml +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.gitignore +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.mcp.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/cache.sqlite +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/cache.sqlite-shm +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/cache.sqlite-wal +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/events.jsonl +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/live.sqlite +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/live.sqlite-shm +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board/live.sqlite-wal +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/board.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/reports/lifecycle-chapter.html +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/reports/reports-chapter.html +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/.taskops/ui.lock +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/CLAUDE.md +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/README.md +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/pyproject.toml +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_clock.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_errors.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_ids.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_json.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_locate.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/_wire.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/board.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/__main__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/admin.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/claude.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/commands.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/enrol.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/github.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/gitremote.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/grants.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/hooks.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/main.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/operate.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/paging.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/parser.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/pull.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/push.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/remote.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/rm.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/serving.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/team.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/watch.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/window.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/cli/wording.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/actors.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/challenge.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/chapters.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/event.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/forge.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/graph.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/holding.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/hours.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/kinds.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/machine.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/mentions.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/replay.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/reports.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/review.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/scope.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/seams.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/core/types.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/bare.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/bind.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/catchup.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/claudefiles.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/diff.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/install.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/landing.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/onward.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/patch.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/remote.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/run.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/sig.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/trailer.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/gitwork/trees.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/admin.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/auth.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/feed.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/gitbody.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/gitdoor.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/gitpack.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/grants.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/handler.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/ingest.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/login.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/members.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/mounts.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/page.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/removal.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/repos.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/routes.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/rpc.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/scoped.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/server.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/static.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/upstream.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/http/watcher.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/identity.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/__main__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/activity.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/before.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/boards.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/boardview.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/brief.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/chapter.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/dossier.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/fields.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/gitmoves.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/hello.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/integrate.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/orders.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/render.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/schema.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/server.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/thread.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/mcp/tools.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/py.typed +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/session.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/cache.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/creds.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/handover.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/live.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/log.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/mirroring.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/pubkeys.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/reviews.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/server.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/store/stores.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/ui/index.html +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/ui/style.css +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_args.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_cards.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_chapter.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_context.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_facts.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_mentions.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_rows.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_stories.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_waiting.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/_windows.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/activity.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/assign.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/card.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/events.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/filed.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/plan.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/project.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/pulse.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/record.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/report.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/review.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/take.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/src/taskops/verbs/update.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/__init__.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/conftest.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_architecture.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_claude.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_core.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_git.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_mcp.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_mirror.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_report.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_store.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_ui.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_verbs.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/test_window.py +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/tests/ui_harness.js +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/build.mjs +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/index.html +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/package-lock.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/package.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/fixture.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/main.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/run.mjs +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/actors-window-filter.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/actors.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/all-chapters-scope.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/board-columns.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/board-flow-view.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/board-motion-and-avatars.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/board-root-mount.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/chapter-completion-derivation.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/chapter-landed.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/chapter-story-grid.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/chapters-open.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/comment-box.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/comment-toasts-model.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/comment-toasts-stack.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/diff-page.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/dossier.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/event-stream.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/feed-reconnect.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/forge-links.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/forge-opens-the-board.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/hosted-window.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/monitor-panes.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/overlay-escape.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/report-markdown.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/report-sandbox.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/reviewing-skew.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/section.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/swarm-topology.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/thread-closing-note.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections/worktrees-index.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/smoke/sections.mjs +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/App.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/client.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/completed.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/actors/Daysheet.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/actors/DevPanel.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/board/CardTile.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/board/Column.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/board/ViewToggle.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/board/flip.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/board/useFlip.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/CommentBox.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/Drawer.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/Thread.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/split.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/card/tokens.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/chrome/AvatarStack.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/chrome/Header.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/chrome/KpiRail.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/chrome/MilestonePicker.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/chrome/TabNav.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/flow/FlowView.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/flow/layout.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/Chapter.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/DependencyChain.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/EditSurface.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/EventStream.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/LeaseHealth.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/LiveLeases.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/Mentions.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/Pane.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/Swarm.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/Throughput.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/monitor/panels.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/reports/ReportFrame.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/shared/Avatar.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/shared/Markdown.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/shared/Overlay.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/shared/Segmented.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/shared/overlayStack.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/story/ChapterStory.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/story/stats.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/toasts/ToastStack.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/toasts/model.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/components/toasts/useToasts.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/format.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/hoursWindow.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/main.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/markdown.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/pages/Actors.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/pages/Board.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/pages/Monitor.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/pages/Reports.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/pages/Worktrees.tsx +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/theme/theme.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/theme/tokens.css +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/types.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/useBoard.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/src/useEvents.ts +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/styles/index.css +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/ui/tsconfig.json +0 -0
- {taskops_cli-0.5.2 → taskops_cli-0.5.4}/uv.lock +0 -0
|
@@ -1526,9 +1526,16 @@ below — and comes back only standing on a real history: the forge mirror, in
|
|
|
1526
1526
|
That cascade is ONE function — `ui/src/links.tsx::cascade`, beside the slug and
|
|
1527
1527
|
the link templates it already owned — and `ui/src/components/card/Patch.tsx`
|
|
1528
1528
|
only DRAWS the step it is handed, so no component holds a fallback order of its
|
|
1529
|
-
own. It feeds the dossier's **Files changed** (the card as a PR
|
|
1530
|
-
|
|
1531
|
-
|
|
1529
|
+
own. It feeds the dossier's **Files changed** (the card as a PR, over the range
|
|
1530
|
+
the BOARD recorded rather than two branch names — `links.tsx::cardRange`: one
|
|
1531
|
+
recorded commit goes through `commit/<sha>`, which the door diffs against its
|
|
1532
|
+
first parent, and several become `compare/<first>^...<last>`, whose base is the
|
|
1533
|
+
oldest commit's PARENT so that commit's own changes are inside the range. Both
|
|
1534
|
+
ends are durable, which is what makes the pane render for a card whose `tk-*`
|
|
1535
|
+
and `ms/*` branches were pruned before this host became the remote — the head
|
|
1536
|
+
alone was not enough, 0.5.2 shipped that and the pane stayed empty. Then the
|
|
1537
|
+
file list from `stat`, each file's patch on expand via `?path=`) and the fold on
|
|
1538
|
+
every commit row. Availability is
|
|
1532
1539
|
DISCOVERED, not configured: the first refusal whose words are
|
|
1533
1540
|
`gitdoor.py::NO_REPO` flips a module-level flag for the session and nothing asks
|
|
1534
1541
|
again — an unknown ref does not flip it, because that means "ask again for
|
|
@@ -1542,6 +1549,10 @@ effect firing, and that half is covered against a real server in
|
|
|
1542
1549
|
chapter): `pages/WorktreeDiff.tsx`, the full-width page a Worktrees row opens,
|
|
1543
1550
|
hands its whole range `<milestone branch>...tk-<id>` to the very same
|
|
1544
1551
|
`FilesChanged` — plus a summary bar, which is a prop on it and not a second ask.
|
|
1552
|
+
Two live BRANCHES there, deliberately, where the dossier asks by sha: that page's
|
|
1553
|
+
subject is a working tree that exists on disk right now, so where its two tips
|
|
1554
|
+
stand IS the question. `FilesChanged` therefore takes a whole `GitTarget` rather
|
|
1555
|
+
than a base/head pair — a pair could only ever express the second question.
|
|
1545
1556
|
Nothing else moved to do that: **no verb, no stored key, no change to the door**,
|
|
1546
1557
|
and no component fetches a patch outside `cascade()`. The one seam this cost is
|
|
1547
1558
|
`FileList` exported beside `FilesChanged` — the pure half, given a step — for
|
|
@@ -3,6 +3,43 @@
|
|
|
3
3
|
The source of truth for release notes — GitHub Releases are extracted from
|
|
4
4
|
here, never written twice.
|
|
5
5
|
|
|
6
|
+
## 0.5.4 — the Files-changed pane renders for a landed card
|
|
7
|
+
|
|
8
|
+
**0.5.3 is withdrawn in all but name.** It carries this release's source fix but
|
|
9
|
+
the PREVIOUS release's committed UI bundle, so a hosted page served by it still
|
|
10
|
+
asks for branch names and the pane stays empty. The cause is worth writing down:
|
|
11
|
+
the version bump, the changelog and the tag were made while the shell was still
|
|
12
|
+
inside a card's worktree after a conflict resolution, so `v0.5.3` points at that
|
|
13
|
+
card's branch — which holds `links.tsx::cardRange` but not the chapter-closing
|
|
14
|
+
rebuild of `src/taskops/ui/app.js`. Every gate passed there, because that tree
|
|
15
|
+
was internally consistent; what was missing was the rest of the chapter. A
|
|
16
|
+
release is cut from the trunk, and the check that catches this is comparing the
|
|
17
|
+
bundle a host SERVES against the one the tag committed — which is now a deploy
|
|
18
|
+
step, not a habit.
|
|
19
|
+
|
|
20
|
+
- **The pane asked for two branch names, and a landed card has neither.**
|
|
21
|
+
0.5.2 made the HEAD durable — the card's newest recorded sha instead of its
|
|
22
|
+
branch — and stopped there. The BASE stayed the chapter's branch name, and for
|
|
23
|
+
every card that landed before this host became the board's remote that branch
|
|
24
|
+
was pruned on the forge, so the compare refused and the pane was empty while
|
|
25
|
+
the commits sat in the trunk. Reported live on tk-bffa26 and tk-c37061.
|
|
26
|
+
- **The range now comes from the card's own commits, both ends**
|
|
27
|
+
(`ui/src/links.tsx::cardRange`): one recorded commit goes through the commit
|
|
28
|
+
door, which already diffs a commit against its first parent; several become
|
|
29
|
+
`compare/<oldest>^...<newest>`. The base is the oldest commit's PARENT, not
|
|
30
|
+
the oldest commit — `git diff` is exclusive of its base, so
|
|
31
|
+
`<oldest>...<newest>` answers 200 with that commit's own changes silently
|
|
32
|
+
missing, which is a pane that looks complete and is not. No server change was
|
|
33
|
+
needed: `<sha>^` already passed the ref shape and resolves through `^{commit}`.
|
|
34
|
+
- **Pinned where it broke.** The pane renders the route it asked for and a smoke
|
|
35
|
+
section reads that route off the rendered component — the previous attempt was
|
|
36
|
+
pinned one layer below the call site, so a call-site mutation went green while
|
|
37
|
+
the pane stayed broken. `smoke.sh` derives the same route from the LIVE card
|
|
38
|
+
payload and asserts the first commit's files are in the answer.
|
|
39
|
+
- **"so them was never pushed here"** — the host's missing-ref refusal had a
|
|
40
|
+
plural substitution in a subject slot. The number now runs through the whole
|
|
41
|
+
sentence, and both forms are pinned as bytes.
|
|
42
|
+
|
|
6
43
|
## 0.5.2 — the host holds the git; GitHub is the copy
|
|
7
44
|
|
|
8
45
|
0.5.0 and 0.5.1 built the hosted window on a mirror the host PULLED from the
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# (`tests/test_topology.py`), against a host it created.
|
|
16
16
|
#
|
|
17
17
|
# sh smoke.sh # the author's host, defaults below
|
|
18
|
-
# sh smoke.sh <host> <public-board> <private-board> <card-branch> <landed-
|
|
18
|
+
# sh smoke.sh <host> <public-board> <private-board> <card-branch> <landed-card> <reported-card>
|
|
19
19
|
#
|
|
20
20
|
# Every assertion is here because it FAILED once, in production, against a real
|
|
21
21
|
# reader — the comment above each one says which report it comes from. Nothing
|
|
@@ -37,6 +37,10 @@ BRANCH=${4:-tk-32d2ba}
|
|
|
37
37
|
# the fault that turned the pull mirror inside out (§16, 2026-08-31). The host
|
|
38
38
|
# holds the history now and never prunes, so this ref must answer forever.
|
|
39
39
|
LANDED=${5:-tk-dfaff7}
|
|
40
|
+
# The card the Files-changed pane was reported blank on (2026-08-31): two
|
|
41
|
+
# recorded commits, so it exercises the RANGE arm of the rule below, not the
|
|
42
|
+
# single-commit door.
|
|
43
|
+
REPORTED=${6:-tk-bffa26}
|
|
40
44
|
|
|
41
45
|
BASE="https://$HOST"
|
|
42
46
|
C="curl -sS -m 15"
|
|
@@ -228,18 +232,74 @@ code=$(printf %s "$got" | sed -n '1s/[^ ]* \([0-9][0-9]*\).*/\1/p')
|
|
|
228
232
|
"HTTP $code — a private board is not world-clonable"
|
|
229
233
|
pass "GET /$PRIVATE/repo.git upload-pack (anonymous)" "HTTP 401"
|
|
230
234
|
|
|
231
|
-
# ── (h)
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
#
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
# ── (h) the Files-changed pane's OWN range, for the two reported cards ───────
|
|
236
|
+
# This section REPLACES the one that asked `git/commit/<the landed card's branch
|
|
237
|
+
# name>` (written 2026-08-30 for the pull mirror). That assertion is not
|
|
238
|
+
# recoverable and must not come back: `tk-dfaff7`'s branch was pruned on the
|
|
239
|
+
# forge before this host became the board's remote, so the ref was never pushed
|
|
240
|
+
# here and the host — which prunes nothing — has nothing to serve under that
|
|
241
|
+
# name. Asking a landed card for its BRANCH was the fault itself, in the smoke
|
|
242
|
+
# as much as in the pane.
|
|
243
|
+
# Reported 2026-08-31 on tk-bffa26: the pane asked
|
|
244
|
+
# compare(base=ms/promotion-survives-its-own-confi, head=tk-bffa26) and the
|
|
245
|
+
# milestone branch does not exist on the host — pruned before the host became
|
|
246
|
+
# the remote — so a landed card showed nothing while its diff sat right there
|
|
247
|
+
# (proven on tk-dfaff7, whose recorded commit answers 45898 bytes through the
|
|
248
|
+
# commit door). This chapter moved the pane onto the card's OWN recorded
|
|
249
|
+
# commits, so the assertion has to ask what the pane asks and derive it the same
|
|
250
|
+
# way, or it would go green against a broken pane.
|
|
251
|
+
#
|
|
252
|
+
# `links.tsx::cardRange` is the rule, verbatim: no sha → nothing to assert; ONE
|
|
253
|
+
# recorded commit → `git/commit/<sha>`, which the door already diffs against its
|
|
254
|
+
# first parent; SEVERAL → `git/compare/<oldest>^...<newest>`, the base being the
|
|
255
|
+
# OLDEST commit's PARENT because git diff excludes its base. `gitRoute`
|
|
256
|
+
# percent-encodes each ref (`^` → %5E) and leaves `...` literal, since the
|
|
257
|
+
# separator is the route's grammar and not part of either ref.
|
|
258
|
+
#
|
|
259
|
+
# python3 reads the shas and nothing else does the arithmetic: the payload
|
|
260
|
+
# carries `sha` in more places than `commits` (the history and the merge record
|
|
261
|
+
# among them), so a grep over the whole body picks the wrong first and last ref
|
|
262
|
+
# and would pass on a range no pane ever asks for.
|
|
263
|
+
head_ln "the pane's own range, for both reported cards"
|
|
264
|
+
for card in "$LANDED" "$REPORTED"; do
|
|
265
|
+
payload=$($C -X POST "$BASE/$BOARD/api/rpc" -H 'Content-Type: application/json' \
|
|
266
|
+
-d "{\"verb\": \"card\", \"args\": {\"task\": \"$card\"}}") \
|
|
267
|
+
|| fail "POST card $card" "no answer"
|
|
268
|
+
# route on the first line, the first commit's own files on the rest — one read
|
|
269
|
+
# of the payload, and the same read the pane does.
|
|
270
|
+
asked=$(printf %s "$payload" | python3 -c '
|
|
271
|
+
import json, sys, urllib.parse
|
|
272
|
+
data = json.load(sys.stdin).get("data") or {}
|
|
273
|
+
shas = [c["sha"] for c in (data.get("commits") or []) if isinstance(c.get("sha"), str) and c["sha"]]
|
|
274
|
+
if not shas:
|
|
275
|
+
sys.exit("no recorded commit")
|
|
276
|
+
q = urllib.parse.quote
|
|
277
|
+
route = ("git/commit/" + q(shas[-1], safe="") if len(shas) == 1
|
|
278
|
+
else "git/compare/" + q(shas[0] + "^", safe="") + "..." + q(shas[-1], safe=""))
|
|
279
|
+
print(route)
|
|
280
|
+
for name in (data["commits"][0].get("files") or []):
|
|
281
|
+
print(name)
|
|
282
|
+
') || fail "card $card" "could not derive the pane's range"
|
|
283
|
+
route=$(printf %s "$asked" | sed -n 1p)
|
|
284
|
+
body=$($C "$BASE/$BOARD/api/$route") || fail "GET $route" "no answer ($card)"
|
|
285
|
+
case $body in
|
|
286
|
+
*'"patch": "diff'*|*'"patch":"diff'*)
|
|
287
|
+
pass "GET /$BOARD/api/$route" \
|
|
288
|
+
"$card renders ($(printf %s "$body" | wc -c | tr -d ' ') bytes)" ;;
|
|
289
|
+
*) fail "GET $route" "$card: no patch: $(printf %s "$body" | head -c 300)" ;;
|
|
290
|
+
esac
|
|
291
|
+
# THE dropped-base assertion: with the base at the newest commit (or at a
|
|
292
|
+
# branch tip) the answer is still a patch — it is just the wrong one. Only the
|
|
293
|
+
# FIRST commit's own files prove the range reaches back to where it started.
|
|
294
|
+
printf '%s\n' "$asked" | sed -n '2,$p' | while read -r name; do
|
|
295
|
+
[ -n "$name" ] || continue
|
|
296
|
+
case $body in
|
|
297
|
+
*"\"$name\""*) : ;;
|
|
298
|
+
*) fail "GET $route" "$card: $name — the first commit's file is missing from stat: the base was dropped" ;;
|
|
299
|
+
esac
|
|
300
|
+
done || exit 1
|
|
301
|
+
pass "the first commit's files are in stat" \
|
|
302
|
+
"$card: $(printf '%s\n' "$asked" | sed -n '2,$p' | wc -l | tr -d ' ') file(s) from $(printf %s "$asked" | sed -n 2p)"
|
|
303
|
+
done
|
|
244
304
|
|
|
245
305
|
printf '\nall green — %s, board %s\n' "$HOST" "$BOARD"
|
|
@@ -49,12 +49,12 @@ that reader and must not drift toward the host's."""
|
|
|
49
49
|
HOSTED = (
|
|
50
50
|
"{refs} not in this board's own repository on this host. Nothing was "
|
|
51
51
|
"pruned to make that true — this host keeps every branch pushed to it "
|
|
52
|
-
"forever — so {
|
|
53
|
-
"became the board's remote, or a worktree whose commits have not left it. "
|
|
52
|
+
"forever — so {subject} never pushed here: {cause}. "
|
|
54
53
|
"A commit reaches this repository the moment it is made in a worktree "
|
|
55
54
|
"joined to the board; the declared forge is a copy of what is here, never "
|
|
56
55
|
"the other way round, so there is nowhere else this pane could look."
|
|
57
56
|
)
|
|
57
|
+
|
|
58
58
|
"""The HOST's words — a reader with no clone, who can run nothing. No command
|
|
59
59
|
is named because there is none they could run, and no forge is named because
|
|
60
60
|
the forge is no longer a source: under the reversal it is a projection of this
|
|
@@ -62,6 +62,21 @@ repository, so "not here" is not "look over there". What replaced the mirror's
|
|
|
62
62
|
"a pruned branch is normal" is the stronger fact — this host prunes nothing —
|
|
63
63
|
and therefore a different diagnosis: the commits never arrived."""
|
|
64
64
|
|
|
65
|
+
SINGLE = (
|
|
66
|
+
"a card worked before this host became the board's remote, or a "
|
|
67
|
+
"worktree whose commits have not left it"
|
|
68
|
+
)
|
|
69
|
+
SEVERAL = (
|
|
70
|
+
"cards worked before this host became the board's remote, or "
|
|
71
|
+
"worktrees whose commits have not left them"
|
|
72
|
+
)
|
|
73
|
+
"""The DIAGNOSIS, in the number of the refs it explains. It is an apposition
|
|
74
|
+
to the missing refs themselves — "they were never pushed here: cards worked
|
|
75
|
+
before …" — so it declines with them, subject and possessive both: one ref
|
|
76
|
+
missing is one card or one worktree, several are cards or worktrees. 0.5.2
|
|
77
|
+
shipped "so them was never pushed here" with this clause frozen singular; a
|
|
78
|
+
sentence a reader is meant to trust cannot ask them to forgive its grammar."""
|
|
79
|
+
|
|
65
80
|
SHA = "0123456789abcdef"
|
|
66
81
|
|
|
67
82
|
|
|
@@ -82,7 +97,11 @@ def sentence(*refs: str, hosted: bool = False) -> str:
|
|
|
82
97
|
listed = f"{' and '.join(names)} {'are' if many else 'is'}"
|
|
83
98
|
them = "them" if many else "it"
|
|
84
99
|
if hosted:
|
|
85
|
-
return HOSTED.format(
|
|
100
|
+
return HOSTED.format(
|
|
101
|
+
refs=listed,
|
|
102
|
+
subject="they were" if many else "it was",
|
|
103
|
+
cause=SEVERAL if many else SINGLE,
|
|
104
|
+
)
|
|
86
105
|
branches = [ref for ref in names if not _looks_like_a_sha(ref)]
|
|
87
106
|
return STALE.format(
|
|
88
107
|
refs=listed,
|