claude-code-log 1.4.0__tar.gz → 1.6.0__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.
- claude_code_log-1.6.0/.claude/skills/foldyard/SKILL.md +84 -0
- claude_code_log-1.6.0/.claude/skills/foldyard/references/egress-and-capture.md +50 -0
- claude_code_log-1.6.0/.claude/skills/foldyard/references/posture-and-credentials.md +54 -0
- claude_code_log-1.6.0/.claude/skills/foldyard/references/when-a-change-doesnt-take.md +32 -0
- claude_code_log-1.6.0/.claude/skills/update-tools-coverage/SKILL.md +114 -0
- claude_code_log-1.6.0/.claude/skills/update-tools-coverage/check_codex_coverage.py +89 -0
- claude_code_log-1.6.0/.claude/skills/update-tools-coverage/check_coverage.py +119 -0
- claude_code_log-1.6.0/.editorconfig +25 -0
- claude_code_log-1.6.0/.github/workflows/ci.yml +117 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.gitignore +16 -1
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/CHANGELOG.md +101 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/CLAUDE.md +4 -1
- claude_code_log-1.6.0/CONTRIBUTING.md +505 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/PKG-INFO +11 -3
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/README.md +7 -0
- claude_code_log-1.6.0/claude_code_log/api.py +198 -0
- claude_code_log-1.6.0/claude_code_log/builtin_plugins/__init__.py +1 -0
- claude_code_log-1.6.0/claude_code_log/builtin_plugins/codex_docs.py +373 -0
- claude_code_log-1.6.0/claude_code_log/cache.py +2956 -0
- claude_code_log-1.6.0/claude_code_log/cli.py +2528 -0
- claude_code_log-1.6.0/claude_code_log/converter.py +6983 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/dag.py +178 -16
- claude_code_log-1.6.0/claude_code_log/discovery.py +72 -0
- claude_code_log-1.6.0/claude_code_log/entry_store.py +335 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/__init__.py +2 -0
- claude_code_log-1.6.0/claude_code_log/factories/attachment_factory.py +322 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/meta_factory.py +8 -1
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/system_factory.py +3 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/tool_factory.py +166 -9
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/user_factory.py +265 -18
- claude_code_log-1.6.0/claude_code_log/fragment_store.py +311 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/git_remote.py +27 -3
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/__init__.py +4 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/async_formatter.py +2 -2
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/renderer.py +444 -53
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/renderer_code.py +13 -1
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/system_formatters.py +18 -15
- claude_code_log-1.6.0/claude_code_log/html/templates/archive_search.html +735 -0
- claude_code_log-1.6.0/claude_code_log/html/templates/components/archive_search_link.html +18 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/global_styles.css +78 -9
- claude_code_log-1.6.0/claude_code_log/html/templates/components/live_update.js +566 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/message_styles.css +637 -11
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/pygments_styles.css +17 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/search.html +439 -136
- claude_code_log-1.6.0/claude_code_log/html/templates/components/search_inline.html +36 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/search_styles.css +43 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/session_nav.html +8 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/session_nav_styles.css +8 -3
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/timeline.html +109 -8
- claude_code_log-1.6.0/claude_code_log/html/templates/components/timezone_converter.js +148 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/index.html +8 -1
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/transcript.html +536 -321
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/tool_formatters.py +764 -52
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/user_formatters.py +172 -1
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/utils.py +305 -35
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/image_export.py +32 -8
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/json/renderer.py +13 -4
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/markdown/renderer.py +469 -44
- claude_code_log-1.6.0/claude_code_log/migrations/007_subagents_fingerprint.sql +16 -0
- claude_code_log-1.6.0/claude_code_log/migrations/008_session_sidecar.sql +53 -0
- claude_code_log-1.6.0/claude_code_log/migrations/009_sessions_hidden.sql +17 -0
- claude_code_log-1.6.0/claude_code_log/migrations/010_sessions_residual_count.sql +29 -0
- claude_code_log-1.6.0/claude_code_log/migrations/011_cached_file_size.sql +24 -0
- claude_code_log-1.6.0/claude_code_log/migrations/012_message_lookup_indexes.sql +81 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/models.py +347 -81
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/plugins.py +53 -10
- claude_code_log-1.6.0/claude_code_log/providers/__init__.py +11 -0
- claude_code_log-1.6.0/claude_code_log/providers/agy.py +381 -0
- claude_code_log-1.6.0/claude_code_log/providers/base.py +368 -0
- claude_code_log-1.6.0/claude_code_log/providers/claude.py +71 -0
- claude_code_log-1.6.0/claude_code_log/providers/codex.py +2869 -0
- claude_code_log-1.6.0/claude_code_log/providers/codex_messages.py +155 -0
- claude_code_log-1.6.0/claude_code_log/providers/codex_quickjs.py +780 -0
- claude_code_log-1.6.0/claude_code_log/providers/codex_tools.py +879 -0
- claude_code_log-1.6.0/claude_code_log/providers/codex_web.py +75 -0
- claude_code_log-1.6.0/claude_code_log/providers/registry.py +133 -0
- claude_code_log-1.6.0/claude_code_log/render_cache.py +203 -0
- claude_code_log-1.6.0/claude_code_log/render_dispatch.py +258 -0
- claude_code_log-1.6.0/claude_code_log/render_pool.py +720 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/renderer.py +1384 -339
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/renderer_timings.py +42 -5
- claude_code_log-1.6.0/claude_code_log/search.py +1081 -0
- claude_code_log-1.6.0/claude_code_log/server.py +304 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/tui.py +7 -7
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/utils.py +358 -43
- claude_code_log-1.6.0/claude_code_log/watch.py +239 -0
- claude_code_log-1.6.0/claude_code_log/workflow.py +661 -0
- claude_code_log-1.6.0/dev-docs/agents.md +369 -0
- claude_code_log-1.6.0/dev-docs/application_model.md +1495 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/css-classes.md +20 -1
- claude_code_log-1.6.0/dev-docs/dag.md +721 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/implementing-a-tool-renderer.md +24 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/message-hierarchy.md +40 -36
- claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_result.json +24 -0
- claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_result.jsonl +1 -0
- claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_use.json +27 -0
- claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_use.jsonl +1 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/README.md +82 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/collaboration/agent-tools.json +19 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/collaboration/thread-spawn.json +15 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/legacy/flat-rollout.md +6 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/lifecycle/turn-context.json +9 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/manifest.json +16 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/messages/environment-context.json +7 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/messages/user-shell-command.json +7 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/messages/visible-pair.json +17 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/reasoning/summary.json +9 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/session/session_meta.json +10 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/tools/async-command.json +41 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/tools/exec-wrapper.json +19 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/tools/function-call.json +19 -0
- claude_code_log-1.6.0/dev-docs/messages/codex/tools/web-run.json +19 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/messages.md +269 -55
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/plugins.md +131 -49
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/rendering-architecture.md +17 -8
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/teammates.md +13 -12
- claude_code_log-1.6.0/dev-docs/tools-coverage.md +344 -0
- claude_code_log-1.6.0/dev-docs/workflows.md +341 -0
- claude_code_log-1.6.0/foldyard.local.toml.example +86 -0
- claude_code_log-1.6.0/foldyard.toml +248 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/justfile +28 -22
- claude_code_log-1.6.0/mise.toml +8 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/mkdocs.yml +11 -1
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/pyproject.toml +49 -3
- claude_code_log-1.6.0/stubs/quickjs.pyi +13 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/uv.lock +67 -24
- claude_code_log-1.6.0/work/agent-hierarchies-design.md +229 -0
- claude_code_log-1.6.0/work/archive-search-server.md +1088 -0
- claude_code_log-1.6.0/work/codex-backlog.md +373 -0
- claude_code_log-1.6.0/work/identifier-consolidation.md +162 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/obsidian-friendly-output.md +25 -2
- claude_code_log-1.6.0/work/parse-memory-spike.md +140 -0
- claude_code_log-1.6.0/work/render-format-once.md +1472 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/rendering-next.md +43 -0
- claude_code_log-1.6.0/work/tui-output-fixes.md +75 -0
- claude_code_log-1.6.0/work/watch-mode.md +1695 -0
- claude_code_log-1.6.0/work/win-io.md +79 -0
- claude_code_log-1.6.0/work/xdist-import-cost.md +133 -0
- claude_code_log-1.4.0/.github/workflows/ci.yml +0 -87
- claude_code_log-1.4.0/CONTRIBUTING.md +0 -329
- claude_code_log-1.4.0/claude_code_log/cache.py +0 -1712
- claude_code_log-1.4.0/claude_code_log/cli.py +0 -1162
- claude_code_log-1.4.0/claude_code_log/converter.py +0 -2934
- claude_code_log-1.4.0/claude_code_log/factories/attachment_factory.py +0 -126
- claude_code_log-1.4.0/claude_code_log/html/templates/components/search_inline.html +0 -29
- claude_code_log-1.4.0/claude_code_log/html/templates/components/search_inline_script.html +0 -3
- claude_code_log-1.4.0/claude_code_log/html/templates/components/search_results_panel.html +0 -10
- claude_code_log-1.4.0/claude_code_log/html/templates/components/timezone_converter.js +0 -115
- claude_code_log-1.4.0/dev-docs/agents.md +0 -191
- claude_code_log-1.4.0/dev-docs/application_model.md +0 -458
- claude_code_log-1.4.0/dev-docs/dag.md +0 -701
- claude_code_log-1.4.0/mise.toml +0 -2
- claude_code_log-1.4.0/work/refactor-reindex-with-ghosting.md +0 -197
- claude_code_log-1.4.0/work/simplify-converter-renderer.md +0 -312
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.claude/settings.json +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.claude/skills/tool-renderer/SKILL.md +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.github/workflows/docs.yml +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.vscode/settings.json +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/LICENSE +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/__init__.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/agent_metadata_factory.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/assistant_factory.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/priorities.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/task_notification_factory.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/teammate_factory.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/transcript_factory.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/ansi_colors.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/assistant_formatters.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/teammate_formatter.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/edit_diff_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/filter_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/page_nav_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/project_card_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/teammate_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/timeline_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/todo_styles.css +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/json/__init__.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/markdown/__init__.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/markdown_plugins.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/001_initial_schema.sql +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/002_html_cache.sql +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/003_html_pagination.sql +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/004_html_pagination_variant.sql +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/005_session_team_name.sql +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/006_session_ai_title.sql +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/__init__.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/runner.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/parser.py +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/py.typed +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant_sidechain.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant_sidechain.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/thinking.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/thinking.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/file_history_snapshot.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/file_history_snapshot.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/queue_operation.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/queue_operation.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/summary.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/summary.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/system_info.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/system_info.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result_error.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result_error.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_result.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_result.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_use.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_use.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_input.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_input.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_output.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_output.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/command_output.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/command_output.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/image.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/image.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_command.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_command.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_sidechain.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_sidechain.jsonl +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_slash_command.json +0 -0
- {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_slash_command.jsonl +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/__init__.pyi +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/formatter.pyi +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/formatters/__init__.pyi +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/lexer.pyi +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/lexers/__init__.pyi +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/util.pyi +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/session-state-propagation.md +0 -0
- {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/tool-renderer-plugins.md +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: foldyard
|
|
3
|
+
description: Orient yourself in a foldyard dev box and drive it — the host/box split, what the box structurally cannot do, posture modes for credentials, egress and the proxy, worktrees, and why a config or compose change might not have taken effect. Use whenever `fy`/`foldyard` commands appear, when something needs a credential or network access it doesn't have, when a change "doesn't take", or when asked to work on the dev environment itself.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Working in (and on) a foldyard dev box
|
|
7
|
+
|
|
8
|
+
Foldyard runs this project inside a **rootless VM that mounts only this repo**. You are almost
|
|
9
|
+
certainly *in the box* — a container in that VM — and the person you're working with is on the
|
|
10
|
+
**host** (their Mac). That split explains nearly everything below.
|
|
11
|
+
|
|
12
|
+
Check where you are: `fy mode` prints the posture and says which side it's reading from.
|
|
13
|
+
`fy verify` proves the boundary (it exits non-zero if any of it is false).
|
|
14
|
+
|
|
15
|
+
## The four facts that will save you the most time
|
|
16
|
+
|
|
17
|
+
1. **You cannot push.** No credential to the git remote reaches the box, by design. Read and
|
|
18
|
+
commit locally; the human pushes. Don't try to work around it — there is nothing to find.
|
|
19
|
+
2. **You hold no real secrets, and can't grant yourself any.** Posture state lives in the host's
|
|
20
|
+
home, outside the mount. `fy mode` *shows* posture anywhere; *setting* it is host-only.
|
|
21
|
+
3. **Your egress goes through the host's proxy** and may be allow-listed or walled. A blocked
|
|
22
|
+
host is a decision, not a bug — ask; don't route around it.
|
|
23
|
+
4. **The engine socket you have is real** and bounded to this VM. `docker`/`podman` commands
|
|
24
|
+
work and act on the live dev stack — including anything a test suite's mocks let slip.
|
|
25
|
+
|
|
26
|
+
## Ask the tool, don't guess
|
|
27
|
+
|
|
28
|
+
Foldyard is introspectable, and its own output is always current — prefer it over any summary
|
|
29
|
+
(including this one):
|
|
30
|
+
|
|
31
|
+
| question | command |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| what can this environment do right now? | `fy mode` (posture), `fy state` (desired vs observed) |
|
|
34
|
+
| what's broken / missing? | `fy doctor` — one line per check, each with its fix |
|
|
35
|
+
| is the isolation intact? | `fy verify` |
|
|
36
|
+
| what does this verb do? | `fy --help`, `fy <verb> --help` |
|
|
37
|
+
| the manual, offline, by topic | `fy docs` — then `fy docs <topic>` |
|
|
38
|
+
| what does the config let the host do? | `fy config widenings` |
|
|
39
|
+
|
|
40
|
+
`fy docs` serves **this install's** documentation, so it can't drift from the code you're running.
|
|
41
|
+
Start with `fy docs quickstart`, `fy docs modes`, `fy docs networking`, `fy docs security`; the
|
|
42
|
+
ADRs (`fy docs adr-0001` …) carry the reasoning behind each design decision.
|
|
43
|
+
|
|
44
|
+
## Daily verbs
|
|
45
|
+
|
|
46
|
+
`fy up | ps | logs [svc] | shell | down` drive the compose stack; `fy box shell | ps` the dev box
|
|
47
|
+
itself; `fy verify` proves the cage. A consumer repo usually wraps these in its own `just`
|
|
48
|
+
recipes — check the repo's justfile and CLAUDE.md before reaching for `fy` directly.
|
|
49
|
+
|
|
50
|
+
## When you need something you don't have
|
|
51
|
+
|
|
52
|
+
**A credential** (a cloud token, an API key): you can't grant it. Name the exact command the human
|
|
53
|
+
should run on their Mac and why. Postures are per-axis — `fy mode` lists the axes this project
|
|
54
|
+
declares and their rungs, and high-privilege rungs expire on a timer by design. Detail:
|
|
55
|
+
[posture-and-credentials.md](references/posture-and-credentials.md).
|
|
56
|
+
|
|
57
|
+
**A host through the network wall**: `fy allow add <host> --level session` — **on the host**. Tell
|
|
58
|
+
them the hostname and what needs it. Detail:
|
|
59
|
+
[egress-and-capture.md](references/egress-and-capture.md).
|
|
60
|
+
|
|
61
|
+
**A tool in the box**: it belongs in the project's `foldyard.toml` (`[[box.tools]]`) so it survives
|
|
62
|
+
a box rebuild, not in an ad-hoc `apt install` that the next `fy box down` throws away. The
|
|
63
|
+
`bootstrap-devbox` skill covers growing that config from inside the box.
|
|
64
|
+
|
|
65
|
+
## "I changed it and nothing happened"
|
|
66
|
+
|
|
67
|
+
The most common class of confusion here. Full table:
|
|
68
|
+
[when-a-change-doesnt-take.md](references/when-a-change-doesnt-take.md). The three big ones:
|
|
69
|
+
|
|
70
|
+
- **`foldyard.toml`** — the host runs the copy it **adopted**, not your working tree. Your edit is
|
|
71
|
+
inert until the human answers the prompt at the next `fy up`/`fy host` (or runs `fy config
|
|
72
|
+
adopt`). Check with `fy config status`; see what changed with `fy config diff`.
|
|
73
|
+
- **Compose files** — read from the **primary checkout**, so an edit inside a worktree changes
|
|
74
|
+
nothing until it reaches that checkout.
|
|
75
|
+
- **A running container** — keeps the command and env it was created with. A config change needs a
|
|
76
|
+
recreate (`fy up`), not a restart.
|
|
77
|
+
|
|
78
|
+
## Working on foldyard itself
|
|
79
|
+
|
|
80
|
+
Read `fy docs` first — it's the installed version's own manual. The source lives at
|
|
81
|
+
<https://github.com/twistco/foldyard>. Don't clone it into the box to "check how it works": you'd
|
|
82
|
+
get a different version than the one running here, which is the exact confusion this design goes
|
|
83
|
+
out of its way to prevent. The supported way to develop against it is the **co-dev mount**
|
|
84
|
+
(`fy docs adr-0020`), which mounts the real checkout and installs it editable.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Egress, capture and the wall — why a request failed, and who can unblock it
|
|
2
|
+
|
|
3
|
+
All of the box's internet traffic routes through a proxy **on the host**. That's how credential
|
|
4
|
+
injection works, and it's the observation point for everything leaving the yard. Three separate
|
|
5
|
+
controls sit on that path; they get conflated constantly, so name the right one when you ask.
|
|
6
|
+
|
|
7
|
+
| control | question it answers | who changes it |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| **routing** | does traffic go through the proxy at all? | baked in at box creation (always on) |
|
|
10
|
+
| **the wall** | can traffic *ignore* the proxy and go direct? | project config, at VM provisioning |
|
|
11
|
+
| **the allowlist** | which hosts may the proxy reach? | `fy allow …` on the host, live |
|
|
12
|
+
| **capture** | is traffic decrypted and logged? | `fy mode capture=on` / `fy mode capture=off`, on the host, live |
|
|
13
|
+
|
|
14
|
+
## Diagnosing a failed request
|
|
15
|
+
|
|
16
|
+
- **`403` from the proxy / "blocked by the egress wall"** — the allowlist refused the host. It's a
|
|
17
|
+
decision. Ask the human for `fy allow add <host> --level session` (or `--level permanent` if it's
|
|
18
|
+
a permanent dependency of the project). Grants live in the host's home, outside the mount, so
|
|
19
|
+
there is deliberately no way to grant one from here. If the host is a real dependency of the
|
|
20
|
+
PROJECT (not just this task), also add it to `[proxy] recommend` in `foldyard.toml` with a
|
|
21
|
+
one-line `why`: that commits the recommendation for the whole team — each operator is OFFERED
|
|
22
|
+
it per host (after reviewing your edit at the adoption gate) instead of rediscovering the
|
|
23
|
+
block, and nothing is granted without their yes.
|
|
24
|
+
- **Connection refused / hangs on everything** — the host proxy probably isn't running. `fy doctor`
|
|
25
|
+
names it; the fix is `fy up` or `fy host` on the Mac.
|
|
26
|
+
- **TLS/certificate errors** — the proxy re-signs decrypted traffic with a CA the box trusts, so a
|
|
27
|
+
tool with its own hardcoded trust store (or one that pins) can fail here. Point it at the box's
|
|
28
|
+
combined CA bundle rather than disabling verification.
|
|
29
|
+
- **Works for a while, then dies ~60s in** — that's an idle-connection reset from the upstream,
|
|
30
|
+
not the proxy. Streaming or keepalives fix it; the proxy doesn't.
|
|
31
|
+
|
|
32
|
+
## Capture is not filtering
|
|
33
|
+
|
|
34
|
+
`capture=on` decrypts and logs requests so the human can *see* what the yard talks to. It doesn't
|
|
35
|
+
block anything, and hosts on the project's `passthrough` list are tunnelled without decryption —
|
|
36
|
+
often a couple of hundred of them, since one `@bundle` reference expands to a whole toolchain.
|
|
37
|
+
`fy config widenings` prints the real count.
|
|
38
|
+
|
|
39
|
+
Conversely the wall (`[machine] wall = true`) is the enforcing control: traffic that ignores the
|
|
40
|
+
proxy environment is *rejected*, not silently allowed. Without it, routing is cooperative — it
|
|
41
|
+
bounds what is **logged**, not what can leave. `fy verify` probes this directly.
|
|
42
|
+
|
|
43
|
+
## Don't route around it
|
|
44
|
+
|
|
45
|
+
Unsetting `HTTPS_PROXY`, adding `--insecure`, or hunting for a direct path defeats the observation
|
|
46
|
+
the human relies on — and under the wall it simply fails. If a task genuinely needs a host, say
|
|
47
|
+
which host and why; that's a one-command grant for them.
|
|
48
|
+
|
|
49
|
+
Depth: `fy docs networking`, `fy docs security`, `fy docs adr-0009` (why monitoring is called
|
|
50
|
+
monitoring and not filtering).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Posture and credentials — how the box gets access, and why you can't grant it
|
|
2
|
+
|
|
3
|
+
The yard's resting state is **zero secrets**: no key files, no token env vars, no credential
|
|
4
|
+
helpers. Nothing to lift, so nothing to leak. Access is a *posture* the human declares on the host,
|
|
5
|
+
and it reaches you as capability, never as a secret you hold.
|
|
6
|
+
|
|
7
|
+
## Axes and rungs
|
|
8
|
+
|
|
9
|
+
Posture is a set of independent **axes**, each at a **rung**. Which axes exist is per project —
|
|
10
|
+
`fy mode` prints them with a one-line blurb per rung; there is no fixed list to memorise. Typical
|
|
11
|
+
shapes: an off/on injector for one API, or a ladder like `off → logs → sa → user` where each rung
|
|
12
|
+
grants more.
|
|
13
|
+
|
|
14
|
+
- **Rung 0 is always the secretless one.** An axis at rest costs nothing and grants nothing.
|
|
15
|
+
- **High-privilege rungs are TTL-bound.** "Act as me" rungs expire (default an hour) and revert to
|
|
16
|
+
the default rung on their own. If something worked earlier and now 401s, check `fy mode` first —
|
|
17
|
+
a lapse looks exactly like a broken credential.
|
|
18
|
+
- `fy mode` also renders **DEGRADED**: the rung is set, but the host's capability probe says the
|
|
19
|
+
chain behind it isn't working right now (an expired grant, revoked access). That's the difference
|
|
20
|
+
between "not asked for" and "asked for, not currently working".
|
|
21
|
+
|
|
22
|
+
## How a credential reaches you (and doesn't)
|
|
23
|
+
|
|
24
|
+
The real token is minted **on the host** and injected into your request in flight by the egress
|
|
25
|
+
proxy. The box holds a dummy value at most. So:
|
|
26
|
+
|
|
27
|
+
- reading the env var gives you a placeholder — that's expected, not a misconfiguration;
|
|
28
|
+
- the access only exists while the axis is on, and only against the host it's scoped to;
|
|
29
|
+
- a fully compromised box can *use* the access during that window but can never *hold* it.
|
|
30
|
+
|
|
31
|
+
Some services in the stack instead get an identity from a local metadata emulator — same idea:
|
|
32
|
+
the container is handed short-lived capability, not a key.
|
|
33
|
+
|
|
34
|
+
## What to do when you need access
|
|
35
|
+
|
|
36
|
+
You cannot set posture from the box (`fy mode <axis>=<rung>` refuses here — the authoritative state
|
|
37
|
+
is in the host's home, outside the mount). So:
|
|
38
|
+
|
|
39
|
+
1. Run `fy mode` and read the axis blurbs; work out the exact rung you need.
|
|
40
|
+
2. Ask for it explicitly, with the reason and the command:
|
|
41
|
+
*"To read staging logs I need `fy mode gcp=logs` on your Mac (expires in an hour)."*
|
|
42
|
+
3. If a **secret** is missing rather than a posture — the host may need to capture it once
|
|
43
|
+
(`fy box up` prompts on a TTY, storing it host-side at 0600). `fy doctor` on the host names
|
|
44
|
+
which one.
|
|
45
|
+
|
|
46
|
+
## Reading the current grant surface
|
|
47
|
+
|
|
48
|
+
`fy config widenings` inventories what this project's config asks the host to allow: which hosts
|
|
49
|
+
are exempt from traffic capture, where each mechanism delivers a credential (armed *and* declared
|
|
50
|
+
but not yet armed), which agent prompts are shared with the team vs personal, and any config key
|
|
51
|
+
that reads as a control but is no longer honoured.
|
|
52
|
+
|
|
53
|
+
Depth: `fy docs modes`, `fy docs security`, `fy docs adr-0005` (why axes are data), `fy docs
|
|
54
|
+
adr-0007` (injection at the proxy), `fy docs adr-0008` (keyless agent auth).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# "I changed it and nothing happened"
|
|
2
|
+
|
|
3
|
+
Every entry below is a place where the thing you edited is **not** the thing that's running. They
|
|
4
|
+
share one root cause: state that the box can write is never authoritative for what the host does,
|
|
5
|
+
and containers freeze parts of their config at creation. Work down the table before assuming a bug.
|
|
6
|
+
|
|
7
|
+
| you edited | why it didn't take | what makes it take |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `foldyard.toml` / `foldyard.local.toml` | the host reconciles from the copy it **adopted**, outside the mount — your edit is inert by design | the human answers the adopt/revert/ignore prompt at the next `fy up`/`fy host`, or runs `fy config adopt`. `fy config status` / `fy config diff` show where you are |
|
|
10
|
+
| a block you deleted from `foldyard.toml` | `foldyard.local.toml` wins the merge and may still declare it (that file is gitignored, so it's invisible in `git status`) | `fy config widenings` names the file behind each one; a local `disabled = true` is how one person opts out of a block the team keeps |
|
|
11
|
+
| a compose file, inside a worktree | compose runs from the **primary checkout**, not your worktree | the edit has to reach the primary checkout |
|
|
12
|
+
| a compose file, anywhere | a running container keeps the command + env it was CREATED with | `fy up` (recreates on a config change) — a `restart` is not enough |
|
|
13
|
+
| an env var in the stack's env file | same: baked at container creation | recreate the service |
|
|
14
|
+
| posture (`fy mode …`) | setting is host-only; from the box it refuses | ask the human, then re-check `fy mode` |
|
|
15
|
+
| an egress allow / the wall | grants live in the host's home | `fy allow add <host>` on the host |
|
|
16
|
+
| a code file, expecting hot reload | the watcher may not see host-side writes across the VM's shared filesystem — but **edits made in the box do** propagate | make the edit in the box (you're already there); if a host-side edit was the trigger, touch the file from here |
|
|
17
|
+
| foldyard's own source (vendored consumers only) | a running supervisor holds the code it started with | the next host-side `fy up` bounces it and adopts the new code |
|
|
18
|
+
| a bundled skill / docs | they ship inside the installed package | reinstall foldyard, or run from the source checkout |
|
|
19
|
+
|
|
20
|
+
## Diagnosing, in order
|
|
21
|
+
|
|
22
|
+
1. `fy config status` — is the config the host runs the one you edited?
|
|
23
|
+
2. `fy state` — desired vs observed, per tier (files, daemons, capability, stack, box). It exits
|
|
24
|
+
non-zero on drift, so it's the fastest "is anything out of sync" check.
|
|
25
|
+
3. `fy doctor` — one line per check with its fix; the row that's warning usually is the answer.
|
|
26
|
+
4. `fy ps` / `fy logs <svc>` — is the container even the one you think? Check when it was created.
|
|
27
|
+
|
|
28
|
+
## The general rule
|
|
29
|
+
|
|
30
|
+
If a change would let the **box** widen what the **host** does — its credentials, its egress, its
|
|
31
|
+
capture — assume it needs a host-side act, and say which one. That's not an obstacle to route
|
|
32
|
+
around; it's the property that makes it safe to run an agent here with permissions skipped.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: update-tools-coverage
|
|
3
|
+
description: Refresh dev-docs/tools-coverage.md against the upstream Claude Code tools reference and the Codex app-server item schema. Use when checkpointing tool-renderer/provider coverage, after adding/removing a renderer or Codex adapter, or when either upstream taxonomy may have changed.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Update Tool Coverage
|
|
7
|
+
|
|
8
|
+
Keeps [`dev-docs/tools-coverage.md`](../../../dev-docs/tools-coverage.md) in
|
|
9
|
+
sync with the upstream contracts and our implementation:
|
|
10
|
+
|
|
11
|
+
1. **Upstream** — the documented tool list at
|
|
12
|
+
<https://code.claude.com/docs/en/tools-reference>.
|
|
13
|
+
2. **Us** — `TOOL_INPUT_MODELS` / `TOOL_OUTPUT_PARSERS` in
|
|
14
|
+
[`claude_code_log/factories/tool_factory.py`](../../../claude_code_log/factories/tool_factory.py).
|
|
15
|
+
3. **Codex** — the installed version's generated app-server `ThreadItem`
|
|
16
|
+
schema, plus the rollout adapters in `providers/codex.py`,
|
|
17
|
+
`providers/codex_tools.py`, and `providers/codex_javascript.py`.
|
|
18
|
+
|
|
19
|
+
The doc grades each documented tool **Full** (typed input + typed output),
|
|
20
|
+
**Input only** (typed input, generic output), or **Generic** (no registry
|
|
21
|
+
entry → params-table + raw-`<pre>` fallback), and separately lists tools we
|
|
22
|
+
support that upstream no longer documents (renames like `Task`→`Agent`,
|
|
23
|
+
supersessions like `MultiEdit`, legacy aliases, undocumented features).
|
|
24
|
+
|
|
25
|
+
## Claude Code procedure
|
|
26
|
+
|
|
27
|
+
1. **Fetch the upstream tool names.** WebFetch the reference and ask only
|
|
28
|
+
for the tool-table names (the page is ~80 KB; a targeted prompt keeps it
|
|
29
|
+
manageable):
|
|
30
|
+
|
|
31
|
+
> WebFetch `https://code.claude.com/docs/en/tools-reference` —
|
|
32
|
+
> "List the exact tool names in the main tools table, one per line.
|
|
33
|
+
> Names only, no descriptions."
|
|
34
|
+
|
|
35
|
+
Note any tool the page marks deprecated/renamed — that's a candidate for
|
|
36
|
+
the second table.
|
|
37
|
+
|
|
38
|
+
2. **Compute the truth mechanically.** Feed those names to the bundled
|
|
39
|
+
helper (run from the repo root; `uv run` is required so `pydantic`
|
|
40
|
+
resolves — bare `python3` fails with `ModuleNotFoundError: pydantic`):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
printf 'Agent Artifact AskUserQuestion ... Write' \
|
|
44
|
+
| uv run python .claude/skills/update-tools-coverage/check_coverage.py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
It prints each tool's support level, the totals, the "we register but
|
|
48
|
+
upstream doesn't document" set, and — if the doc exists — a **drift
|
|
49
|
+
report** (missing / mismatched / stale rows). If it says `in sync [OK]` and
|
|
50
|
+
the upstream name set is unchanged, there is nothing to do.
|
|
51
|
+
|
|
52
|
+
3. **Reconcile the doc.** Apply the helper's output to
|
|
53
|
+
`dev-docs/tools-coverage.md`:
|
|
54
|
+
- Move rows between the two tables as tools enter/leave the upstream list —
|
|
55
|
+
**never delete** a row for a tool we still register. A tool leaving the
|
|
56
|
+
reference moves to the "no longer documented" table (it's history a
|
|
57
|
+
transcript viewer must still render); it does not lose support.
|
|
58
|
+
- Fix any support-level the drift report flags.
|
|
59
|
+
- Update the **totals line** and the **snapshot date** in the intro
|
|
60
|
+
(`snapshot YYYY-MM-DD`).
|
|
61
|
+
- The **Notes column is hand-maintained** — carry notes forward; only the
|
|
62
|
+
support level is machine-derived.
|
|
63
|
+
|
|
64
|
+
4. **Re-run the helper** to confirm `in sync [OK]`.
|
|
65
|
+
|
|
66
|
+
## Codex procedure
|
|
67
|
+
|
|
68
|
+
Codex function/MCP/plugin names are open-ended, so do not try to create a
|
|
69
|
+
closed upstream function-name list. Check two separate tables instead:
|
|
70
|
+
|
|
71
|
+
1. Generate the public semantic item schema for the installed Codex version:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
codex --version
|
|
75
|
+
codex app-server generate-json-schema --out /tmp/codex-app-server-schema
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
2. Read `definitions.ThreadItem.oneOf` in
|
|
79
|
+
`/tmp/codex-app-server-schema/codex_app_server_protocol.v2.schemas.json`.
|
|
80
|
+
Reconcile added/removed variants with "Codex provider coverage / Public
|
|
81
|
+
item families" and update its version, date, and totals.
|
|
82
|
+
Run the local drift checker after editing:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
uv run python .claude/skills/update-tools-coverage/check_codex_coverage.py \
|
|
86
|
+
/tmp/codex-app-server-schema/codex_app_server_protocol.v2.schemas.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
3. Reconcile concrete call mappings with `_canonicalize()` in
|
|
90
|
+
`providers/codex_tools.py`, result/batch reconstruction in
|
|
91
|
+
`providers/codex.py`, and the `test/test_codex_*` contracts.
|
|
92
|
+
4. Reconcile the static-JavaScript list with the whitelisted transfer
|
|
93
|
+
functions in `providers/codex_javascript.py`. Never describe legacy-regex
|
|
94
|
+
support as production fallback: it is retained only as an explicit test
|
|
95
|
+
comparison baseline.
|
|
96
|
+
|
|
97
|
+
The generated schema is version-specific and the rollout format is not a
|
|
98
|
+
public wire contract. State both facts in the documentation snapshot.
|
|
99
|
+
|
|
100
|
+
## Guardrails
|
|
101
|
+
|
|
102
|
+
- **Generic is a feature, not a gap.** Unknown / `mcp__*` / plugin tools
|
|
103
|
+
*should* fall back to generic rendering. Only type a tool when it's common
|
|
104
|
+
or carries structure worth surfacing — see
|
|
105
|
+
[`implementing-a-tool-renderer.md`](../../../dev-docs/implementing-a-tool-renderer.md)
|
|
106
|
+
(or the `tool-renderer` skill) to actually add one.
|
|
107
|
+
- **Undocumented ≠ obsolete.** The reference table isn't a full census of
|
|
108
|
+
what lands in a JSONL file (e.g. `TeamCreate`/`TeamDelete` are typed both
|
|
109
|
+
sides but never appeared upstream). Keep those under "no longer /never
|
|
110
|
+
documented" with a note, not removed.
|
|
111
|
+
- **Dead models.** `GlobOutput` / `GrepOutput` exist in `models.py` but no
|
|
112
|
+
parser constructs them, so `Glob`/`Grep` are **Input only**. If a future
|
|
113
|
+
change wires up a parser, they graduate to Full automatically — the helper
|
|
114
|
+
will show the flip.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Check the documented Codex ThreadItem census against a generated schema."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import sys
|
|
9
|
+
from collections import Counter
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
DOC_PATH = Path(__file__).parents[3] / "dev-docs" / "tools-coverage.md"
|
|
14
|
+
SECTION_START = "### Public item families"
|
|
15
|
+
SECTION_END = "### Concrete Codex call adapters"
|
|
16
|
+
ROW_RE = re.compile(
|
|
17
|
+
r"^\| `(?P<name>[^`]+)` \| "
|
|
18
|
+
r"(?P<status>Direct|Adapted|Partial|Missing) \|",
|
|
19
|
+
re.MULTILINE,
|
|
20
|
+
)
|
|
21
|
+
TOTAL_RE = re.compile(
|
|
22
|
+
r"\*\*Totals:\*\* (?P<direct>\d+) direct · "
|
|
23
|
+
r"(?P<adapted>\d+) adapted · (?P<partial>\d+) partial · "
|
|
24
|
+
r"(?P<missing>\d+) missing\."
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def schema_items(path: Path) -> set[str]:
|
|
29
|
+
schema = json.loads(path.read_text(encoding="utf-8"))
|
|
30
|
+
variants = schema["definitions"]["ThreadItem"]["oneOf"]
|
|
31
|
+
return {variant["properties"]["type"]["enum"][0] for variant in variants}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def documented_items() -> tuple[dict[str, str], Counter[str], Counter[str]]:
|
|
35
|
+
document = DOC_PATH.read_text(encoding="utf-8")
|
|
36
|
+
section = document.split(SECTION_START, 1)[1].split(SECTION_END, 1)[0]
|
|
37
|
+
rows = ROW_RE.findall(section)
|
|
38
|
+
names = Counter(name for name, _ in rows)
|
|
39
|
+
statuses = Counter(status.lower() for _, status in rows)
|
|
40
|
+
return dict(rows), names, statuses
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main() -> int:
|
|
44
|
+
if len(sys.argv) != 2:
|
|
45
|
+
print(f"Usage: {Path(sys.argv[0]).name} SCHEMA.json", file=sys.stderr)
|
|
46
|
+
return 2
|
|
47
|
+
|
|
48
|
+
expected = schema_items(Path(sys.argv[1]))
|
|
49
|
+
documented, name_counts, statuses = documented_items()
|
|
50
|
+
actual = set(documented)
|
|
51
|
+
errors: list[str] = []
|
|
52
|
+
|
|
53
|
+
if duplicates := sorted(name for name, count in name_counts.items() if count > 1):
|
|
54
|
+
errors.append(f"duplicate documented items: {', '.join(duplicates)}")
|
|
55
|
+
if missing := sorted(expected - actual):
|
|
56
|
+
errors.append(f"schema items missing from documentation: {', '.join(missing)}")
|
|
57
|
+
if stale := sorted(actual - expected):
|
|
58
|
+
errors.append(f"documented items absent from schema: {', '.join(stale)}")
|
|
59
|
+
|
|
60
|
+
document = DOC_PATH.read_text(encoding="utf-8")
|
|
61
|
+
total_match = TOTAL_RE.search(document)
|
|
62
|
+
if not total_match:
|
|
63
|
+
errors.append("Codex totals line is missing or malformed")
|
|
64
|
+
else:
|
|
65
|
+
totals = {name: int(value) for name, value in total_match.groupdict().items()}
|
|
66
|
+
if totals != statuses:
|
|
67
|
+
errors.append(
|
|
68
|
+
f"documented totals {totals} do not match table {dict(statuses)}"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
if errors:
|
|
72
|
+
for error in errors:
|
|
73
|
+
print(f"[FAIL] {error}")
|
|
74
|
+
return 1
|
|
75
|
+
|
|
76
|
+
print(f"Codex ThreadItem census: {len(actual)} variants")
|
|
77
|
+
print(
|
|
78
|
+
"Coverage: "
|
|
79
|
+
+ " / ".join(
|
|
80
|
+
f"{status.title()} {statuses[status]}"
|
|
81
|
+
for status in ("direct", "adapted", "partial", "missing")
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
print("Generated schema and documentation are in sync [OK]")
|
|
85
|
+
return 0
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Compute tool-coverage status from the live factory registries.
|
|
3
|
+
|
|
4
|
+
Run from the repo root via ``uv run`` (needs pydantic on the path):
|
|
5
|
+
|
|
6
|
+
# Feed the upstream documented tool names (whitespace/newline separated)
|
|
7
|
+
printf 'Agent Artifact ... Write' | uv run python .claude/skills/update-tools-coverage/check_coverage.py
|
|
8
|
+
|
|
9
|
+
Emits, for the given upstream tool set:
|
|
10
|
+
* per-tool support level (Full / Input only / Generic),
|
|
11
|
+
* totals,
|
|
12
|
+
* tools we register that upstream does NOT list (obsolete / undocumented),
|
|
13
|
+
* drift vs. the committed dev-docs/tools-coverage.md table, if present.
|
|
14
|
+
|
|
15
|
+
The classification here is the *source of truth*; the doc's Notes column is
|
|
16
|
+
hand-maintained, so reconcile prose by hand after reading this output.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
from collections import Counter
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
from claude_code_log.factories.tool_factory import (
|
|
27
|
+
TOOL_INPUT_MODELS,
|
|
28
|
+
TOOL_OUTPUT_PARSERS,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
DOC = Path("dev-docs/tools-coverage.md")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def support(tool: str) -> str:
|
|
35
|
+
has_in = tool in TOOL_INPUT_MODELS
|
|
36
|
+
has_out = tool in TOOL_OUTPUT_PARSERS
|
|
37
|
+
if has_in and has_out:
|
|
38
|
+
return "Full"
|
|
39
|
+
if has_in:
|
|
40
|
+
return "Input only"
|
|
41
|
+
return "Generic"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def read_upstream() -> list[str]:
|
|
45
|
+
raw = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else sys.stdin.read()
|
|
46
|
+
tools = raw.split()
|
|
47
|
+
if not tools:
|
|
48
|
+
sys.exit(
|
|
49
|
+
"No upstream tool names given.\n"
|
|
50
|
+
"Pass them as args or on stdin (whitespace/newline separated).\n"
|
|
51
|
+
"Get them by fetching https://code.claude.com/docs/en/tools-reference"
|
|
52
|
+
)
|
|
53
|
+
# de-dupe, preserve order
|
|
54
|
+
seen: dict[str, None] = {}
|
|
55
|
+
for t in tools:
|
|
56
|
+
seen.setdefault(t, None)
|
|
57
|
+
return list(seen)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main() -> None:
|
|
61
|
+
upstream = read_upstream()
|
|
62
|
+
print(f"UPSTREAM documented tools: {len(upstream)}\n")
|
|
63
|
+
|
|
64
|
+
print("=== Support level (source of truth) ===")
|
|
65
|
+
width = max(len(t) for t in upstream)
|
|
66
|
+
for t in sorted(upstream):
|
|
67
|
+
print(f" {t:<{width}} {support(t)}")
|
|
68
|
+
|
|
69
|
+
counts = Counter(support(t) for t in upstream)
|
|
70
|
+
print(
|
|
71
|
+
f"\n=== Totals === "
|
|
72
|
+
f"Full: {counts['Full']} "
|
|
73
|
+
f"Input only: {counts['Input only']} "
|
|
74
|
+
f"Generic: {counts['Generic']}"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
registered = set(TOOL_INPUT_MODELS) | set(TOOL_OUTPUT_PARSERS)
|
|
78
|
+
extra = sorted(registered - set(upstream))
|
|
79
|
+
print("\n=== We register but upstream does NOT document ===")
|
|
80
|
+
print("(obsolete renames/supersessions, legacy aliases, or undocumented features)")
|
|
81
|
+
for t in extra:
|
|
82
|
+
sides = []
|
|
83
|
+
if t in TOOL_INPUT_MODELS:
|
|
84
|
+
sides.append("input")
|
|
85
|
+
if t in TOOL_OUTPUT_PARSERS:
|
|
86
|
+
sides.append("output")
|
|
87
|
+
print(f" {t:<20} typed: {', '.join(sides)}")
|
|
88
|
+
|
|
89
|
+
# --- Drift check against the committed doc, if present ------------------
|
|
90
|
+
if not DOC.exists():
|
|
91
|
+
print(f"\n(no {DOC} yet — nothing to diff)")
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
doc_rows = dict(
|
|
95
|
+
re.findall(
|
|
96
|
+
r"^\| `(\w+)` \| (Full|Input only|Generic) \|",
|
|
97
|
+
DOC.read_text(encoding="utf-8"),
|
|
98
|
+
re.M,
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
print(f"\n=== Drift vs {DOC} ===")
|
|
102
|
+
problems = False
|
|
103
|
+
for t in upstream:
|
|
104
|
+
want, have = support(t), doc_rows.get(t)
|
|
105
|
+
if have is None:
|
|
106
|
+
print(f" MISSING from doc: {t} (should be {want})")
|
|
107
|
+
problems = True
|
|
108
|
+
elif have != want:
|
|
109
|
+
print(f" MISMATCH: {t} — doc says {have!r}, code says {want!r}")
|
|
110
|
+
problems = True
|
|
111
|
+
for t in doc_rows.keys() - set(upstream):
|
|
112
|
+
print(f" STALE in doc (not in upstream list): {t}")
|
|
113
|
+
problems = True
|
|
114
|
+
if not problems:
|
|
115
|
+
print(" in sync [OK]")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
main()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# EditorConfig — https://editorconfig.org
|
|
2
|
+
# Baseline whitespace hygiene, observed by most editors/IDEs. See the
|
|
3
|
+
# "Code Quality" section of CONTRIBUTING.md.
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
[*]
|
|
7
|
+
charset = utf-8
|
|
8
|
+
end_of_line = lf
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
trim_trailing_whitespace = true
|
|
11
|
+
|
|
12
|
+
# Markdown: a line ending in two spaces is a hard line break — trimming it
|
|
13
|
+
# would silently rewrite content, so leave trailing whitespace alone here.
|
|
14
|
+
[*.md]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
16
|
+
|
|
17
|
+
# Syrupy snapshots: the serializer indents *every* line of the embedded block,
|
|
18
|
+
# including blank ones, so blank lines legitimately carry trailing whitespace.
|
|
19
|
+
# Never trim — regenerate with `pytest --snapshot-update -n0` instead.
|
|
20
|
+
[*.ambr]
|
|
21
|
+
trim_trailing_whitespace = false
|
|
22
|
+
|
|
23
|
+
[*.py]
|
|
24
|
+
indent_style = space
|
|
25
|
+
indent_size = 4
|