flonat-research 0.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/.claude/agents/domain-reviewer.md +336 -0
- package/.claude/agents/fixer.md +226 -0
- package/.claude/agents/paper-critic.md +370 -0
- package/.claude/agents/peer-reviewer.md +289 -0
- package/.claude/agents/proposal-reviewer.md +215 -0
- package/.claude/agents/referee2-reviewer.md +367 -0
- package/.claude/agents/references/journal-referee-profiles.md +354 -0
- package/.claude/agents/references/paper-critic/council-personas.md +77 -0
- package/.claude/agents/references/paper-critic/council-prompts.md +198 -0
- package/.claude/agents/references/peer-reviewer/report-template.md +199 -0
- package/.claude/agents/references/peer-reviewer/sa-prompts.md +260 -0
- package/.claude/agents/references/peer-reviewer/security-scan.md +188 -0
- package/.claude/agents/references/proposal-reviewer/report-template.md +144 -0
- package/.claude/agents/references/proposal-reviewer/sa-prompts.md +149 -0
- package/.claude/agents/references/referee-config.md +114 -0
- package/.claude/agents/references/referee2-reviewer/audit-checklists.md +287 -0
- package/.claude/agents/references/referee2-reviewer/report-template.md +334 -0
- package/.claude/rules/design-before-results.md +52 -0
- package/.claude/rules/ignore-agents-md.md +17 -0
- package/.claude/rules/ignore-gemini-md.md +17 -0
- package/.claude/rules/lean-claude-md.md +45 -0
- package/.claude/rules/learn-tags.md +99 -0
- package/.claude/rules/overleaf-separation.md +67 -0
- package/.claude/rules/plan-first.md +175 -0
- package/.claude/rules/read-docs-first.md +50 -0
- package/.claude/rules/scope-discipline.md +28 -0
- package/.claude/settings.json +125 -0
- package/.context/current-focus.md +33 -0
- package/.context/preferences/priorities.md +36 -0
- package/.context/preferences/task-naming.md +28 -0
- package/.context/profile.md +29 -0
- package/.context/projects/_index.md +41 -0
- package/.context/projects/papers/nudge-exp.md +22 -0
- package/.context/projects/papers/uncertainty.md +31 -0
- package/.context/resources/claude-scientific-writer-review.md +48 -0
- package/.context/resources/cunningham-multi-analyst-agents.md +104 -0
- package/.context/resources/cunningham-multilang-code-audit.md +62 -0
- package/.context/resources/google-ai-co-scientist-review.md +72 -0
- package/.context/resources/karpathy-llm-council-review.md +58 -0
- package/.context/resources/multi-coder-reliability-protocol.md +175 -0
- package/.context/resources/pedro-santanna-takeaways.md +96 -0
- package/.context/resources/venue-rankings/abs_ajg_2024.csv +1823 -0
- package/.context/resources/venue-rankings/abs_ajg_2024_econ.csv +356 -0
- package/.context/resources/venue-rankings/cabs_4_4star_theory.csv +40 -0
- package/.context/resources/venue-rankings/core_2026.csv +801 -0
- package/.context/resources/venue-rankings.md +147 -0
- package/.context/workflows/README.md +69 -0
- package/.context/workflows/daily-review.md +91 -0
- package/.context/workflows/meeting-actions.md +108 -0
- package/.context/workflows/replication-protocol.md +155 -0
- package/.context/workflows/weekly-review.md +113 -0
- package/.mcp-server-biblio/formatters.py +158 -0
- package/.mcp-server-biblio/pyproject.toml +11 -0
- package/.mcp-server-biblio/server.py +678 -0
- package/.mcp-server-biblio/sources/__init__.py +14 -0
- package/.mcp-server-biblio/sources/base.py +73 -0
- package/.mcp-server-biblio/sources/formatters.py +83 -0
- package/.mcp-server-biblio/sources/models.py +22 -0
- package/.mcp-server-biblio/sources/multi_source.py +243 -0
- package/.mcp-server-biblio/sources/openalex_source.py +183 -0
- package/.mcp-server-biblio/sources/scopus_source.py +309 -0
- package/.mcp-server-biblio/sources/wos_source.py +508 -0
- package/.mcp-server-biblio/uv.lock +896 -0
- package/.scripts/README.md +161 -0
- package/.scripts/ai_pattern_density.py +446 -0
- package/.scripts/conf +445 -0
- package/.scripts/config.py +122 -0
- package/.scripts/count_inventory.py +275 -0
- package/.scripts/daily_digest.py +288 -0
- package/.scripts/done +177 -0
- package/.scripts/extract_meeting_actions.py +223 -0
- package/.scripts/focus +176 -0
- package/.scripts/generate-codex-agents-md.py +217 -0
- package/.scripts/inbox +194 -0
- package/.scripts/notion_helpers.py +325 -0
- package/.scripts/openalex/query_helpers.py +306 -0
- package/.scripts/papers +227 -0
- package/.scripts/query +223 -0
- package/.scripts/session-history.py +201 -0
- package/.scripts/skill-health.py +516 -0
- package/.scripts/skill-log-miner.py +273 -0
- package/.scripts/sync-to-codex.sh +252 -0
- package/.scripts/task +213 -0
- package/.scripts/tasks +190 -0
- package/.scripts/week +206 -0
- package/CLAUDE.md +197 -0
- package/LICENSE +21 -0
- package/MEMORY.md +38 -0
- package/README.md +269 -0
- package/docs/agents.md +44 -0
- package/docs/bibliography-setup.md +55 -0
- package/docs/council-mode.md +36 -0
- package/docs/getting-started.md +245 -0
- package/docs/hooks.md +38 -0
- package/docs/mcp-servers.md +82 -0
- package/docs/notion-setup.md +109 -0
- package/docs/rules.md +33 -0
- package/docs/scripts.md +303 -0
- package/docs/setup-overview/setup-overview.pdf +0 -0
- package/docs/skills.md +70 -0
- package/docs/system.md +159 -0
- package/hooks/block-destructive-git.sh +66 -0
- package/hooks/context-monitor.py +114 -0
- package/hooks/postcompact-restore.py +157 -0
- package/hooks/precompact-autosave.py +181 -0
- package/hooks/promise-checker.sh +124 -0
- package/hooks/protect-source-files.sh +81 -0
- package/hooks/resume-context-loader.sh +53 -0
- package/hooks/startup-context-loader.sh +102 -0
- package/package.json +51 -0
- package/packages/cli-council/.github/workflows/claude-code-review.yml +44 -0
- package/packages/cli-council/.github/workflows/claude.yml +50 -0
- package/packages/cli-council/README.md +100 -0
- package/packages/cli-council/pyproject.toml +43 -0
- package/packages/cli-council/src/cli_council/__init__.py +19 -0
- package/packages/cli-council/src/cli_council/__main__.py +185 -0
- package/packages/cli-council/src/cli_council/backends/__init__.py +8 -0
- package/packages/cli-council/src/cli_council/backends/base.py +81 -0
- package/packages/cli-council/src/cli_council/backends/claude.py +25 -0
- package/packages/cli-council/src/cli_council/backends/codex.py +27 -0
- package/packages/cli-council/src/cli_council/backends/gemini.py +26 -0
- package/packages/cli-council/src/cli_council/checkpoint.py +212 -0
- package/packages/cli-council/src/cli_council/config.py +51 -0
- package/packages/cli-council/src/cli_council/council.py +391 -0
- package/packages/cli-council/src/cli_council/models.py +46 -0
- package/packages/llm-council/.github/workflows/claude-code-review.yml +44 -0
- package/packages/llm-council/.github/workflows/claude.yml +50 -0
- package/packages/llm-council/README.md +453 -0
- package/packages/llm-council/pyproject.toml +42 -0
- package/packages/llm-council/src/llm_council/__init__.py +23 -0
- package/packages/llm-council/src/llm_council/__main__.py +259 -0
- package/packages/llm-council/src/llm_council/checkpoint.py +193 -0
- package/packages/llm-council/src/llm_council/client.py +253 -0
- package/packages/llm-council/src/llm_council/config.py +232 -0
- package/packages/llm-council/src/llm_council/council.py +482 -0
- package/packages/llm-council/src/llm_council/models.py +46 -0
- package/packages/mcp-bibliography/MEMORY.md +31 -0
- package/packages/mcp-bibliography/_app.py +226 -0
- package/packages/mcp-bibliography/formatters.py +158 -0
- package/packages/mcp-bibliography/log/2026-03-13-2100.md +35 -0
- package/packages/mcp-bibliography/pyproject.toml +15 -0
- package/packages/mcp-bibliography/run.sh +20 -0
- package/packages/mcp-bibliography/scholarly_formatters.py +83 -0
- package/packages/mcp-bibliography/server.py +1857 -0
- package/packages/mcp-bibliography/tools/__init__.py +28 -0
- package/packages/mcp-bibliography/tools/_registry.py +19 -0
- package/packages/mcp-bibliography/tools/altmetric.py +107 -0
- package/packages/mcp-bibliography/tools/core.py +92 -0
- package/packages/mcp-bibliography/tools/dblp.py +52 -0
- package/packages/mcp-bibliography/tools/openalex.py +296 -0
- package/packages/mcp-bibliography/tools/opencitations.py +102 -0
- package/packages/mcp-bibliography/tools/openreview.py +179 -0
- package/packages/mcp-bibliography/tools/orcid.py +131 -0
- package/packages/mcp-bibliography/tools/scholarly.py +575 -0
- package/packages/mcp-bibliography/tools/unpaywall.py +63 -0
- package/packages/mcp-bibliography/tools/zenodo.py +123 -0
- package/packages/mcp-bibliography/uv.lock +711 -0
- package/scripts/setup.sh +143 -0
- package/skills/beamer-deck/SKILL.md +199 -0
- package/skills/beamer-deck/references/quality-rubric.md +54 -0
- package/skills/beamer-deck/references/review-prompts.md +106 -0
- package/skills/bib-validate/SKILL.md +261 -0
- package/skills/bib-validate/references/council-mode.md +34 -0
- package/skills/bib-validate/references/deep-verify.md +79 -0
- package/skills/bib-validate/references/fix-mode.md +36 -0
- package/skills/bib-validate/references/openalex-verification.md +45 -0
- package/skills/bib-validate/references/preprint-check.md +31 -0
- package/skills/bib-validate/references/ref-manager-crossref.md +41 -0
- package/skills/bib-validate/references/report-template.md +82 -0
- package/skills/code-archaeology/SKILL.md +141 -0
- package/skills/code-review/SKILL.md +265 -0
- package/skills/code-review/references/quality-rubric.md +67 -0
- package/skills/consolidate-memory/SKILL.md +208 -0
- package/skills/context-status/SKILL.md +126 -0
- package/skills/creation-guard/SKILL.md +230 -0
- package/skills/devils-advocate/SKILL.md +130 -0
- package/skills/devils-advocate/references/competing-hypotheses.md +83 -0
- package/skills/init-project/SKILL.md +115 -0
- package/skills/init-project-course/references/memory-and-settings.md +92 -0
- package/skills/init-project-course/references/organise-templates.md +94 -0
- package/skills/init-project-course/skill.md +147 -0
- package/skills/init-project-light/skill.md +139 -0
- package/skills/init-project-research/SKILL.md +368 -0
- package/skills/init-project-research/references/atlas-pipeline-sync.md +70 -0
- package/skills/init-project-research/references/atlas-schema.md +81 -0
- package/skills/init-project-research/references/confirmation-report.md +39 -0
- package/skills/init-project-research/references/domain-profile-template.md +104 -0
- package/skills/init-project-research/references/interview-round3.md +34 -0
- package/skills/init-project-research/references/literature-discovery.md +43 -0
- package/skills/init-project-research/references/scaffold-details.md +197 -0
- package/skills/init-project-research/templates/field-calibration.md +60 -0
- package/skills/init-project-research/templates/pipeline-manifest.md +63 -0
- package/skills/init-project-research/templates/run-all.sh +116 -0
- package/skills/init-project-research/templates/seed-files.md +337 -0
- package/skills/insights-deck/SKILL.md +151 -0
- package/skills/interview-me/SKILL.md +157 -0
- package/skills/latex/SKILL.md +141 -0
- package/skills/latex/references/latex-configs.md +183 -0
- package/skills/latex-autofix/SKILL.md +230 -0
- package/skills/latex-autofix/references/known-errors.md +183 -0
- package/skills/latex-autofix/references/quality-rubric.md +50 -0
- package/skills/latex-health-check/SKILL.md +161 -0
- package/skills/learn/SKILL.md +220 -0
- package/skills/learn/scripts/validate_skill.py +265 -0
- package/skills/lessons-learned/SKILL.md +201 -0
- package/skills/literature/SKILL.md +335 -0
- package/skills/literature/references/agent-templates.md +393 -0
- package/skills/literature/references/bibliometric-apis.md +44 -0
- package/skills/literature/references/cli-council-search.md +79 -0
- package/skills/literature/references/openalex-api-guide.md +371 -0
- package/skills/literature/references/openalex-common-queries.md +381 -0
- package/skills/literature/references/openalex-workflows.md +248 -0
- package/skills/literature/references/reference-manager-sync.md +36 -0
- package/skills/literature/references/scopus-api-guide.md +208 -0
- package/skills/literature/references/wos-api-guide.md +308 -0
- package/skills/multi-perspective/SKILL.md +311 -0
- package/skills/multi-perspective/references/computational-many-analysts.md +77 -0
- package/skills/pipeline-manifest/SKILL.md +226 -0
- package/skills/pre-submission-report/SKILL.md +153 -0
- package/skills/process-reviews/SKILL.md +244 -0
- package/skills/process-reviews/references/rr-routing.md +101 -0
- package/skills/project-deck/SKILL.md +87 -0
- package/skills/project-safety/SKILL.md +135 -0
- package/skills/proofread/SKILL.md +254 -0
- package/skills/proofread/references/quality-rubric.md +104 -0
- package/skills/python-env/SKILL.md +57 -0
- package/skills/quarto-deck/SKILL.md +226 -0
- package/skills/quarto-deck/references/markdown-format.md +143 -0
- package/skills/quarto-deck/references/quality-rubric.md +54 -0
- package/skills/save-context/SKILL.md +174 -0
- package/skills/session-log/SKILL.md +98 -0
- package/skills/shared/concept-validation-gate.md +161 -0
- package/skills/shared/council-protocol.md +265 -0
- package/skills/shared/distribution-diagnostics.md +164 -0
- package/skills/shared/engagement-stratified-sampling.md +218 -0
- package/skills/shared/escalation-protocol.md +74 -0
- package/skills/shared/external-audit-protocol.md +205 -0
- package/skills/shared/intercoder-reliability.md +256 -0
- package/skills/shared/mcp-degradation.md +81 -0
- package/skills/shared/method-probing-questions.md +163 -0
- package/skills/shared/multi-language-conventions.md +143 -0
- package/skills/shared/paid-api-safety.md +174 -0
- package/skills/shared/palettes.md +90 -0
- package/skills/shared/progressive-disclosure.md +92 -0
- package/skills/shared/project-documentation-content.md +443 -0
- package/skills/shared/project-documentation-format.md +281 -0
- package/skills/shared/project-documentation.md +100 -0
- package/skills/shared/publication-output.md +138 -0
- package/skills/shared/quality-scoring.md +70 -0
- package/skills/shared/reference-resolution.md +77 -0
- package/skills/shared/research-quality-rubric.md +165 -0
- package/skills/shared/rhetoric-principles.md +54 -0
- package/skills/shared/skill-design-patterns.md +272 -0
- package/skills/shared/skill-index.md +240 -0
- package/skills/shared/system-documentation.md +334 -0
- package/skills/shared/tikz-rules.md +402 -0
- package/skills/shared/validation-tiers.md +121 -0
- package/skills/shared/venue-guides/README.md +46 -0
- package/skills/shared/venue-guides/cell_press_style.md +483 -0
- package/skills/shared/venue-guides/conferences_formatting.md +564 -0
- package/skills/shared/venue-guides/cs_conference_style.md +463 -0
- package/skills/shared/venue-guides/examples/cell_summary_example.md +247 -0
- package/skills/shared/venue-guides/examples/medical_structured_abstract.md +313 -0
- package/skills/shared/venue-guides/examples/nature_abstract_examples.md +213 -0
- package/skills/shared/venue-guides/examples/neurips_introduction_example.md +245 -0
- package/skills/shared/venue-guides/journals_formatting.md +486 -0
- package/skills/shared/venue-guides/medical_journal_styles.md +535 -0
- package/skills/shared/venue-guides/ml_conference_style.md +556 -0
- package/skills/shared/venue-guides/nature_science_style.md +405 -0
- package/skills/shared/venue-guides/reviewer_expectations.md +417 -0
- package/skills/shared/venue-guides/venue_writing_styles.md +321 -0
- package/skills/split-pdf/SKILL.md +172 -0
- package/skills/split-pdf/methodology.md +48 -0
- package/skills/sync-notion/SKILL.md +93 -0
- package/skills/system-audit/SKILL.md +157 -0
- package/skills/system-audit/references/sub-agent-prompts.md +294 -0
- package/skills/task-management/SKILL.md +131 -0
- package/skills/update-focus/SKILL.md +204 -0
- package/skills/update-project-doc/SKILL.md +194 -0
- package/skills/validate-bib/SKILL.md +242 -0
- package/skills/validate-bib/references/council-mode.md +34 -0
- package/skills/validate-bib/references/deep-verify.md +71 -0
- package/skills/validate-bib/references/openalex-verification.md +45 -0
- package/skills/validate-bib/references/preprint-check.md +31 -0
- package/skills/validate-bib/references/report-template.md +62 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Skip on non-Mac environments (cloud, mobile)
|
|
3
|
+
source "$(dirname "$0")/resolve-task-mgmt.sh" || exit 0
|
|
4
|
+
# resume-context-loader.sh
|
|
5
|
+
# SessionStart hook (resume) — surfaces current focus and latest session log
|
|
6
|
+
# so Claude picks up where things left off.
|
|
7
|
+
FOCUS_FILE="$TASK_MGMT/.context/current-focus.md"
|
|
8
|
+
LOG_DIR="$TASK_MGMT/log"
|
|
9
|
+
|
|
10
|
+
CONTEXT=""
|
|
11
|
+
|
|
12
|
+
# Read current focus
|
|
13
|
+
if [ -f "$FOCUS_FILE" ]; then
|
|
14
|
+
FOCUS=$(head -20 "$FOCUS_FILE")
|
|
15
|
+
CONTEXT="## Current Focus\n$FOCUS"
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Load project planning state (if in a project with orchestration)
|
|
19
|
+
CWD="$(pwd)"
|
|
20
|
+
if [ "$CWD" != "$TASK_MGMT" ]; then
|
|
21
|
+
PROJECT_ROOT=$(git -C "$CWD" rev-parse --show-toplevel 2>/dev/null || echo "$CWD")
|
|
22
|
+
if [ -f "$PROJECT_ROOT/.planning/state.md" ]; then
|
|
23
|
+
STATE=$(head -30 "$PROJECT_ROOT/.planning/state.md")
|
|
24
|
+
CONTEXT="$CONTEXT\n\n## Project Planning State\n$STATE"
|
|
25
|
+
fi
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Find latest session log (not plans, not compact saves)
|
|
29
|
+
if [ -d "$LOG_DIR" ]; then
|
|
30
|
+
LATEST_LOG=$(find "$LOG_DIR" -maxdepth 1 -name "*.md" -type f | sort -r | head -1)
|
|
31
|
+
if [ -n "$LATEST_LOG" ] && [ -f "$LATEST_LOG" ]; then
|
|
32
|
+
LOG_SUMMARY=$(head -30 "$LATEST_LOG")
|
|
33
|
+
CONTEXT="$CONTEXT\n\n## Latest Session Log ($(basename "$LATEST_LOG"))\n$LOG_SUMMARY"
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [ -z "$CONTEXT" ]; then
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Escape for JSON
|
|
42
|
+
CONTEXT_ESCAPED=$(echo -e "$CONTEXT" | jq -Rs .)
|
|
43
|
+
|
|
44
|
+
cat <<EOF
|
|
45
|
+
{
|
|
46
|
+
"hookSpecificOutput": {
|
|
47
|
+
"hookEventName": "SessionStart",
|
|
48
|
+
"additionalContext": $CONTEXT_ESCAPED
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
EOF
|
|
52
|
+
|
|
53
|
+
exit 0
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Skip on non-Mac environments (cloud, mobile)
|
|
3
|
+
source "$(dirname "$0")/resolve-task-mgmt.sh" || exit 0
|
|
4
|
+
# startup-context-loader.sh
|
|
5
|
+
# SessionStart hook (startup) — auto-detects and surfaces project documentation
|
|
6
|
+
# on fresh sessions in any project, so Claude doesn't waste tokens searching.
|
|
7
|
+
CWD="$(pwd)"
|
|
8
|
+
CONTEXT=""
|
|
9
|
+
MAX_LINES=30
|
|
10
|
+
|
|
11
|
+
add_section() {
|
|
12
|
+
local title="$1"
|
|
13
|
+
local file="$2"
|
|
14
|
+
local lines="${3:-$MAX_LINES}"
|
|
15
|
+
|
|
16
|
+
if [ -f "$file" ]; then
|
|
17
|
+
local content
|
|
18
|
+
content=$(head -"$lines" "$file")
|
|
19
|
+
if [ -n "$content" ]; then
|
|
20
|
+
if [ -n "$CONTEXT" ]; then
|
|
21
|
+
CONTEXT="$CONTEXT\n\n"
|
|
22
|
+
fi
|
|
23
|
+
CONTEXT="${CONTEXT}## ${title}\n${content}"
|
|
24
|
+
fi
|
|
25
|
+
fi
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# --- Current focus (Task Management context) ---
|
|
29
|
+
add_section "Current Focus" "$TASK_MGMT/.context/current-focus.md" 25
|
|
30
|
+
|
|
31
|
+
# --- Project index (Task Management context) ---
|
|
32
|
+
add_section "Project Index" "$TASK_MGMT/.context/projects/_index.md" 40
|
|
33
|
+
|
|
34
|
+
# --- Resolve project root (handles subdirectory CWDs) ---
|
|
35
|
+
if [ "$CWD" != "$TASK_MGMT" ]; then
|
|
36
|
+
PROJECT_ROOT=$(git -C "$CWD" rev-parse --show-toplevel 2>/dev/null || echo "$CWD")
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# --- MEMORY.md (structured knowledge tables and [LEARN] corrections) ---
|
|
40
|
+
if [ "$CWD" = "$TASK_MGMT" ]; then
|
|
41
|
+
add_section "MEMORY.md" "$TASK_MGMT/MEMORY.md" 30
|
|
42
|
+
else
|
|
43
|
+
add_section "Project MEMORY" "$PROJECT_ROOT/MEMORY.md" 30
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# --- Project-specific docs (if not in Task Management itself) ---
|
|
47
|
+
if [ "$CWD" != "$TASK_MGMT" ]; then
|
|
48
|
+
|
|
49
|
+
add_section "Project README" "$PROJECT_ROOT/README.md" 40
|
|
50
|
+
|
|
51
|
+
# Check for project-specific context files
|
|
52
|
+
add_section "Project Focus" "$PROJECT_ROOT/.context/current-focus.md" 25
|
|
53
|
+
|
|
54
|
+
# Check for project planning state
|
|
55
|
+
add_section "Project Planning State" "$PROJECT_ROOT/.planning/state.md" 30
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# --- Latest session log ---
|
|
59
|
+
if [ -d "$TASK_MGMT/log" ]; then
|
|
60
|
+
LATEST_LOG=$(find "$TASK_MGMT/log" -maxdepth 1 -name "*.md" -type f | sort -r | head -1)
|
|
61
|
+
add_section "Latest Session Log ($(basename "$LATEST_LOG" 2>/dev/null))" "$LATEST_LOG" 30
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# --- Latest plan (if any) ---
|
|
65
|
+
if [ -d "$TASK_MGMT/log/plans" ]; then
|
|
66
|
+
LATEST_PLAN=$(find "$TASK_MGMT/log/plans" -maxdepth 1 -name "*.md" -type f | sort -r | head -1)
|
|
67
|
+
add_section "Latest Plan ($(basename "$LATEST_PLAN" 2>/dev/null))" "$LATEST_PLAN" 25
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# --- Skill observations: weekly review check ---
|
|
71
|
+
REVIEW_DATE_FILE="$HOME/.claude/skill-observations/last-review-date.txt"
|
|
72
|
+
if [ -f "$REVIEW_DATE_FILE" ]; then
|
|
73
|
+
LAST_REVIEW=$(cat "$REVIEW_DATE_FILE" | tr -d '\n')
|
|
74
|
+
DAYS_SINCE=$(( ( $(date +%s) - $(date -j -f "%Y-%m-%d" "$LAST_REVIEW" +%s 2>/dev/null || echo 0) ) / 86400 ))
|
|
75
|
+
if [ "$DAYS_SINCE" -ge 7 ] 2>/dev/null; then
|
|
76
|
+
if [ -n "$CONTEXT" ]; then
|
|
77
|
+
CONTEXT="$CONTEXT\n\n"
|
|
78
|
+
fi
|
|
79
|
+
CONTEXT="${CONTEXT}## Skill Observations\nWeekly review overdue (last: ${LAST_REVIEW}, ${DAYS_SINCE} days ago). Consider running \`/skill-health\` to review."
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
if [ -z "$CONTEXT" ]; then
|
|
84
|
+
exit 0
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Add a header
|
|
88
|
+
CONTEXT="# Session Context (auto-loaded)\nRead these docs — do NOT re-search for this information.\n\n${CONTEXT}"
|
|
89
|
+
|
|
90
|
+
# Escape for JSON
|
|
91
|
+
CONTEXT_ESCAPED=$(echo -e "$CONTEXT" | jq -Rs .)
|
|
92
|
+
|
|
93
|
+
cat <<EOF
|
|
94
|
+
{
|
|
95
|
+
"hookSpecificOutput": {
|
|
96
|
+
"hookEventName": "SessionStart",
|
|
97
|
+
"additionalContext": $CONTEXT_ESCAPED
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
EOF
|
|
101
|
+
|
|
102
|
+
exit 0
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flonat-research",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Claude Code infrastructure for academic research — skills, agents, hooks, and rules for LaTeX, bibliography, proofreading, and project management workflows.",
|
|
5
|
+
"author": "Florian Burnat",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/flonat/claude-research.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/flonat/claude-research",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claude-code",
|
|
14
|
+
"academic",
|
|
15
|
+
"research",
|
|
16
|
+
"latex",
|
|
17
|
+
"bibliography",
|
|
18
|
+
"proofreading",
|
|
19
|
+
"phd",
|
|
20
|
+
"skills",
|
|
21
|
+
"agents",
|
|
22
|
+
"hooks"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"claude-research-setup": "scripts/setup.sh"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"postinstall": "echo '\\nRun: npx claude-research-setup\\nto create symlinks for skills, agents, hooks, and rules.\\n'",
|
|
29
|
+
"setup": "bash scripts/setup.sh"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"skills/",
|
|
33
|
+
"hooks/",
|
|
34
|
+
".claude/agents/",
|
|
35
|
+
".claude/rules/",
|
|
36
|
+
".claude/settings.json",
|
|
37
|
+
".context/",
|
|
38
|
+
".scripts/",
|
|
39
|
+
".mcp-server-biblio/",
|
|
40
|
+
"packages/",
|
|
41
|
+
"docs/",
|
|
42
|
+
"scripts/setup.sh",
|
|
43
|
+
"CLAUDE.md",
|
|
44
|
+
"MEMORY.md",
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"README.md"
|
|
47
|
+
],
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Claude Code Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, ready_for_review, reopened]
|
|
6
|
+
# Optional: Only run on specific file changes
|
|
7
|
+
# paths:
|
|
8
|
+
# - "src/**/*.ts"
|
|
9
|
+
# - "src/**/*.tsx"
|
|
10
|
+
# - "src/**/*.js"
|
|
11
|
+
# - "src/**/*.jsx"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude-review:
|
|
15
|
+
# Optional: Filter by PR author
|
|
16
|
+
# if: |
|
|
17
|
+
# github.event.pull_request.user.login == 'external-contributor' ||
|
|
18
|
+
# github.event.pull_request.user.login == 'new-developer' ||
|
|
19
|
+
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
|
20
|
+
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
pull-requests: read
|
|
25
|
+
issues: read
|
|
26
|
+
id-token: write
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout repository
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 1
|
|
33
|
+
|
|
34
|
+
- name: Run Claude Code Review
|
|
35
|
+
id: claude-review
|
|
36
|
+
uses: anthropics/claude-code-action@v1
|
|
37
|
+
with:
|
|
38
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
39
|
+
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
|
40
|
+
plugins: 'code-review@claude-code-plugins'
|
|
41
|
+
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
|
42
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
43
|
+
# or https://code.claude.com/docs/en/cli-reference for available options
|
|
44
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
if: |
|
|
16
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
17
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
19
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
pull-requests: read
|
|
24
|
+
issues: read
|
|
25
|
+
id-token: write
|
|
26
|
+
actions: read # Required for Claude to read CI results on PRs
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout repository
|
|
29
|
+
uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
|
|
33
|
+
- name: Run Claude Code
|
|
34
|
+
id: claude
|
|
35
|
+
uses: anthropics/claude-code-action@v1
|
|
36
|
+
with:
|
|
37
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
38
|
+
|
|
39
|
+
# This is an optional setting that allows Claude to read CI results on PRs
|
|
40
|
+
additional_permissions: |
|
|
41
|
+
actions: read
|
|
42
|
+
|
|
43
|
+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
|
44
|
+
# prompt: 'Update the pull request description to include a summary of changes.'
|
|
45
|
+
|
|
46
|
+
# Optional: Add claude_args to customize behavior and configuration
|
|
47
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
48
|
+
# or https://code.claude.com/docs/en/cli-reference for available options
|
|
49
|
+
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
|
50
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# cli-council
|
|
2
|
+
|
|
3
|
+
Local multi-model council deliberation using CLI tools. Runs Gemini CLI, Codex CLI, and Claude Code in parallel to get diverse AI perspectives on any question — using your existing subscriptions, not per-token API costs.
|
|
4
|
+
|
|
5
|
+
Part of [claude-research](https://github.com/user/claude-research) infrastructure.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
Three-stage deliberation protocol (inspired by [Karpathy's llm-council](https://github.com/karpathy/llm-council)):
|
|
10
|
+
|
|
11
|
+
1. **Stage 1: Independent Assessments** — Each CLI tool independently answers the same question in parallel
|
|
12
|
+
2. **Stage 2: Anonymised Peer Review** — Each tool reviews all assessments (anonymised as "Assessment A/B/C") and ranks them
|
|
13
|
+
3. **Stage 3: Chairman Synthesis** — One tool reads everything and produces a single synthesised answer
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Install the CLI tools you want to use:
|
|
18
|
+
|
|
19
|
+
| Backend | Install | Auth |
|
|
20
|
+
|---------|---------|------|
|
|
21
|
+
| **Gemini CLI** | `npm install -g @google/generative-ai-cli` | `gemini` (Google account) |
|
|
22
|
+
| **Codex CLI** | `npm install -g @openai/codex-cli` | `codex login` (ChatGPT Plus) |
|
|
23
|
+
| **Claude Code** | `npm install -g @anthropic-ai/claude-code` | `claude` (Claude Pro) |
|
|
24
|
+
|
|
25
|
+
Check availability:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m cli_council --check
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### CLI
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Simple question
|
|
37
|
+
python -m cli_council "What are the tradeoffs between microservices and monoliths?"
|
|
38
|
+
|
|
39
|
+
# With context file and markdown output
|
|
40
|
+
python -m cli_council \
|
|
41
|
+
--prompt-file question.txt \
|
|
42
|
+
--context-file project-context.md \
|
|
43
|
+
--output-md council-report.md
|
|
44
|
+
|
|
45
|
+
# Pipe from stdin
|
|
46
|
+
echo "Review this research design for causal identification issues" | python -m cli_council
|
|
47
|
+
|
|
48
|
+
# Select specific backends
|
|
49
|
+
python -m cli_council --backends gemini,claude "Best approach for time-series forecasting?"
|
|
50
|
+
|
|
51
|
+
# Change chairman
|
|
52
|
+
python -m cli_council --chairman codex "Evaluate this argument..."
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Python API
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import asyncio
|
|
59
|
+
from cli_council import CouncilRunner
|
|
60
|
+
|
|
61
|
+
runner = CouncilRunner(
|
|
62
|
+
backends=["gemini", "codex", "claude"],
|
|
63
|
+
chairman="claude",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
result = asyncio.run(runner.run(
|
|
67
|
+
"What are the key risks in this experimental design?",
|
|
68
|
+
system_context="We're studying the effect of AI assistance on decision quality...",
|
|
69
|
+
))
|
|
70
|
+
|
|
71
|
+
print(result.synthesis)
|
|
72
|
+
for a in result.assessments:
|
|
73
|
+
print(f"{a.label} ({a.backend}): {a.text[:100]}...")
|
|
74
|
+
print(f"Total time: {result.meta.total_ms}ms")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Output
|
|
78
|
+
|
|
79
|
+
Returns a `CouncilResult` with:
|
|
80
|
+
|
|
81
|
+
- `synthesis` — Chairman's final synthesised answer
|
|
82
|
+
- `assessments` — List of individual Stage 1 responses
|
|
83
|
+
- `peer_reviews` — List of Stage 2 peer reviews with rankings
|
|
84
|
+
- `meta` — Timing, backends used, errors
|
|
85
|
+
|
|
86
|
+
## Relationship to llm-council
|
|
87
|
+
|
|
88
|
+
| | cli-council | [llm-council](https://github.com/user/llm-council) |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| **Transport** | Local CLI subprocesses | OpenRouter API |
|
|
91
|
+
| **Cost** | Subscription-included | Per-token |
|
|
92
|
+
| **Output** | Free-form text | Structured JSON |
|
|
93
|
+
| **Best for** | Ad-hoc reviews, research, quick opinions | Automated pipelines, structured reports |
|
|
94
|
+
| **Models** | Whatever your CLIs support | Full OpenRouter catalogue |
|
|
95
|
+
|
|
96
|
+
Both implement the same 3-stage protocol. Use cli-council for interactive work, llm-council for programmatic integration.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cli-council"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Local multi-model council deliberation via CLI tools (Gemini CLI, Codex CLI, Claude Code)"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "the user" },
|
|
10
|
+
]
|
|
11
|
+
keywords = ["llm", "council", "multi-model", "cli", "gemini", "codex", "claude"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"pydantic>=2.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/user/cli-council"
|
|
29
|
+
Repository = "https://github.com/user/cli-council"
|
|
30
|
+
Issues = "https://github.com/user/cli-council/issues"
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=8.0",
|
|
35
|
+
"pytest-asyncio>=0.23",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["hatchling"]
|
|
40
|
+
build-backend = "hatchling.build"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.build.targets.wheel]
|
|
43
|
+
packages = ["src/cli_council"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""cli-council: Local multi-model council deliberation via CLI tools."""
|
|
2
|
+
|
|
3
|
+
from cli_council.checkpoint import CouncilCheckpointer
|
|
4
|
+
from cli_council.council import CouncilRunner
|
|
5
|
+
from cli_council.models import (
|
|
6
|
+
Assessment,
|
|
7
|
+
CouncilMeta,
|
|
8
|
+
CouncilResult,
|
|
9
|
+
PeerReview,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"CouncilCheckpointer",
|
|
14
|
+
"CouncilRunner",
|
|
15
|
+
"Assessment",
|
|
16
|
+
"CouncilMeta",
|
|
17
|
+
"CouncilResult",
|
|
18
|
+
"PeerReview",
|
|
19
|
+
]
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""CLI entry point: python -m cli_council."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import asyncio
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from cli_council.config import DEFAULT_CHAIRMAN, DEFAULT_COUNCIL_BACKENDS
|
|
13
|
+
from cli_council.council import CouncilRunner
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _parse_args() -> argparse.Namespace:
|
|
17
|
+
parser = argparse.ArgumentParser(
|
|
18
|
+
prog="cli-council",
|
|
19
|
+
description="Run a multi-model council deliberation using local CLI tools.",
|
|
20
|
+
)
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"prompt",
|
|
23
|
+
nargs="?",
|
|
24
|
+
help="The question or task for the council. If omitted, reads from stdin.",
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--prompt-file",
|
|
28
|
+
type=Path,
|
|
29
|
+
help="Read prompt from a file instead of argument/stdin.",
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"--context-file",
|
|
33
|
+
type=Path,
|
|
34
|
+
help="File with system context (project description, constraints, etc.).",
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--backends",
|
|
38
|
+
type=str,
|
|
39
|
+
default=",".join(DEFAULT_COUNCIL_BACKENDS),
|
|
40
|
+
help=f"Comma-separated list of backends (default: {','.join(DEFAULT_COUNCIL_BACKENDS)}).",
|
|
41
|
+
)
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--chairman",
|
|
44
|
+
type=str,
|
|
45
|
+
default=DEFAULT_CHAIRMAN,
|
|
46
|
+
help=f"Backend for Stage 3 synthesis (default: {DEFAULT_CHAIRMAN}).",
|
|
47
|
+
)
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--timeout",
|
|
50
|
+
type=int,
|
|
51
|
+
default=120,
|
|
52
|
+
help="Timeout per backend call in seconds (default: 120).",
|
|
53
|
+
)
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"--output",
|
|
56
|
+
type=Path,
|
|
57
|
+
help="Write JSON result to file (default: stdout).",
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--output-md",
|
|
61
|
+
type=Path,
|
|
62
|
+
help="Write markdown report to file.",
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"--cwd",
|
|
66
|
+
type=str,
|
|
67
|
+
help="Working directory for CLI tools (default: current directory).",
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--check",
|
|
71
|
+
action="store_true",
|
|
72
|
+
help="Check which backends are available and exit.",
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"-v", "--verbose",
|
|
76
|
+
action="store_true",
|
|
77
|
+
help="Enable verbose logging.",
|
|
78
|
+
)
|
|
79
|
+
return parser.parse_args()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _format_markdown(result) -> str:
|
|
83
|
+
"""Format a CouncilResult as a readable markdown report."""
|
|
84
|
+
lines = ["# Council Report\n"]
|
|
85
|
+
|
|
86
|
+
lines.append("## Synthesis\n")
|
|
87
|
+
lines.append(result.synthesis)
|
|
88
|
+
lines.append("")
|
|
89
|
+
|
|
90
|
+
lines.append("## Individual Assessments\n")
|
|
91
|
+
for a in result.assessments:
|
|
92
|
+
lines.append(f"### {a.label} ({a.backend}, {a.model})\n")
|
|
93
|
+
lines.append(a.text)
|
|
94
|
+
lines.append(f"\n*Elapsed: {a.elapsed_ms}ms*\n")
|
|
95
|
+
|
|
96
|
+
if result.peer_reviews:
|
|
97
|
+
lines.append("## Peer Reviews\n")
|
|
98
|
+
for r in result.peer_reviews:
|
|
99
|
+
lines.append(f"### Review by {r.backend} ({r.model})\n")
|
|
100
|
+
lines.append(r.review_text)
|
|
101
|
+
if r.parsed_ranking:
|
|
102
|
+
lines.append(f"\n**Ranking:** {' > '.join(r.parsed_ranking)}")
|
|
103
|
+
lines.append(f"\n*Elapsed: {r.elapsed_ms}ms*\n")
|
|
104
|
+
|
|
105
|
+
lines.append("## Metadata\n")
|
|
106
|
+
meta = result.meta
|
|
107
|
+
lines.append(f"- **Backends:** {', '.join(meta.backends_used)}")
|
|
108
|
+
lines.append(f"- **Chairman:** {meta.chairman_backend}")
|
|
109
|
+
lines.append(f"- **Timing:** Stage 1: {meta.stage1_ms}ms, Stage 2: {meta.stage2_ms}ms, Stage 3: {meta.stage3_ms}ms, Total: {meta.total_ms}ms")
|
|
110
|
+
if meta.errors:
|
|
111
|
+
lines.append(f"- **Errors:** {'; '.join(meta.errors)}")
|
|
112
|
+
|
|
113
|
+
return "\n".join(lines)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def main() -> None:
|
|
117
|
+
args = _parse_args()
|
|
118
|
+
|
|
119
|
+
logging.basicConfig(
|
|
120
|
+
level=logging.DEBUG if args.verbose else logging.WARNING,
|
|
121
|
+
format="%(levelname)s %(name)s: %(message)s",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# --check mode
|
|
125
|
+
if args.check:
|
|
126
|
+
backends = args.backends.split(",")
|
|
127
|
+
runner = CouncilRunner(backends=backends)
|
|
128
|
+
available = runner.available_backends()
|
|
129
|
+
print(f"Requested: {', '.join(backends)}")
|
|
130
|
+
print(f"Available: {', '.join(available) or 'none'}")
|
|
131
|
+
missing = set(backends) - set(available)
|
|
132
|
+
if missing:
|
|
133
|
+
print(f"Missing: {', '.join(missing)}")
|
|
134
|
+
sys.exit(1)
|
|
135
|
+
print("All backends available.")
|
|
136
|
+
sys.exit(0)
|
|
137
|
+
|
|
138
|
+
# Resolve prompt
|
|
139
|
+
prompt: str | None = args.prompt
|
|
140
|
+
if args.prompt_file:
|
|
141
|
+
prompt = args.prompt_file.read_text().strip()
|
|
142
|
+
elif prompt is None:
|
|
143
|
+
if not sys.stdin.isatty():
|
|
144
|
+
prompt = sys.stdin.read().strip()
|
|
145
|
+
else:
|
|
146
|
+
print("Error: No prompt provided. Use positional arg, --prompt-file, or pipe via stdin.", file=sys.stderr)
|
|
147
|
+
sys.exit(1)
|
|
148
|
+
|
|
149
|
+
if not prompt:
|
|
150
|
+
print("Error: Empty prompt.", file=sys.stderr)
|
|
151
|
+
sys.exit(1)
|
|
152
|
+
|
|
153
|
+
# Resolve context
|
|
154
|
+
system_context = ""
|
|
155
|
+
if args.context_file:
|
|
156
|
+
system_context = args.context_file.read_text().strip()
|
|
157
|
+
|
|
158
|
+
# Run council
|
|
159
|
+
backends = [b.strip() for b in args.backends.split(",")]
|
|
160
|
+
runner = CouncilRunner(
|
|
161
|
+
backends=backends,
|
|
162
|
+
chairman=args.chairman,
|
|
163
|
+
timeout=args.timeout,
|
|
164
|
+
cwd=args.cwd,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
result = asyncio.run(runner.run(prompt, system_context=system_context))
|
|
168
|
+
|
|
169
|
+
# Output JSON
|
|
170
|
+
result_json = result.model_dump()
|
|
171
|
+
if args.output:
|
|
172
|
+
args.output.write_text(json.dumps(result_json, indent=2) + "\n")
|
|
173
|
+
print(f"JSON result written to {args.output}", file=sys.stderr)
|
|
174
|
+
else:
|
|
175
|
+
print(json.dumps(result_json, indent=2))
|
|
176
|
+
|
|
177
|
+
# Output markdown
|
|
178
|
+
if args.output_md:
|
|
179
|
+
md = _format_markdown(result)
|
|
180
|
+
args.output_md.write_text(md + "\n")
|
|
181
|
+
print(f"Markdown report written to {args.output_md}", file=sys.stderr)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
if __name__ == "__main__":
|
|
185
|
+
main()
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""CLI backend implementations."""
|
|
2
|
+
|
|
3
|
+
from cli_council.backends.base import CLIBackend
|
|
4
|
+
from cli_council.backends.claude import ClaudeBackend
|
|
5
|
+
from cli_council.backends.codex import CodexBackend
|
|
6
|
+
from cli_council.backends.gemini import GeminiBackend
|
|
7
|
+
|
|
8
|
+
__all__ = ["CLIBackend", "ClaudeBackend", "CodexBackend", "GeminiBackend"]
|