frontier-council 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ # History (may contain personal questions)
2
+ council_history.jsonl
3
+
4
+ # Local Claude config
5
+ .claude/
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ dist/
11
+ build/
12
+ *.egg-info/
13
+
14
+ # IDE
15
+ .vscode/
16
+ .idea/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Terry Li
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,10 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontier-council
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Multi-model deliberation for important decisions. 5 frontier LLMs debate, then a judge synthesizes consensus.
5
- Project-URL: Homepage, https://github.com/terry-li-hm/skills
5
+ Project-URL: Homepage, https://github.com/terry-li-hm/frontier-council
6
+ Project-URL: Repository, https://github.com/terry-li-hm/frontier-council
7
+ Project-URL: Issues, https://github.com/terry-li-hm/frontier-council/issues
6
8
  Author-email: Terry Li <terry.li.hm@gmail.com>
7
9
  License-Expression: MIT
10
+ License-File: LICENSE
8
11
  Keywords: ai,council,debate,deliberation,frontier,llm,multi-model,openrouter
9
12
  Classifier: Development Status :: 4 - Beta
10
13
  Classifier: Environment :: Console
@@ -77,8 +80,13 @@ frontier-council "Career question" --output transcript.md
77
80
 
78
81
  # Share via GitHub Gist
79
82
  frontier-council "Important decision" --share
83
+
84
+ # List past sessions
85
+ frontier-council --sessions
80
86
  ```
81
87
 
88
+ All sessions are auto-saved to `~/.frontier-council/sessions/` for later review.
89
+
82
90
  ## Options
83
91
 
84
92
  | Flag | Description |
@@ -93,6 +101,8 @@ frontier-council "Important decision" --share
93
101
  | `--persona TEXT` | Context about the person asking |
94
102
  | `--advocate N` | Which speaker (1-5) should be devil's advocate (default: random) |
95
103
  | `--quiet` | Suppress progress output |
104
+ | `--sessions` | List recent saved sessions |
105
+ | `--no-save` | Don't auto-save transcript to ~/.frontier-council/sessions/ |
96
106
 
97
107
  ## How It Works
98
108
 
@@ -57,8 +57,13 @@ frontier-council "Career question" --output transcript.md
57
57
 
58
58
  # Share via GitHub Gist
59
59
  frontier-council "Important decision" --share
60
+
61
+ # List past sessions
62
+ frontier-council --sessions
60
63
  ```
61
64
 
65
+ All sessions are auto-saved to `~/.frontier-council/sessions/` for later review.
66
+
62
67
  ## Options
63
68
 
64
69
  | Flag | Description |
@@ -73,6 +78,8 @@ frontier-council "Important decision" --share
73
78
  | `--persona TEXT` | Context about the person asking |
74
79
  | `--advocate N` | Which speaker (1-5) should be devil's advocate (default: random) |
75
80
  | `--quiet` | Suppress progress output |
81
+ | `--sessions` | List recent saved sessions |
82
+ | `--no-save` | Don't auto-save transcript to ~/.frontier-council/sessions/ |
76
83
 
77
84
  ## How It Works
78
85
 
@@ -1,6 +1,6 @@
1
1
  """Frontier Council - Multi-model deliberation for important decisions."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.1.2"
4
4
 
5
5
  from .council import (
6
6
  run_council,
@@ -4,11 +4,27 @@ import argparse
4
4
  import json
5
5
  import os
6
6
  import random
7
+ import re
7
8
  import subprocess
8
9
  import sys
9
10
  from datetime import datetime
10
11
  from pathlib import Path
11
12
 
13
+
14
+ def get_sessions_dir() -> Path:
15
+ """Get the sessions directory, creating if needed."""
16
+ sessions_dir = Path.home() / ".frontier-council" / "sessions"
17
+ sessions_dir.mkdir(parents=True, exist_ok=True)
18
+ return sessions_dir
19
+
20
+
21
+ def slugify(text: str, max_len: int = 40) -> str:
22
+ """Convert text to a filename-safe slug."""
23
+ text = text.lower()
24
+ text = re.sub(r'[^\w\s-]', '', text)
25
+ text = re.sub(r'[\s_-]+', '-', text)
26
+ return text[:max_len].strip('-')
27
+
12
28
  from .council import (
13
29
  COUNCIL,
14
30
  detect_social_context,
@@ -78,8 +94,33 @@ Examples:
78
94
  choices=[1, 2, 3, 4, 5],
79
95
  help="Which speaker (1-5) should be devil's advocate (default: random)",
80
96
  )
97
+ parser.add_argument(
98
+ "--no-save",
99
+ action="store_true",
100
+ help="Don't auto-save transcript to ~/.frontier-council/sessions/",
101
+ )
102
+ parser.add_argument(
103
+ "--sessions",
104
+ action="store_true",
105
+ help="List recent sessions and exit",
106
+ )
81
107
  args = parser.parse_args()
82
108
 
109
+ # Handle --sessions flag
110
+ if args.sessions:
111
+ sessions_dir = get_sessions_dir()
112
+ sessions = sorted(sessions_dir.glob("*.md"), key=lambda p: p.stat().st_mtime, reverse=True)
113
+ if not sessions:
114
+ print("No sessions found.")
115
+ else:
116
+ print(f"Sessions in {sessions_dir}:\n")
117
+ for s in sessions[:20]: # Show last 20
118
+ mtime = datetime.fromtimestamp(s.stat().st_mtime).strftime("%Y-%m-%d %H:%M")
119
+ print(f" {mtime} {s.name}")
120
+ if len(sessions) > 20:
121
+ print(f"\n ... and {len(sessions) - 20} more")
122
+ sys.exit(0)
123
+
83
124
  # Auto-detect social context if not explicitly set
84
125
  social_mode = args.social or detect_social_context(args.question)
85
126
  if social_mode and not args.social and not args.quiet:
@@ -153,12 +194,38 @@ Examples:
153
194
  print("=" * 60)
154
195
  print()
155
196
 
156
- # Save transcript
197
+ # Save transcript to user-specified location
157
198
  if args.output:
158
199
  Path(args.output).write_text(transcript)
159
200
  if not args.quiet:
160
201
  print(f"Transcript saved to: {args.output}")
161
202
 
203
+ # Auto-save to sessions directory
204
+ session_path = None
205
+ if not args.no_save:
206
+ timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
207
+ slug = slugify(args.question)
208
+ filename = f"{timestamp}-{slug}.md"
209
+ session_path = get_sessions_dir() / filename
210
+
211
+ # Build full session content with metadata header
212
+ session_content = f"""# Council Session
213
+
214
+ **Question:** {args.question}
215
+ **Date:** {datetime.now().strftime("%Y-%m-%d %H:%M")}
216
+ **Rounds:** {args.rounds}
217
+ **Mode:** {"named" if args.named else "anonymous"}, {"blind" if use_blind else "no blind"}{", social" if social_mode else ""}
218
+ {f"**Context:** {args.context}" if args.context else ""}
219
+ {f"**Persona:** {args.persona}" if args.persona else ""}
220
+
221
+ ---
222
+
223
+ {transcript}
224
+ """
225
+ session_path.write_text(session_content)
226
+ if not args.quiet:
227
+ print(f"Session saved to: {session_path}")
228
+
162
229
  # Share via gist
163
230
  gist_url = None
164
231
  if args.share:
@@ -190,10 +257,11 @@ Examples:
190
257
  print("Error: 'gh' CLI not found. Install with: brew install gh", file=sys.stderr)
191
258
 
192
259
  # Log to history
193
- history_file = Path(__file__).parent.parent / "council_history.jsonl"
260
+ history_file = get_sessions_dir().parent / "history.jsonl"
194
261
  log_entry = {
195
262
  "timestamp": datetime.now().isoformat(),
196
263
  "question": args.question[:200],
264
+ "session": str(session_path) if session_path else None,
197
265
  "gist": gist_url,
198
266
  "context": args.context,
199
267
  "rounds": args.rounds,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "frontier-council"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "Multi-model deliberation for important decisions. 5 frontier LLMs debate, then a judge synthesizes consensus."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -27,7 +27,9 @@ dependencies = [
27
27
  frontier-council = "frontier_council.cli:main"
28
28
 
29
29
  [project.urls]
30
- Homepage = "https://github.com/terry-li-hm/skills"
30
+ Homepage = "https://github.com/terry-li-hm/frontier-council"
31
+ Repository = "https://github.com/terry-li-hm/frontier-council"
32
+ Issues = "https://github.com/terry-li-hm/frontier-council/issues"
31
33
 
32
34
  [build-system]
33
35
  requires = ["hatchling"]
@@ -1,87 +0,0 @@
1
- ---
2
- name: llm-council
3
- description: LLM Council with 5 frontier models (Opus 4.5, GPT-5.2, Gemini 3 Pro, Grok 4, Kimi K2.5). Models deliberate on a question, each seeing previous responses, then a judge synthesizes consensus. Use for important decisions needing diverse AI perspectives.
4
- ---
5
-
6
- # LLM Council
7
-
8
- 5 frontier models deliberate on a question. Unlike `/ask-llms` which shows parallel responses, this creates an actual debate where models see and respond to previous speakers, followed by a judge synthesizing the consensus.
9
-
10
- ## When to Use
11
-
12
- - Important decisions that benefit from diverse perspectives
13
- - You want models to actually debate, not just answer in parallel
14
- - You need a synthesized recommendation, not raw comparison
15
- - Exploring trade-offs where different viewpoints matter
16
-
17
- ## When NOT to Use
18
-
19
- - **Thinking out loud** — exploratory discussions where you're still forming the question
20
- - **Claude has good context** — if we've been discussing the topic, direct conversation is faster
21
- - **Personal preference** — council excels at objective trade-offs, not "what would I enjoy"
22
- - **Already converged** — if discussion reached a conclusion, council just validates
23
- - **Speed matters** — takes 60-90s and costs several dollars
24
-
25
- ## Prerequisites
26
-
27
- ```bash
28
- export OPENROUTER_API_KEY=sk-or-v1-... # Required
29
- export GOOGLE_API_KEY=AIza... # Optional: Gemini fallback
30
- export MOONSHOT_API_KEY=sk-... # Optional: Kimi fallback
31
- ```
32
-
33
- ## Instructions
34
-
35
- ### Step 1: Get the Question
36
-
37
- Ask the user what question they want the council to deliberate, or use the question they provided.
38
-
39
- ### Step 2: Run the Council
40
-
41
- ```bash
42
- llm-council "Should we use microservices or a monolith for this project?"
43
- ```
44
-
45
- **Common options:**
46
- ```bash
47
- llm-council "question" --social # Interview/networking questions
48
- llm-council "question" --persona "context" # Add personal context
49
- llm-council "question" --rounds 3 # More deliberation
50
- llm-council "question" --output file.md # Save transcript
51
- llm-council "question" --share # Upload to secret Gist
52
- ```
53
-
54
- ### Step 3: Review and Critique
55
-
56
- Present the judge's synthesis, then critique it:
57
- - Did the council overcorrect on any point?
58
- - Did they miss obvious scenarios?
59
- - Does the advice fit the user's specific context?
60
- - Any groupthink where everyone agreed too fast?
61
-
62
- ## Prompting Tips
63
-
64
- **For social/conversational contexts** (interview questions, networking, outreach):
65
-
66
- LLMs over-optimize for thoroughness. Add constraints like:
67
- - "Make it feel like a natural conversation"
68
- - "Something you'd actually ask over coffee"
69
- - "Simple and human, not structured and comprehensive"
70
-
71
- **Match context depth to question type:**
72
- - Strategic decisions: provide rich context (full background, constraints, history)
73
- - Social questions: minimal context + clear tone constraints
74
-
75
- **For architecture/design questions:**
76
-
77
- Provide scale and constraints upfront to avoid premature optimization advice:
78
- - "This is a single-user system" (avoids multi-user concerns)
79
- - "We have 500 notes, not 50,000" (avoids scaling infrastructure)
80
- - "Manual processes are acceptable" (avoids automation overkill)
81
-
82
- Without these constraints, council tends to suggest infrastructure for problems that don't exist yet.
83
-
84
- ## See Also
85
-
86
- - Full documentation: `cat /Users/terry/skills/llm-council/README.md`
87
- - Python API available: `from llm_council import run_council`
@@ -1,21 +0,0 @@
1
- {"timestamp": "2026-01-20T20:40:06.696079", "question": "What is 2+2?", "context": null, "rounds": 1, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
2
- {"timestamp": "2026-01-20T21:19:53.101354", "question": "Terry has a persistent Claude Code setup (tmux, Obsidian vault, browser automation, background tasks). He's job hunting as a senior exec (Head of Data Science) being counselled out of a Hong Kong bank", "gist": null, "context": "AI autonomy for job hunting", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
3
- {"timestamp": "2026-01-20T21:21:25.406704", "question": "Terry is job hunting after being counselled out of his Head of Data Science role at a bank in Hong Kong. He's using Claude Code as his AI assistant. Based on Ethan Mollick's insight that AI agents mak", "gist": null, "context": "job hunting strategy for senior data science leader", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
4
- {"timestamp": "2026-01-21T14:49:02.706670", "question": "Should Terry reach out to Kelvin Chan (AGM, Head of Customer Intelligence at BOCHK) and if so, how direct should he be about job opportunities?\n\n**Context about Terry:**\n- Currently AGM & Head of Data", "gist": null, "context": "career networking decision under time pressure", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
5
- {"timestamp": "2026-01-21T15:12:10.947338", "question": "Review this LinkedIn message from Terry to Kelvin Chan. Is it good to send as-is, or does it need refinement?\n\n**The message:**\n'Hi Kelvin, great connecting at the HKMA GenAI Sandbox graduation \u2014 cong", "gist": null, "context": "LinkedIn outreach message review", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
6
- {"timestamp": "2026-01-22T07:52:14.589415", "question": "Terry is about to have his 3rd round interview at Capco (consulting firm) for a Principal Consultant, AI Solution Lead role. The interviewer is Marco Chiu, a Principal Consultant in Data - so a peer i", "gist": null, "context": "peer interview strategy", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
7
- {"timestamp": "2026-01-22T08:05:15.654039", "question": "Terry has a peer interview at Capco with Marco Chiu (Principal Consultant, Data). He's been there 10+ years. Terry wants 1 question to ask at the end.\n\nConstraint: Make it feel like a natural conversa", "gist": null, "context": "peer interview question", "rounds": 1, "blind": false, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
8
- {"timestamp": "2026-01-22T11:47:56.997936", "question": "**Question:** Why is my job application-to-interview conversion rate low, and what should I change?\n\n**Context:**\n\nI'm Terry Li, AGM & Head of Data Science at China CITIC Bank International (Hong Kong", "gist": null, "context": "career strategy for senior data science leader in Hong Kong banking", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
9
- {"timestamp": "2026-01-22T12:31:37.102976", "question": "Context: Terry Li is AGM & Head of Data Science at China CITIC Bank International (small Chinese bank HK subsidiary). He's being counselled out despite strong performance (Very Good ratings, Best Fint", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
10
- {"timestamp": "2026-01-22T13:45:32.943472", "question": "Final check on this LinkedIn reply before sending.\n\nContext: Terry (AGM at smaller bank CITIC, job hunting) is replying to Kelvin Chan (AGM, Head of Customer Intelligence at BOCHK \u2014 bigger tier-1 bank", "gist": null, "context": "networking reply", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
11
- {"timestamp": "2026-01-22T14:16:55.519265", "question": "Given the commoditization of the tech stack (Python + Docker + DB covers most needs) and the rise of AI coding tools, what is the realistic competitive positioning for a senior technical person in Hon", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
12
- {"timestamp": "2026-01-23T15:20:19.552247", "question": "Terry is negotiating a Principal Consultant, AI Solution Lead role at Capco Hong Kong. He needs advice on compensation negotiation strategy.\n\n**Terry's situation:**\n- Currently AGM & Head of Data Scie", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
13
- {"timestamp": "2026-01-23T15:54:31.430621", "question": "Terry is considering accepting a Principal Consultant role at Capco Hong Kong as a 1-2 year 'bridge' strategy before returning to in-house banking. He wants the council to stress-test this plan.\n\n**Th", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
14
- {"timestamp": "2026-01-25T09:12:10.579975", "question": "Should a bank's customer-facing FAQ chatbot use LLM-generated answers (with guardrails) or stick with verbatim pre-approved answers?\n\n## Context\n\nTerry is building a POC chatbot for CITIC Bank Hong Ko", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
15
- {"timestamp": "2026-01-25T19:38:26.635861", "question": "How are AI coding agents (like Claude Code, Cursor, Copilot) affecting the landscape of software development? Consider impacts on: build vs buy economics, vendor relationships, team structures, skill ", "gist": null, "context": "business strategy discussion between banking executives", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
16
- {"timestamp": "2026-01-26T14:12:01.575180", "question": "Gavin Maxwell (Capco recruiter) just messaged Terry on WhatsApp at 1:54 PM today:\n\n'Hi Terry, is your notice period negotiable?'\n'Or will you need to complete two months'\n\nContext:\n- Terry is at offer", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
17
- {"timestamp": "2026-01-27T06:28:25.073503", "question": "Terry is job hunting in Hong Kong (Head of Data Science level, ~HKD 1.78M total comp). He's at offer stage with Capco (consulting firm) \u2014 final round passed Jan 23, recruiter Gavin confirmed Bertie ap", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
18
- {"timestamp": "2026-01-27T12:03:37.851741", "question": "Terry is at offer stage with Capco (consulting firm) for Principal Consultant, AI Solution Lead role in Hong Kong.\n\n**Timeline:**\n- Jan 16: 2nd round interview (Subashini, Regional Lead Analytics & AI", "gist": null, "context": "job negotiation strategy", "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
19
- {"timestamp": "2026-01-27T19:40:23.765214", "question": "Terry is evaluating a Capco (consulting firm) offer in Hong Kong. He's concerned about the non-compete clause:\n\n**The clause (15.1):** 6 months post-employment, cannot work for:\n- Named competitors: A", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
20
- {"timestamp": "2026-01-30T16:06:22.366395", "question": "I'm leaving CNCBI (being counselled out, have Capco offer). Should I share my personal FAQ chatbot demo with Derek (Head of Direct Banking, worked together on agent-assist chatbot, potential Hang Seng", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}
21
- {"timestamp": "2026-01-31T08:10:37.823456", "question": "We've been building a system where:\n\n1. **Skills** = crystallized procedures (how to do things) - stored as SKILL.md files, invoked by Claude\n2. **Vault notes** = content libraries (what to know/say) ", "gist": null, "context": null, "rounds": 2, "blind": true, "models": ["Claude", "GPT", "Gemini", "Grok", "Kimi"]}