You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(mcp): flatten Handler god-object, promote session state to entity
Closes TASKS.md:45 ("Move 6 grandfathered cross-package MCP types to
entity/") by eliminating the Handler struct entirely and reducing the
grandfathered cross-package types count from 6 to 0.
## Phase 1 — sub-task moves
- `def/prompt.EntrySpec`/`EntryField` -> `entity.PromptEntrySpec`/
`PromptEntryField` (pure data, natural entity fit)
- `internal/mcp/session/*` collapsed into `internal/mcp/handler/*`
(sole consumer; eliminates the sibling crossing)
- `internal/mcp/server/poll/` -> `internal/mcp/server/dispatch/poll/`
(ancestor->descendant exemption closes the last sibling crossing
before Phase 2)
## Phase 2 — flatten the Handler god-object
The Handler struct was a parameter bundle masquerading as domain
logic. 13 of its 17 methods only read ContextDir; 2 mutated session
state; the other 2 did not touch the receiver at all. TokenBudget
was a pass-through passenger consumed only by dispatch.go.
- New `entity.MCPDeps { ContextDir, TokenBudget, *MCPSession }`
parameter object, held by the server and threaded through dispatch
- New `entity.MCPSession` holding the former session.State fields
with pure Record*/Increment* mutation methods (no I/O)
- New `entity.PendingUpdate` (pure data)
- All 17 `(h *Handler) Foo(...)` methods converted to free functions
`handler.Foo(d *entity.MCPDeps, ...)`
- `handler.CheckGovernance` kept as a free function in handler/
because it still reads .context/state/violations.json (Phase 3
absorbed into Phase 2 naturally)
- `server.Server.handler *handler.Handler` replaced with
`server.Server.deps *entity.MCPDeps`; route/tool/* and
route/prompt/* updated to take `*entity.MCPDeps`
- `handler.Handler` struct deleted entirely; `handler/handler.go`
deleted; `handler/state.go` deleted
- `governance_test.go` rewritten to construct `*entity.MCPDeps`
## Grandfather purge (TestTypeFileConvention)
The grandfatheredTypes map was cleared to zero entries. All 35
underlying violations across 18 packages were fixed by moving type
declarations into per-package types.go files; methods remain in
their original files, which become type-decl-free and are skipped
by the audit.
- New types.go created in 13 packages (cli/dep/core/{golang,node,
python,rust}, cli/drift/core/{fix,out}, cli/guide/core/skill,
cli/remind/core/store, cli/system/core/nudge, cli/why/core/data,
config/memory, mcp/server/catalog, mcp/server/io)
- fm.go renamed to types.go (frontmatter) and atom.go renamed to
types.go (rss) since they were pure type definition files
- session.go regenerated with only the Session interface
- parser.{ClaudeCode,Copilot,CopilotCLI,MarkdownSession} and
lookup.commandEntry absorbed into their packages' existing types.go
Hardened the grandfatheredTypes comment with an explicit agent
directive: do not add entries here under any circumstance. Any
re-addition requires a dedicated pull request with per-entry
justification and maintainer approval. Drive-by additions by any
assistant are unauthorized.
## Interface segregation
Interfaces are behavioral contracts, not data blueprints, so they
live in their own <name>.go files rather than types.go.
- TestTypeFileConvention updated: interface type declarations are
now exempt from the "must have exported receiver" phase 4 check.
Interfaces cannot carry receivers; a file containing only an
interface is a valid pure type file.
- `parser.Session` interface moved to journal/parser/session.go
- `builder.GraphBuilder` interface moved to
cli/dep/core/builder/graph_builder.go
## Audit state
- TestCrossPackageTypes: grandfathered 6 -> 0
- TestTypeFileConvention: grandfathered map 34 -> 0
- TestDocCommentStructure: 0 (unchanged)
- make test: all pass
- make lint: 0 issues
## Documentation
Updated .context/DETAILED_DESIGN-mcp.md, .context/ARCHITECTURE.md,
.context/DANGER-ZONES.md, and .context/DETAILED_DESIGN.md to reflect
the new package layout (no more mcp/session, poll lives under
dispatch, Handler replaced by entity.MCPDeps).
Also sweeps in two pre-existing .context/ entries that were
uncommitted at session start (architecture skill pipeline decision,
pad index shifting learning).
Spec: specs/mcp-handler-flatten.md
Signed-off-by: Jose Alekhinne <jose@ctx.ist>
| 2026-04-06 | Use hook relay for session provenance instead of JSONL parsing or env vars |
8
9
| 2026-04-04 | TestNoMagicStrings and TestNoMagicValues no longer exempt const/var definitions outside config/ |
@@ -118,6 +119,20 @@ For significant decisions:
118
119
119
120
-->
120
121
122
+
## [2026-04-09-001332] Architecture skill pipeline is a triad not a quartet
123
+
124
+
**Status**: Accepted
125
+
126
+
**Context**: Had a proposed ctx-architecture-extend for extension point mapping, making four skills
127
+
128
+
**Decision**: Architecture skill pipeline is a triad not a quartet
129
+
130
+
**Rationale**: Extension points already covered per-module in DETAILED_DESIGN and by registration site discovery in enrich. Fourth skill fragments pipeline without distinct value
131
+
132
+
**Consequence**: Pipeline is map enrich hunt. Three skills three questions: how does it work, how well does it connect, where will it break
133
+
134
+
---
135
+
121
136
## [2026-04-08-013731] Remove #done tag convention, simplify task archival
## [2026-04-09-001323] Pad index shifting is a real UX bug in batch operations
116
+
117
+
**Context**: ctx pad rm 10; rm 11; rm 12 deleted wrong entries because indices shifted after each deletion
118
+
119
+
**Lesson**: Any ID-based system where users chain operations needs stable IDs. Look-then-act is safe for single ops; look-then-batch-act breaks with shifting indices
120
+
121
+
**Application**: Both pad and remind now use stable IDs with batch delete and range support. Apply same pattern to any future numbered-list subsystem
122
+
123
+
---
124
+
114
125
## [2026-04-08-074612] fmt.Fprintf to strings.Builder silently discards errors
115
126
116
127
**Context**: golangci-lint errcheck allows fmt.Fprintf to strings.Builder because Write never fails, but project convention says zero silent discard
0 commit comments