@proflandrigan/shards 1.1.0
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.
- package/README.md +475 -0
- package/package.json +37 -0
- package/src/agents/academic.md +276 -0
- package/src/agents/ai-engineer.md +377 -0
- package/src/agents/analytics-engineer.md +364 -0
- package/src/agents/applied-ml-scientist.md +410 -0
- package/src/agents/backend-engineer.md +255 -0
- package/src/agents/bi-engineer.md +333 -0
- package/src/agents/data-analyst.md +343 -0
- package/src/agents/data-engineer.md +260 -0
- package/src/agents/data-modeller.md +386 -0
- package/src/agents/data-scientist.md +366 -0
- package/src/agents/deep-learning-engineer.md +389 -0
- package/src/agents/ml-engineer.md +424 -0
- package/src/agents/mlops-engineer.md +339 -0
- package/src/agents/researcher.md +187 -0
- package/src/agents/specific_instructions/academic/critical_review.md +263 -0
- package/src/agents/specific_instructions/academic/report.md +113 -0
- package/src/agents/specific_instructions/ai_engineer/advise.md +162 -0
- package/src/agents/specific_instructions/ai_engineer/bi_engineer_handoff.md +86 -0
- package/src/agents/specific_instructions/ai_engineer/experiment.md +471 -0
- package/src/agents/specific_instructions/ai_engineer/experiment_ui_mode.md +44 -0
- package/src/agents/specific_instructions/ai_engineer/phases/index.md +45 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-1.md +55 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-2.md +86 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-3.md +96 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-4.md +138 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-5.md +157 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-6.md +196 -0
- package/src/agents/specific_instructions/ai_engineer/phases/phase-7.md +313 -0
- package/src/agents/specific_instructions/ai_engineer/phases.md +1011 -0
- package/src/agents/specific_instructions/ai_engineer/prompt_lab.md +161 -0
- package/src/agents/specific_instructions/ai_engineer/prompt_lab_ui_mode.md +28 -0
- package/src/agents/specific_instructions/ai_engineer/research.md +393 -0
- package/src/agents/specific_instructions/ai_engineer/research_ui_mode.md +66 -0
- package/src/agents/specific_instructions/ai_engineer/review.md +159 -0
- package/src/agents/specific_instructions/ai_engineer/validation_checklist.md +182 -0
- package/src/agents/specific_instructions/analytics_engineer/advise.md +155 -0
- package/src/agents/specific_instructions/analytics_engineer/bi_engineer_handoff.md +91 -0
- package/src/agents/specific_instructions/analytics_engineer/data_analyst_handoff.md +84 -0
- package/src/agents/specific_instructions/analytics_engineer/deep_phases.md +818 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/index.md +24 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-1.md +77 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-2.md +106 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-3.md +93 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-4.md +79 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-5.md +61 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-6.md +45 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-7.md +235 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-8.md +221 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_quick/index.md +19 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_quick/phase-1.md +47 -0
- package/src/agents/specific_instructions/analytics_engineer/phases_quick/phase-2.md +78 -0
- package/src/agents/specific_instructions/analytics_engineer/quick_phases.md +112 -0
- package/src/agents/specific_instructions/analytics_engineer/review.md +167 -0
- package/src/agents/specific_instructions/analytics_engineer/service_mode.md +369 -0
- package/src/agents/specific_instructions/analytics_engineer/ui_mode.md +45 -0
- package/src/agents/specific_instructions/analytics_engineer/update.md +162 -0
- package/src/agents/specific_instructions/analytics_engineer/validation_checklist.md +121 -0
- package/src/agents/specific_instructions/applied_ml_scientist/advise.md +143 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases/index.md +21 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-1.md +51 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-2.md +66 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-3.md +113 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-4.md +104 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-5.md +156 -0
- package/src/agents/specific_instructions/applied_ml_scientist/phases.md +428 -0
- package/src/agents/specific_instructions/applied_ml_scientist/research.md +379 -0
- package/src/agents/specific_instructions/applied_ml_scientist/review.md +142 -0
- package/src/agents/specific_instructions/applied_ml_scientist/validation_checklist.md +136 -0
- package/src/agents/specific_instructions/backend_engineer/clean.md +149 -0
- package/src/agents/specific_instructions/backend_engineer/review.md +91 -0
- package/src/agents/specific_instructions/backend_engineer/review_checklist.md +54 -0
- package/src/agents/specific_instructions/backend_engineer/service_mode.md +67 -0
- package/src/agents/specific_instructions/bi_engineer/advise.md +137 -0
- package/src/agents/specific_instructions/bi_engineer/data_analyst_handoff.md +77 -0
- package/src/agents/specific_instructions/bi_engineer/incoming_handoff.md +45 -0
- package/src/agents/specific_instructions/bi_engineer/phases/index.md +20 -0
- package/src/agents/specific_instructions/bi_engineer/phases/phase-1.md +164 -0
- package/src/agents/specific_instructions/bi_engineer/phases/phase-2.md +92 -0
- package/src/agents/specific_instructions/bi_engineer/phases/phase-3.md +121 -0
- package/src/agents/specific_instructions/bi_engineer/phases/phase-4.md +106 -0
- package/src/agents/specific_instructions/bi_engineer/phases.md +451 -0
- package/src/agents/specific_instructions/bi_engineer/review.md +166 -0
- package/src/agents/specific_instructions/bi_engineer/update.md +147 -0
- package/src/agents/specific_instructions/bi_engineer/validation_checklist.md +124 -0
- package/src/agents/specific_instructions/data_analyst/advise.md +138 -0
- package/src/agents/specific_instructions/data_analyst/explain.md +221 -0
- package/src/agents/specific_instructions/data_analyst/incoming_handoff.md +40 -0
- package/src/agents/specific_instructions/data_analyst/phases/index.md +20 -0
- package/src/agents/specific_instructions/data_analyst/phases/phase-1.md +159 -0
- package/src/agents/specific_instructions/data_analyst/phases/phase-2.md +112 -0
- package/src/agents/specific_instructions/data_analyst/phases/phase-3.md +265 -0
- package/src/agents/specific_instructions/data_analyst/phases/phase-4.md +100 -0
- package/src/agents/specific_instructions/data_analyst/phases.md +501 -0
- package/src/agents/specific_instructions/data_analyst/review.md +138 -0
- package/src/agents/specific_instructions/data_analyst/ui_mode.md +26 -0
- package/src/agents/specific_instructions/data_analyst/update.md +144 -0
- package/src/agents/specific_instructions/data_analyst/validation_checklist.md +95 -0
- package/src/agents/specific_instructions/data_engineer/advise.md +137 -0
- package/src/agents/specific_instructions/data_engineer/phases.md +466 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/index.md +23 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-1.md +49 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-2.md +93 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-3.md +55 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-4.md +48 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-5.md +40 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-6.md +102 -0
- package/src/agents/specific_instructions/data_engineer/phases_deep/phase-7.md +87 -0
- package/src/agents/specific_instructions/data_engineer/phases_quick/index.md +19 -0
- package/src/agents/specific_instructions/data_engineer/phases_quick/phase-1.md +45 -0
- package/src/agents/specific_instructions/data_engineer/phases_quick/phase-2.md +54 -0
- package/src/agents/specific_instructions/data_engineer/review.md +135 -0
- package/src/agents/specific_instructions/data_engineer/validation_checklist.md +136 -0
- package/src/agents/specific_instructions/data_modeller/advise.md +137 -0
- package/src/agents/specific_instructions/data_modeller/phases.md +581 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/index.md +23 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-1.md +52 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-2.md +113 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-3.md +47 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-4.md +51 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-5.md +45 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-6.md +105 -0
- package/src/agents/specific_instructions/data_modeller/phases_deep/phase-7.md +136 -0
- package/src/agents/specific_instructions/data_modeller/phases_quick/index.md +19 -0
- package/src/agents/specific_instructions/data_modeller/phases_quick/phase-1.md +47 -0
- package/src/agents/specific_instructions/data_modeller/phases_quick/phase-2.md +65 -0
- package/src/agents/specific_instructions/data_modeller/review.md +141 -0
- package/src/agents/specific_instructions/data_modeller/service_mode.md +218 -0
- package/src/agents/specific_instructions/data_modeller/validation_checklist.md +125 -0
- package/src/agents/specific_instructions/data_scientist/advise.md +158 -0
- package/src/agents/specific_instructions/data_scientist/bi_engineer_handoff.md +63 -0
- package/src/agents/specific_instructions/data_scientist/experiment.md +482 -0
- package/src/agents/specific_instructions/data_scientist/experiment_ui_mode.md +44 -0
- package/src/agents/specific_instructions/data_scientist/explain.md +247 -0
- package/src/agents/specific_instructions/data_scientist/greenfield_data.md +35 -0
- package/src/agents/specific_instructions/data_scientist/ml_engineer_handoff.md +52 -0
- package/src/agents/specific_instructions/data_scientist/notebook_walkthrough.md +76 -0
- package/src/agents/specific_instructions/data_scientist/phases/index.md +24 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-1.md +45 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-2.md +67 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-3.md +89 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-4.md +143 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-5.md +71 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-6.md +239 -0
- package/src/agents/specific_instructions/data_scientist/phases/phase-7.md +207 -0
- package/src/agents/specific_instructions/data_scientist/phases.md +651 -0
- package/src/agents/specific_instructions/data_scientist/research.md +345 -0
- package/src/agents/specific_instructions/data_scientist/research_ui_mode.md +52 -0
- package/src/agents/specific_instructions/data_scientist/review.md +136 -0
- package/src/agents/specific_instructions/data_scientist/service_mode.md +247 -0
- package/src/agents/specific_instructions/data_scientist/validation_checklist.md +183 -0
- package/src/agents/specific_instructions/deep_learning_engineer/advise.md +145 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases/index.md +21 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-1.md +74 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-2.md +98 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-3.md +76 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-4.md +128 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-5.md +292 -0
- package/src/agents/specific_instructions/deep_learning_engineer/phases.md +567 -0
- package/src/agents/specific_instructions/deep_learning_engineer/research.md +389 -0
- package/src/agents/specific_instructions/deep_learning_engineer/review.md +155 -0
- package/src/agents/specific_instructions/deep_learning_engineer/validation_checklist.md +147 -0
- package/src/agents/specific_instructions/ml_engineer/advise.md +174 -0
- package/src/agents/specific_instructions/ml_engineer/bi_engineer_handoff.md +71 -0
- package/src/agents/specific_instructions/ml_engineer/experiment.md +474 -0
- package/src/agents/specific_instructions/ml_engineer/experiment_ui_mode.md +44 -0
- package/src/agents/specific_instructions/ml_engineer/notebook_walkthrough.md +75 -0
- package/src/agents/specific_instructions/ml_engineer/phases/index.md +25 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-1.md +49 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-2.md +75 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-3.md +124 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-4.md +279 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-5.md +160 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-6-5.md +170 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-6.md +295 -0
- package/src/agents/specific_instructions/ml_engineer/phases/phase-7.md +337 -0
- package/src/agents/specific_instructions/ml_engineer/phases.md +1068 -0
- package/src/agents/specific_instructions/ml_engineer/research.md +437 -0
- package/src/agents/specific_instructions/ml_engineer/research_ui_mode.md +71 -0
- package/src/agents/specific_instructions/ml_engineer/review.md +187 -0
- package/src/agents/specific_instructions/ml_engineer/service_mode.md +273 -0
- package/src/agents/specific_instructions/ml_engineer/validation_checklist.md +185 -0
- package/src/agents/specific_instructions/mlops_engineer/advise.md +139 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/index.md +23 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-1.md +52 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-2.md +86 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-3.md +105 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-4.md +128 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-5.md +106 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-6.md +128 -0
- package/src/agents/specific_instructions/mlops_engineer/phases/phase-7.md +144 -0
- package/src/agents/specific_instructions/mlops_engineer/phases.md +671 -0
- package/src/agents/specific_instructions/mlops_engineer/review.md +164 -0
- package/src/agents/specific_instructions/mlops_engineer/service_mode.md +81 -0
- package/src/agents/specific_instructions/mlops_engineer/validation_checklist.md +151 -0
- package/src/agents/specific_instructions/researcher/critical_review.md +292 -0
- package/src/agents/specific_instructions/researcher/review_checklist.md +67 -0
- package/src/agents/specific_instructions/researcher/service_mode.md +224 -0
- package/src/agents/specific_instructions/shared/auto_verify_mode.md +141 -0
- package/src/agents/specific_instructions/shared/autonomous_research.md +1289 -0
- package/src/agents/specific_instructions/shared/behavioral_rules.md +36 -0
- package/src/agents/specific_instructions/shared/diverge_protocol.md +387 -0
- package/src/agents/specific_instructions/shared/engineering_guidelines.md +136 -0
- package/src/agents/specific_instructions/shared/experiment_versioning.md +184 -0
- package/src/agents/specific_instructions/shared/goal_mode.md +187 -0
- package/src/agents/specific_instructions/shared/incremental_testing.md +139 -0
- package/src/agents/specific_instructions/shared/intent_discovery.md +223 -0
- package/src/agents/specific_instructions/shared/join_path_protocol.md +168 -0
- package/src/agents/specific_instructions/shared/knowledge_checkpoint.md +83 -0
- package/src/agents/specific_instructions/shared/knowledge_harvest.md +220 -0
- package/src/agents/specific_instructions/shared/knowledge_retrieval.md +100 -0
- package/src/agents/specific_instructions/shared/notebook_walkthrough_protocol.md +367 -0
- package/src/agents/specific_instructions/shared/reviewer_verdict_protocol.md +74 -0
- package/src/agents/specific_instructions/shared/swarm_protocol.md +97 -0
- package/src/agents/specific_instructions/shared/validation_protocol.md +139 -0
- package/src/agents/specific_instructions/syn/arbiter.md +140 -0
- package/src/agents/specific_instructions/syn/brainstorm.md +550 -0
- package/src/agents/specific_instructions/syn/code_review.md +232 -0
- package/src/agents/specific_instructions/syn/diff.md +239 -0
- package/src/agents/specific_instructions/syn/final_review.md +65 -0
- package/src/agents/specific_instructions/syn/fixer.md +240 -0
- package/src/agents/specific_instructions/syn/free_form.md +130 -0
- package/src/agents/specific_instructions/syn/knowledge.md +468 -0
- package/src/agents/specific_instructions/syn/notebook_walkthrough.md +78 -0
- package/src/agents/specific_instructions/syn/panel_review.md +634 -0
- package/src/agents/specific_instructions/syn/pm.md +453 -0
- package/src/agents/specific_instructions/syn/pr_review.md +255 -0
- package/src/agents/specific_instructions/syn/slides.md +417 -0
- package/src/agents/syn.md +729 -0
- package/src/commands/academic.md +41 -0
- package/src/commands/ai-engineer.md +45 -0
- package/src/commands/analytics-engineer.md +48 -0
- package/src/commands/applied-ml-scientist.md +45 -0
- package/src/commands/backend-engineer.md +35 -0
- package/src/commands/bi-engineer.md +40 -0
- package/src/commands/brainstorm.md +24 -0
- package/src/commands/data-analyst.md +38 -0
- package/src/commands/data-engineer.md +37 -0
- package/src/commands/data-modeller.md +38 -0
- package/src/commands/data-scientist.md +38 -0
- package/src/commands/deep-learning-engineer.md +47 -0
- package/src/commands/end.md +49 -0
- package/src/commands/knowledge.md +24 -0
- package/src/commands/ml-engineer.md +42 -0
- package/src/commands/mlops-engineer.md +47 -0
- package/src/commands/notebook-walkthrough.md +58 -0
- package/src/commands/researcher.md +40 -0
- package/src/commands/resume.md +57 -0
- package/src/commands/review-pr.md +26 -0
- package/src/commands/shards-guide.md +41 -0
- package/src/commands/shards-ui.md +32 -0
- package/src/commands/shards.md +41 -0
- package/src/docs/01-getting-started/concepts.md +109 -0
- package/src/docs/01-getting-started/first-session.md +79 -0
- package/src/docs/01-getting-started/install.md +61 -0
- package/src/docs/02-agents/academic.md +71 -0
- package/src/docs/02-agents/ai-engineer.md +78 -0
- package/src/docs/02-agents/analytics-engineer.md +58 -0
- package/src/docs/02-agents/applied-ml-scientist.md +59 -0
- package/src/docs/02-agents/backend-engineer.md +58 -0
- package/src/docs/02-agents/bi-engineer.md +65 -0
- package/src/docs/02-agents/data-analyst.md +67 -0
- package/src/docs/02-agents/data-engineer.md +57 -0
- package/src/docs/02-agents/data-modeller.md +51 -0
- package/src/docs/02-agents/data-scientist.md +78 -0
- package/src/docs/02-agents/deep-learning-engineer.md +64 -0
- package/src/docs/02-agents/ml-engineer.md +80 -0
- package/src/docs/02-agents/mlops-engineer.md +59 -0
- package/src/docs/02-agents/overview.md +62 -0
- package/src/docs/02-agents/researcher.md +73 -0
- package/src/docs/02-agents/syn.md +88 -0
- package/src/docs/03-protocols/auto-verify.md +82 -0
- package/src/docs/03-protocols/autonomous-research.md +59 -0
- package/src/docs/03-protocols/behavioral-rules.md +35 -0
- package/src/docs/03-protocols/diverge.md +50 -0
- package/src/docs/03-protocols/engineering-guidelines.md +56 -0
- package/src/docs/03-protocols/experiment-versioning.md +38 -0
- package/src/docs/03-protocols/gate-pattern.md +65 -0
- package/src/docs/03-protocols/incremental-testing.md +68 -0
- package/src/docs/03-protocols/join-path.md +46 -0
- package/src/docs/03-protocols/knowledge-ledger.md +70 -0
- package/src/docs/03-protocols/reviewer-verdicts.md +39 -0
- package/src/docs/03-protocols/swarm.md +40 -0
- package/src/docs/03-protocols/validation.md +174 -0
- package/src/docs/04-ui/activity-bar.md +70 -0
- package/src/docs/04-ui/chat-pane.md +80 -0
- package/src/docs/04-ui/code-intel.md +62 -0
- package/src/docs/04-ui/file-editing.md +61 -0
- package/src/docs/04-ui/git.md +54 -0
- package/src/docs/04-ui/keybindings.md +79 -0
- package/src/docs/04-ui/knowledge-map.md +76 -0
- package/src/docs/04-ui/overview.md +93 -0
- package/src/docs/04-ui/panels.md +49 -0
- package/src/docs/04-ui/pinboard-selection.md +66 -0
- package/src/docs/04-ui/quick-open-palette.md +56 -0
- package/src/docs/04-ui/sessions.md +81 -0
- package/src/docs/04-ui/settings-permissions.md +56 -0
- package/src/docs/05-commands/reference.md +59 -0
- package/src/docs/06-outputs/directory-map.md +116 -0
- package/src/docs/07-workflows/ai-eval-first.md +57 -0
- package/src/docs/07-workflows/deep-study-to-production.md +76 -0
- package/src/docs/07-workflows/diverge-exploration.md +77 -0
- package/src/docs/07-workflows/quick-analysis.md +45 -0
- package/src/docs/08-integrations/claude-code-auto-mode.md +191 -0
- package/src/docs/08-integrations/google-slides.md +175 -0
- package/src/docs/README.md +30 -0
- package/src/docs/manifest.json +108 -0
- package/src/templates/analysis-template.md +20 -0
- package/src/templates/branch-report.md +46 -0
- package/src/templates/diff-report.md +88 -0
- package/src/templates/knowledge-index.md +7 -0
- package/src/templates/model-card-schema.json +186 -0
- package/src/templates/model-card-schema.md +88 -0
- package/src/templates/model-card.md +124 -0
- package/src/templates/project-plan.md +47 -0
- package/src/templates/project-specs.md +81 -0
- package/src/templates/report-template.md +43 -0
- package/src/templates/study-template.md +25 -0
- package/src/ui/cc-readonly.js +181 -0
- package/src/ui/chat-session.js +466 -0
- package/src/ui/css/base.css +136 -0
- package/src/ui/css/brainstorm.css +525 -0
- package/src/ui/css/chat.css +1405 -0
- package/src/ui/css/editor.css +546 -0
- package/src/ui/css/eval-dashboard.css +157 -0
- package/src/ui/css/experiment.css +237 -0
- package/src/ui/css/guide.css +186 -0
- package/src/ui/css/knowledge-map.css +383 -0
- package/src/ui/css/layout.css +431 -0
- package/src/ui/css/model-card.css +161 -0
- package/src/ui/css/notebook-walkthrough.css +271 -0
- package/src/ui/css/pr-review.css +403 -0
- package/src/ui/css/prompt-lab.css +325 -0
- package/src/ui/css/sessions.css +258 -0
- package/src/ui/css/sidebar.css +661 -0
- package/src/ui/css/terminal.css +113 -0
- package/src/ui/css/theme-light.css +542 -0
- package/src/ui/index.html +389 -0
- package/src/ui/js/agents.js +32 -0
- package/src/ui/js/bookmarks.js +230 -0
- package/src/ui/js/chat.js +1776 -0
- package/src/ui/js/code-intel.js +328 -0
- package/src/ui/js/command-palette.js +142 -0
- package/src/ui/js/events.js +591 -0
- package/src/ui/js/explorer.js +317 -0
- package/src/ui/js/file-view.js +477 -0
- package/src/ui/js/git.js +536 -0
- package/src/ui/js/guide.js +198 -0
- package/src/ui/js/hud.js +75 -0
- package/src/ui/js/init.js +351 -0
- package/src/ui/js/knowledge-map.js +906 -0
- package/src/ui/js/markdown.js +114 -0
- package/src/ui/js/monaco.js +164 -0
- package/src/ui/js/notebook-walkthrough.js +272 -0
- package/src/ui/js/notebook.js +448 -0
- package/src/ui/js/panels.js +2681 -0
- package/src/ui/js/pinboard.js +186 -0
- package/src/ui/js/quick-open.js +164 -0
- package/src/ui/js/selection-context.js +131 -0
- package/src/ui/js/sessions.js +256 -0
- package/src/ui/js/settings.js +476 -0
- package/src/ui/js/split-view.js +82 -0
- package/src/ui/js/state.js +343 -0
- package/src/ui/js/table.js +161 -0
- package/src/ui/js/tabs.js +284 -0
- package/src/ui/js/tabular.js +125 -0
- package/src/ui/js/terminal.js +354 -0
- package/src/ui/js/timeline.js +137 -0
- package/src/ui/js/utils.js +293 -0
- package/src/ui/notebook-kernel.py +790 -0
- package/src/ui/open-browser.js +55 -0
- package/src/ui/permission-pattern.js +42 -0
- package/src/ui/relay.js +513 -0
- package/src/ui/server.js +3072 -0
- package/src/ui/session-index.js +225 -0
- package/src/ui/shards_icon.png +0 -0
- package/src/ui/spawn-server.js +41 -0
- package/src/ui/symbol-index.js +813 -0
- package/src/ui/ui-push.js +177 -0
- package/tools/gate-hook/VALIDATION_SPEC.md +273 -0
- package/tools/gate-hook/__tests__/auto-verify.test.js +343 -0
- package/tools/gate-hook/auto-allowlist.js +179 -0
- package/tools/gate-hook/auto-state.js +68 -0
- package/tools/gate-hook/classify.js +21 -0
- package/tools/gate-hook/log.js +57 -0
- package/tools/gate-hook/parser.js +205 -0
- package/tools/gate-hook/sql-guard.js +230 -0
- package/tools/gate-hook/state.js +170 -0
- package/tools/gate-hook/sweep.js +139 -0
- package/tools/gate-hook/transcript.js +45 -0
- package/tools/gate-hook/validation.js +321 -0
- package/tools/gate-hook.js +475 -0
- package/tools/install.js +914 -0
- package/tools/shards-gates.js +311 -0
- package/tools/shards-sessions.js +261 -0
- package/tools/shards-ui.js +377 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// shards-gates — diagnostics CLI for gate state
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const GATE_DIR = path.join(process.cwd(), '.shards', 'gates');
|
|
9
|
+
const AUTO_DIR = path.join(process.cwd(), '.shards', 'auto');
|
|
10
|
+
const STATE_FILE = path.join(GATE_DIR, 'state.json');
|
|
11
|
+
const VIOLATIONS_FILE = path.join(GATE_DIR, 'violations.jsonl');
|
|
12
|
+
const HISTORY_FILE = path.join(GATE_DIR, 'gates.jsonl');
|
|
13
|
+
const AUTO_STATE_FILE = path.join(AUTO_DIR, 'state.json');
|
|
14
|
+
|
|
15
|
+
// Read state.json and normalize to the v2 shape. Backward-compatible: a legacy
|
|
16
|
+
// single-slot object is upgraded in memory (mirrors tools/gate-hook/state.js).
|
|
17
|
+
function readState() {
|
|
18
|
+
let raw;
|
|
19
|
+
try { raw = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8')); }
|
|
20
|
+
catch { return { version: 2, sessions: {}, history: [] }; }
|
|
21
|
+
if (!raw || typeof raw !== 'object') return { version: 2, sessions: {}, history: [] };
|
|
22
|
+
if (raw.version === 2 || raw.sessions) {
|
|
23
|
+
return {
|
|
24
|
+
version: 2,
|
|
25
|
+
sessions: (raw.sessions && typeof raw.sessions === 'object') ? raw.sessions : {},
|
|
26
|
+
history: Array.isArray(raw.history) ? raw.history : [],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Legacy single-slot upgrade.
|
|
30
|
+
const sessions = {};
|
|
31
|
+
if (raw.open) {
|
|
32
|
+
sessions[raw.agent || '__legacy__'] = {
|
|
33
|
+
open: true,
|
|
34
|
+
id: raw.id,
|
|
35
|
+
phase: typeof raw.phase !== 'undefined' ? raw.phase : null,
|
|
36
|
+
kind: raw.kind || null,
|
|
37
|
+
agent: raw.agent || null,
|
|
38
|
+
opened_at: raw.opened_at || null,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return { version: 2, sessions, history: Array.isArray(raw.history) ? raw.history : [] };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Open session slots as [sessionId, gate] pairs.
|
|
45
|
+
function openSessions(s) {
|
|
46
|
+
return Object.entries(s.sessions || {}).filter(([, g]) => g && g.open);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function readAutoState() {
|
|
50
|
+
try { return JSON.parse(fs.readFileSync(AUTO_STATE_FILE, 'utf8')); }
|
|
51
|
+
catch { return { open: false, history: [] }; }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readJsonl(file, limit) {
|
|
55
|
+
try {
|
|
56
|
+
const lines = fs.readFileSync(file, 'utf8').split('\n').filter(Boolean);
|
|
57
|
+
const entries = lines.map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
|
|
58
|
+
return limit ? entries.slice(-limit) : entries;
|
|
59
|
+
} catch { return []; }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Atomic write helper — mirrors tools/gate-hook/state.js. Used by
|
|
63
|
+
// force-close so an operator override doesn't get clobbered by a concurrent
|
|
64
|
+
// reader / writer.
|
|
65
|
+
function atomicWriteJson(file, data) {
|
|
66
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
67
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
68
|
+
try {
|
|
69
|
+
fs.writeFileSync(tmp, JSON.stringify(data, null, 2));
|
|
70
|
+
fs.renameSync(tmp, file);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
try { fs.unlinkSync(tmp); } catch {}
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function formatDate(iso) {
|
|
78
|
+
if (!iso) return '—';
|
|
79
|
+
return new Date(iso).toLocaleString();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ─── Commands ─────────────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
function cmdStatus() {
|
|
85
|
+
const s = readState();
|
|
86
|
+
const open = openSessions(s);
|
|
87
|
+
console.log('\n── Gate Status ──────────────────────────────');
|
|
88
|
+
if (open.length > 0) {
|
|
89
|
+
console.log(` Status: OPEN (${open.length} session${open.length === 1 ? '' : 's'})`);
|
|
90
|
+
for (const [sessionId, g] of open) {
|
|
91
|
+
console.log(` ┌─ session ${sessionId}`);
|
|
92
|
+
console.log(` │ Gate ID: ${g.id}`);
|
|
93
|
+
console.log(` │ Phase: ${g.phase || '?'}`);
|
|
94
|
+
console.log(` │ Kind: ${g.kind || '?'}`);
|
|
95
|
+
console.log(` │ Agent: ${g.agent || '?'}`);
|
|
96
|
+
console.log(` │ Opened at: ${formatDate(g.opened_at)}`);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
console.log(' Status: closed (no session has an open gate)');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const history = (s.history || []).slice(-10);
|
|
103
|
+
if (history.length > 0) {
|
|
104
|
+
console.log('\n── Last 10 Gates ────────────────────────────');
|
|
105
|
+
for (const h of history) {
|
|
106
|
+
const kindTag = h.kind && h.kind !== 'phase' ? ` [${h.kind}]` : '';
|
|
107
|
+
console.log(` [${h.id}]${kindTag} phase=${h.phase} opened=${formatDate(h.opened_at)} closed=${formatDate(h.closed_at)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
console.log('');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// `checkpoint` and `confirm` are both non-advancing kinds. Advisory-mode
|
|
114
|
+
// checkpoints (SHARDS_CHECKPOINT_ENFORCE=0) are logged only to the JSONL
|
|
115
|
+
// history file — they never enter state.json.history. To give an accurate
|
|
116
|
+
// view we merge both sources, dedup'ing by (gate_id, opened_at|ts).
|
|
117
|
+
const CHECKPOINT_KINDS = new Set(['checkpoint', 'confirm']);
|
|
118
|
+
|
|
119
|
+
function cmdCheckpoints() {
|
|
120
|
+
const s = readState();
|
|
121
|
+
const stateEntries = (s.history || []).filter(h => h.kind && CHECKPOINT_KINDS.has(h.kind));
|
|
122
|
+
const jsonl = readJsonl(HISTORY_FILE);
|
|
123
|
+
// Advisory-mode entries: { event: 'advisory', kind, gate_id, phase, ts }.
|
|
124
|
+
// Opened/closed pairs: { event, gate_id, kind, ts, ... }.
|
|
125
|
+
// We keep advisories and opened-events as separate rows since advisories
|
|
126
|
+
// never have a corresponding close.
|
|
127
|
+
const jsonlEntries = jsonl.filter(e =>
|
|
128
|
+
e && e.kind && CHECKPOINT_KINDS.has(e.kind) &&
|
|
129
|
+
(e.event === 'advisory' || e.event === 'opened')
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Dedup: state.history entries are confirmed closes; the same gate also
|
|
133
|
+
// appears in jsonl as an 'opened' event. Drop jsonl 'opened' rows that have
|
|
134
|
+
// a corresponding closed entry in state.history by gate_id+opened_at.
|
|
135
|
+
const closedKeys = new Set(
|
|
136
|
+
stateEntries.map(h => `${h.id}|${h.opened_at || ''}`)
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const merged = [
|
|
140
|
+
...stateEntries.map(h => ({
|
|
141
|
+
source: 'state',
|
|
142
|
+
id: h.id,
|
|
143
|
+
kind: h.kind,
|
|
144
|
+
phase: h.phase,
|
|
145
|
+
opened_at: h.opened_at,
|
|
146
|
+
closed_at: h.closed_at,
|
|
147
|
+
confirmed_by: h.confirmed_by,
|
|
148
|
+
})),
|
|
149
|
+
...jsonlEntries
|
|
150
|
+
.filter(e => {
|
|
151
|
+
if (e.event !== 'opened') return true; // advisory always shown
|
|
152
|
+
// Skip opened rows whose close is already in state.history.
|
|
153
|
+
return !closedKeys.has(`${e.gate_id}|${e.ts || ''}`) &&
|
|
154
|
+
![...closedKeys].some(k => k.startsWith(`${e.gate_id}|`));
|
|
155
|
+
})
|
|
156
|
+
.map(e => ({
|
|
157
|
+
source: 'jsonl',
|
|
158
|
+
id: e.gate_id,
|
|
159
|
+
kind: e.kind,
|
|
160
|
+
phase: e.phase,
|
|
161
|
+
opened_at: e.ts,
|
|
162
|
+
closed_at: null,
|
|
163
|
+
advisory: e.event === 'advisory',
|
|
164
|
+
})),
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
if (merged.length === 0) {
|
|
168
|
+
console.log('\nNo checkpoint gates recorded in the current session.\n');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
console.log(`\n── Checkpoint / Confirm History (${merged.length} entries) ──────────────`);
|
|
173
|
+
for (const h of merged) {
|
|
174
|
+
const tag = h.advisory ? ' [advisory]' : '';
|
|
175
|
+
const kindLabel = h.kind ? `kind=${h.kind} ` : '';
|
|
176
|
+
console.log(` [${h.id}]${tag} ${kindLabel}phase=${h.phase} opened=${formatDate(h.opened_at)} closed=${formatDate(h.closed_at)} via=${h.confirmed_by || '—'}`);
|
|
177
|
+
}
|
|
178
|
+
console.log('');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function cmdHistory() {
|
|
182
|
+
const entries = readJsonl(HISTORY_FILE);
|
|
183
|
+
if (entries.length === 0) {
|
|
184
|
+
console.log('\nNo gate history yet.\n');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
console.log(`\n── Gate History (${entries.length} entries) ──────────────`);
|
|
188
|
+
for (const e of entries) {
|
|
189
|
+
console.log(` [${e.ts}] ${e.event} gate=${e.gate_id}`);
|
|
190
|
+
}
|
|
191
|
+
console.log('');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function cmdViolations() {
|
|
195
|
+
const entries = readJsonl(VIOLATIONS_FILE);
|
|
196
|
+
if (entries.length === 0) {
|
|
197
|
+
console.log('\nNo violations recorded.\n');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
console.log(`\n── Violations (${entries.length} total) ──────────────────`);
|
|
201
|
+
for (const e of entries) {
|
|
202
|
+
console.log(` [${e.ts}] ${e.type} gate=${e.gate_id} reason=${e.reason}`);
|
|
203
|
+
}
|
|
204
|
+
console.log('');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function cmdForceClose() {
|
|
208
|
+
const s = readState();
|
|
209
|
+
// Operator override unsticks EVERYONE — clear all session slots, appending an
|
|
210
|
+
// operator-force-close history entry per previously-open session.
|
|
211
|
+
const open = openSessions(s);
|
|
212
|
+
const wasOpen = open.length > 0;
|
|
213
|
+
const closed_at = new Date().toISOString();
|
|
214
|
+
const newState = {
|
|
215
|
+
version: 2,
|
|
216
|
+
sessions: {},
|
|
217
|
+
history: [
|
|
218
|
+
...(s.history || []),
|
|
219
|
+
...open.map(([, g]) => ({
|
|
220
|
+
id: g.id || 'unknown',
|
|
221
|
+
phase: g.phase,
|
|
222
|
+
kind: g.kind,
|
|
223
|
+
opened_at: g.opened_at,
|
|
224
|
+
closed_at,
|
|
225
|
+
confirmed_by: 'operator-force-close',
|
|
226
|
+
})),
|
|
227
|
+
],
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// Also reset auto-verify state. If an auto-verify block was open, its
|
|
231
|
+
// budget would otherwise remain live after the operator override and the
|
|
232
|
+
// next bulk-read tool call could be silently auto-approved against the
|
|
233
|
+
// wishes of the operator who just force-closed the session.
|
|
234
|
+
const auto = readAutoState();
|
|
235
|
+
const autoWasOpen = !!auto.open;
|
|
236
|
+
let autoReset = null;
|
|
237
|
+
if (autoWasOpen) {
|
|
238
|
+
autoReset = {
|
|
239
|
+
open: false,
|
|
240
|
+
history: [...(auto.history || []), {
|
|
241
|
+
id: auto.id || 'unknown',
|
|
242
|
+
agent: auto.agent || null,
|
|
243
|
+
phase: auto.phase || null,
|
|
244
|
+
opened_at: auto.opened_at || null,
|
|
245
|
+
closed_at: new Date().toISOString(),
|
|
246
|
+
closed_reason: 'operator-force-close',
|
|
247
|
+
approvals_used: (auto.tool_budget_initial || 0) - (auto.tool_budget_remaining || 0),
|
|
248
|
+
}],
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
fs.mkdirSync(GATE_DIR, { recursive: true });
|
|
254
|
+
atomicWriteJson(STATE_FILE, newState);
|
|
255
|
+
if (autoReset) {
|
|
256
|
+
atomicWriteJson(AUTO_STATE_FILE, autoReset);
|
|
257
|
+
}
|
|
258
|
+
// Log to violations — one entry per previously-open session gate.
|
|
259
|
+
const ts = new Date().toISOString();
|
|
260
|
+
const lines = (wasOpen ? open : [[null, { id: 'unknown' }]]).map(([sid, g]) =>
|
|
261
|
+
JSON.stringify({
|
|
262
|
+
type: 'operator-force-close',
|
|
263
|
+
gate_id: g.id || 'unknown',
|
|
264
|
+
session_id: sid || null,
|
|
265
|
+
auto_verify_was_open: autoWasOpen,
|
|
266
|
+
auto_block_id: auto.id || null,
|
|
267
|
+
reason: 'operator force-close',
|
|
268
|
+
ts,
|
|
269
|
+
})
|
|
270
|
+
);
|
|
271
|
+
fs.appendFileSync(VIOLATIONS_FILE, lines.join('\n') + '\n');
|
|
272
|
+
|
|
273
|
+
if (wasOpen) {
|
|
274
|
+
const ids = open.map(([, g]) => `'${g.id}'`).join(', ');
|
|
275
|
+
console.log(`\nForce-closed ${open.length} gate${open.length === 1 ? '' : 's'}: ${ids}.`);
|
|
276
|
+
} else {
|
|
277
|
+
console.log('\nGate was already closed.');
|
|
278
|
+
}
|
|
279
|
+
if (autoWasOpen) {
|
|
280
|
+
console.log(`Also reset auto-verify block '${auto.id}' (was open).`);
|
|
281
|
+
} else {
|
|
282
|
+
console.log('Auto-verify state was already closed.');
|
|
283
|
+
}
|
|
284
|
+
console.log('');
|
|
285
|
+
} catch (err) {
|
|
286
|
+
console.error('Error force-closing gate:', err.message);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ─── CLI entry ────────────────────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
const cmd = process.argv[2] || 'status';
|
|
293
|
+
|
|
294
|
+
switch (cmd) {
|
|
295
|
+
case 'status': cmdStatus(); break;
|
|
296
|
+
case 'history': cmdHistory(); break;
|
|
297
|
+
case 'checkpoints': cmdCheckpoints(); break;
|
|
298
|
+
case 'violations': cmdViolations(); break;
|
|
299
|
+
case 'force-close': cmdForceClose(); break;
|
|
300
|
+
default:
|
|
301
|
+
console.log(`
|
|
302
|
+
shards-gates — Gate enforcement diagnostics
|
|
303
|
+
|
|
304
|
+
Usage:
|
|
305
|
+
shards-gates status Print current gate state and last 10 history entries
|
|
306
|
+
shards-gates history Full gate history dump
|
|
307
|
+
shards-gates checkpoints List checkpoint / confirm gates (merges advisory-mode entries from JSONL)
|
|
308
|
+
shards-gates violations Tail violations.jsonl
|
|
309
|
+
shards-gates force-close Force-close an open gate (and reset auto-verify) — operator override
|
|
310
|
+
`);
|
|
311
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// shards-sessions — list, inspect, resume, and end Shards chat sessions.
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const sessionIndex = require('../src/ui/session-index.js');
|
|
9
|
+
|
|
10
|
+
const PROJECT_DIR = process.cwd();
|
|
11
|
+
const SHARDS_DIR = path.join(PROJECT_DIR, '.shards');
|
|
12
|
+
const SESSIONS_DIR = path.join(SHARDS_DIR, 'sessions');
|
|
13
|
+
const GATE_STATE_FILE = path.join(SHARDS_DIR, 'gates', 'state.json');
|
|
14
|
+
|
|
15
|
+
// Mirrors src/ui/server.js#readGateSnapshot — returns the gate id (string) if a
|
|
16
|
+
// gate is currently open, else null. Both code paths produce identical shapes
|
|
17
|
+
// in INDEX.json, so the UI Sessions panel and CLI `show` render the same field.
|
|
18
|
+
// Tolerant of a missing/corrupt state file (returns null silently).
|
|
19
|
+
function readGateSnapshot() {
|
|
20
|
+
try {
|
|
21
|
+
const raw = fs.readFileSync(GATE_STATE_FILE, 'utf8');
|
|
22
|
+
const state = JSON.parse(raw);
|
|
23
|
+
if (state && state.open) {
|
|
24
|
+
return {
|
|
25
|
+
gateOpenAtEnd: state.id || null,
|
|
26
|
+
phase: typeof state.phase === 'number' ? state.phase : null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { gateOpenAtEnd: null, phase: null };
|
|
30
|
+
} catch {
|
|
31
|
+
return { gateOpenAtEnd: null, phase: null };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function formatDate(iso) {
|
|
36
|
+
if (!iso) return '—';
|
|
37
|
+
try { return new Date(iso).toLocaleString(); } catch { return iso; }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function formatRelative(iso) {
|
|
41
|
+
if (!iso) return '—';
|
|
42
|
+
const ms = Date.now() - Date.parse(iso);
|
|
43
|
+
if (!Number.isFinite(ms) || ms < 0) return iso;
|
|
44
|
+
const s = Math.round(ms / 1000);
|
|
45
|
+
if (s < 60) return `${s}s ago`;
|
|
46
|
+
const m = Math.round(s / 60);
|
|
47
|
+
if (m < 60) return `${m}m ago`;
|
|
48
|
+
const h = Math.round(m / 60);
|
|
49
|
+
if (h < 48) return `${h}h ago`;
|
|
50
|
+
const d = Math.round(h / 24);
|
|
51
|
+
return `${d}d ago`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function short(id) {
|
|
55
|
+
return id ? id.slice(0, 8) : '—';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function pad(s, n) {
|
|
59
|
+
s = String(s == null ? '' : s);
|
|
60
|
+
if (s.length >= n) return s.slice(0, n);
|
|
61
|
+
return s + ' '.repeat(n - s.length);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ─── Argument parsing ──────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
function parseFlags(argv) {
|
|
67
|
+
const out = { args: [], flags: {} };
|
|
68
|
+
for (let i = 0; i < argv.length; i++) {
|
|
69
|
+
const a = argv[i];
|
|
70
|
+
if (a.startsWith('--')) {
|
|
71
|
+
const eq = a.indexOf('=');
|
|
72
|
+
if (eq > -1) {
|
|
73
|
+
out.flags[a.slice(2, eq)] = a.slice(eq + 1);
|
|
74
|
+
} else {
|
|
75
|
+
const next = argv[i + 1];
|
|
76
|
+
if (next && !next.startsWith('--')) { out.flags[a.slice(2)] = next; i += 1; }
|
|
77
|
+
else { out.flags[a.slice(2)] = true; }
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
out.args.push(a);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resolveSessionId(prefix, rows) {
|
|
87
|
+
// Allow operating on a unique short prefix — typing the full UUID is painful.
|
|
88
|
+
if (!prefix) return null;
|
|
89
|
+
const exact = rows.find((r) => r.sessionId === prefix);
|
|
90
|
+
if (exact) return exact.sessionId;
|
|
91
|
+
const matches = rows.filter((r) => r.sessionId.startsWith(prefix));
|
|
92
|
+
if (matches.length === 0) return null;
|
|
93
|
+
if (matches.length > 1) {
|
|
94
|
+
console.error(`Ambiguous session prefix "${prefix}" — matched ${matches.length} sessions.`);
|
|
95
|
+
process.exit(2);
|
|
96
|
+
}
|
|
97
|
+
return matches[0].sessionId;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ─── Commands ─────────────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
function cmdList(parsed) {
|
|
103
|
+
const filter = {};
|
|
104
|
+
if (parsed.flags.project) filter.project = parsed.flags.project;
|
|
105
|
+
if (parsed.flags.agent) filter.agent = parsed.flags.agent;
|
|
106
|
+
if (parsed.flags.status) filter.status = parsed.flags.status;
|
|
107
|
+
|
|
108
|
+
let rows = sessionIndex.listSessions(SESSIONS_DIR, filter);
|
|
109
|
+
const limit = parsed.flags.limit ? Number(parsed.flags.limit) : null;
|
|
110
|
+
if (limit && Number.isFinite(limit)) rows = rows.slice(0, limit);
|
|
111
|
+
|
|
112
|
+
if (rows.length === 0) {
|
|
113
|
+
console.log('\nNo sessions recorded.\n');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log('');
|
|
118
|
+
console.log(pad('ID', 10) + pad('AGENT', 22) + pad('STATUS', 11) + pad('PHASE', 7) + pad('PROJECT', 28) + 'LAST');
|
|
119
|
+
console.log('─'.repeat(110));
|
|
120
|
+
for (const r of rows) {
|
|
121
|
+
console.log(
|
|
122
|
+
pad(short(r.sessionId), 10) +
|
|
123
|
+
pad(r.agent || '—', 22) +
|
|
124
|
+
pad(r.status, 11) +
|
|
125
|
+
pad(typeof r.phase === 'number' ? `${r.phase}` : '—', 7) +
|
|
126
|
+
pad(r.projectDir || r.projectName || '—', 28) +
|
|
127
|
+
formatRelative(r.lastActivityAt)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log(`${rows.length} session(s). Use \`shards-sessions show <id>\` for full detail.`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function cmdShow(parsed) {
|
|
135
|
+
const all = sessionIndex.listSessions(SESSIONS_DIR);
|
|
136
|
+
const id = resolveSessionId(parsed.args[0], all);
|
|
137
|
+
if (!id) {
|
|
138
|
+
console.error(`No session matches "${parsed.args[0]}".`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
const entry = sessionIndex.getEntry(SESSIONS_DIR, id);
|
|
142
|
+
if (!entry) {
|
|
143
|
+
console.error('Entry vanished.');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
console.log('');
|
|
147
|
+
console.log(`Session: ${entry.sessionId}`);
|
|
148
|
+
console.log(`Agent: ${entry.agent || '—'}`);
|
|
149
|
+
console.log(`Project: ${entry.projectDir || entry.projectName || '—'}`);
|
|
150
|
+
console.log(`Status: ${entry.status}`);
|
|
151
|
+
console.log(`Phase: ${entry.phase == null ? '—' : entry.phase}`);
|
|
152
|
+
console.log(`Created: ${formatDate(entry.createdAt)}`);
|
|
153
|
+
console.log(`Last act: ${formatDate(entry.lastActivityAt)} (${formatRelative(entry.lastActivityAt)})`);
|
|
154
|
+
if (entry.endedAt) console.log(`Ended: ${formatDate(entry.endedAt)} (reason: ${entry.endReason || '—'})`);
|
|
155
|
+
if (entry.gateOpenAtEnd) console.log(`Open gate: ${entry.gateOpenAtEnd}`);
|
|
156
|
+
if (entry.resumedFrom) console.log(`Resumed: from ${entry.resumedFrom}`);
|
|
157
|
+
if (entry.messageCount) console.log(`Messages: ${entry.messageCount}`);
|
|
158
|
+
if (entry.lastUserPrompt) {
|
|
159
|
+
console.log('');
|
|
160
|
+
console.log('Last prompt:');
|
|
161
|
+
console.log(` ${entry.lastUserPrompt}`);
|
|
162
|
+
}
|
|
163
|
+
console.log('');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function cmdResume(parsed) {
|
|
167
|
+
const all = sessionIndex.listSessions(SESSIONS_DIR);
|
|
168
|
+
const id = resolveSessionId(parsed.args[0], all);
|
|
169
|
+
if (!id) {
|
|
170
|
+
console.error(`No session matches "${parsed.args[0]}".`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
const entry = sessionIndex.getEntry(SESSIONS_DIR, id);
|
|
174
|
+
if (!entry) {
|
|
175
|
+
console.error('Entry not found.');
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
if (entry.status === 'active') {
|
|
179
|
+
console.error('That session is still marked active. End it first with `shards-sessions end <id>` or via the UI.');
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// We can't re-exec claude from inside this process and have it land in the
|
|
184
|
+
// user's terminal, so print the exact command they need to run. This also
|
|
185
|
+
// works cleanly inside a Claude Code session — the user can copy-paste.
|
|
186
|
+
console.log('');
|
|
187
|
+
console.log(`To resume this session, run:`);
|
|
188
|
+
console.log('');
|
|
189
|
+
console.log(` claude --resume ${entry.sessionId}`);
|
|
190
|
+
console.log('');
|
|
191
|
+
console.log(`(agent: ${entry.agent || '—'}, project: ${entry.projectDir || entry.projectName || '—'}, phase: ${entry.phase == null ? '—' : entry.phase})`);
|
|
192
|
+
console.log('');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function cmdEnd(parsed) {
|
|
196
|
+
const all = sessionIndex.listSessions(SESSIONS_DIR);
|
|
197
|
+
const id = resolveSessionId(parsed.args[0], all);
|
|
198
|
+
if (!id) {
|
|
199
|
+
console.error(`No session matches "${parsed.args[0]}".`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
const entry = sessionIndex.getEntry(SESSIONS_DIR, id);
|
|
203
|
+
if (!entry) {
|
|
204
|
+
console.error('Entry not found.');
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
if (entry.status !== 'active') {
|
|
208
|
+
console.log(`Session ${short(id)} is already ${entry.status}.`);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
// Snapshot gate state at end-of-session so CLI-ended sessions match the
|
|
212
|
+
// shape written by the UI's POST /chat/end path (src/ui/server.js).
|
|
213
|
+
const snap = readGateSnapshot();
|
|
214
|
+
sessionIndex.markEnded(SESSIONS_DIR, id, {
|
|
215
|
+
reason: 'cli_end',
|
|
216
|
+
gateOpenAtEnd: snap.gateOpenAtEnd,
|
|
217
|
+
});
|
|
218
|
+
if (typeof snap.phase === 'number') {
|
|
219
|
+
sessionIndex.updatePhase(SESSIONS_DIR, id, snap.phase);
|
|
220
|
+
}
|
|
221
|
+
console.log(`Marked session ${short(id)} as ended in the index.`);
|
|
222
|
+
if (snap.gateOpenAtEnd) console.log(`Captured open gate at end: ${snap.gateOpenAtEnd}`);
|
|
223
|
+
console.log(`Note: this does not kill a live claude process — if one is running for this session, end it from its terminal or the UI.`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function cmdHelp() {
|
|
227
|
+
console.log(`
|
|
228
|
+
shards-sessions — list, inspect, resume, and end Shards chat sessions
|
|
229
|
+
|
|
230
|
+
Usage:
|
|
231
|
+
shards-sessions list [--status active|ended|abandoned] [--agent <name>] [--project <dir>] [--limit N]
|
|
232
|
+
shards-sessions show <id|prefix>
|
|
233
|
+
shards-sessions resume <id|prefix> Prints the \`claude --resume\` command to run
|
|
234
|
+
shards-sessions end <id|prefix> Marks an active entry as ended in INDEX.json
|
|
235
|
+
|
|
236
|
+
Tips:
|
|
237
|
+
Session IDs accept any unique prefix (typically 8 chars is plenty).
|
|
238
|
+
All commands operate on .shards/sessions/INDEX.json in the current directory.
|
|
239
|
+
`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ─── Dispatch ──────────────────────────────────────────────────────────────
|
|
243
|
+
|
|
244
|
+
const raw = process.argv.slice(2);
|
|
245
|
+
const cmd = raw[0] || 'list';
|
|
246
|
+
const parsed = parseFlags(raw.slice(1));
|
|
247
|
+
|
|
248
|
+
switch (cmd) {
|
|
249
|
+
case 'list': cmdList(parsed); break;
|
|
250
|
+
case 'show': cmdShow(parsed); break;
|
|
251
|
+
case 'resume': cmdResume(parsed); break;
|
|
252
|
+
case 'end': cmdEnd(parsed); break;
|
|
253
|
+
case 'help':
|
|
254
|
+
case '--help':
|
|
255
|
+
case '-h':
|
|
256
|
+
cmdHelp(); break;
|
|
257
|
+
default:
|
|
258
|
+
console.error(`Unknown command: ${cmd}`);
|
|
259
|
+
cmdHelp();
|
|
260
|
+
process.exit(2);
|
|
261
|
+
}
|