Skip to content

Commit 0a7ef71

Browse files
committed
fix: migrate 42 magic strings from PR #55 to YAML assets
All user-facing format strings in write/steering, write/skill, write/trigger, write/setup, mcp/handler, trigger/, and drift/ now go through desc.Text() with YAML-backed DescKeys. Added 42 YAML entries in ui.yaml and 30 DescKey constants across 6 config/embed/text files (steering.go, trigger.go new; skill.go, setup.go, mcp_tool.go, drift.go updated). Also adds predicate naming convention section to audit-conventions.md. Spec: specs/ast-audit-contributor-guide.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
1 parent 242bc5e commit 0a7ef71

16 files changed

Lines changed: 332 additions & 46 deletions

File tree

‎docs/reference/audit-conventions.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,41 @@ func Journal(cmd *cobra.Command, ...) {
702702
703703
---
704704
705+
## Predicate Naming (no `Is`/`Has`/`Can` prefix)
706+
707+
**Test:** None (manual review convention)
708+
709+
Exported methods that return `bool` must not use `Is`, `Has`, or
710+
`Can` prefixes. The predicate reads more naturally without them,
711+
especially at call sites where the package name provides context.
712+
713+
**Before:**
714+
715+
```go
716+
func IsCompleted(t *Task) bool { ... }
717+
func HasChildren(n *Node) bool { ... }
718+
func IsExemptPackage(path string) bool { ... }
719+
```
720+
721+
**After:**
722+
723+
```go
724+
func Completed(t *Task) bool { ... }
725+
func Children(n *Node) bool { ... } // or: ChildCount > 0
726+
func ExemptPackage(path string) bool { ... }
727+
```
728+
729+
**Rule:** Drop the prefix. Private helpers may use prefixes when it
730+
reads more naturally (`isValid` in a local context is fine). This
731+
convention applies to exported methods and package-level functions.
732+
See CONVENTIONS.md "Predicates" section.
733+
734+
This is not yet enforced by an AST test — it requires semantic
735+
understanding of return types and naming intent that makes automated
736+
detection fragile. Apply during code review.
737+
738+
---
739+
705740
## Mixed Visibility
706741
707742
**Test:** `TestNoMixedVisibility`

‎internal/assets/commands/text/ui.yaml‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,3 +526,94 @@ write.why-label-invariants:
526526
short: "Design Invariants"
527527
help.community-footer:
528528
short: "\nHave a question, bug, or feature request? Join us on Discord:\n https://ctx.ist/discord\n"
529+
530+
write.steering-created:
531+
short: 'Created %s'
532+
write.steering-skipped:
533+
short: 'Skipped %s (already exists)'
534+
write.steering-init-summary:
535+
short: "\n%d created, %d skipped"
536+
write.steering-file-entry:
537+
short: '%-20s inclusion=%-7s priority=%-3d tools=%s'
538+
write.steering-file-count:
539+
short: "\n%d steering file(s)"
540+
write.steering-preview-head:
541+
short: 'Steering files matching prompt %q:'
542+
write.steering-preview-entry:
543+
short: ' %-20s inclusion=%-7s priority=%-3d tools=%s'
544+
write.steering-preview-count:
545+
short: "\n%d file(s) would be included"
546+
write.steering-sync-written:
547+
short: 'Written: %s'
548+
write.steering-sync-skipped:
549+
short: 'Skipped: %s'
550+
write.steering-sync-error:
551+
short: 'Error: %s'
552+
write.steering-sync-summary:
553+
short: "\n%d written, %d skipped, %d errors"
554+
555+
write.skill-installed:
556+
short: 'Installed %s → %s'
557+
write.skill-entry-desc:
558+
short: ' %-20s %s'
559+
write.skill-entry:
560+
short: ' %s'
561+
write.skill-count:
562+
short: "\n%d skill(s)"
563+
write.skill-removed:
564+
short: 'Removed %s'
565+
566+
write.setup-deploy-complete:
567+
short: '%s setup complete.'
568+
write.setup-deploy-mcp:
569+
short: ' MCP server: %s'
570+
write.setup-deploy-steering:
571+
short: ' Steering: %s'
572+
write.setup-deploy-exists:
573+
short: "\u2713 %s already exists (skipped)"
574+
write.setup-deploy-created:
575+
short: "\u2713 Created %s"
576+
write.setup-deploy-synced:
577+
short: "\u2713 Synced steering: %s"
578+
write.setup-deploy-skip-steer:
579+
short: ' Skipped steering: %s (unchanged)'
580+
581+
mcp.steering-section:
582+
short: "## %s\n\n%s\n\n"
583+
mcp.search-hit-line:
584+
short: "%s:%d: %s\n"
585+
mcp.search-no-match:
586+
short: 'No matches for %q in %s.'
587+
588+
trigger.warn:
589+
short: 'hook %s: %v'
590+
trigger.error-item:
591+
short: '%s: %s'
592+
trigger.skip-warn:
593+
short: 'hook skip %s: %v'
594+
595+
drift.tool-suffix:
596+
short: '%s (tool: %s)'
597+
598+
write.trigger-created:
599+
short: 'Created %s'
600+
write.trigger-disabled:
601+
short: 'Disabled %s (%s)'
602+
write.trigger-enabled:
603+
short: 'Enabled %s (%s)'
604+
write.trigger-type-hdr:
605+
short: '[%s]'
606+
write.trigger-entry:
607+
short: ' %-20s %-8s %s'
608+
write.trigger-count:
609+
short: '%d hook(s)'
610+
write.trigger-test-hdr:
611+
short: 'Testing %s hooks...'
612+
write.trigger-test-input:
613+
short: "Input:\n%s"
614+
write.trigger-cancelled:
615+
short: 'Cancelled: %s'
616+
write.trigger-context:
617+
short: "Context:\n%s"
618+
write.trigger-err-line:
619+
short: ' %s'

‎internal/config/embed/text/drift.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const (
5858
DescKeyDriftInvalidTool = "drift.invalid-tool"
5959
DescKeyDriftHookNoExec = "drift.hook-no-exec"
6060
DescKeyDriftStaleSyncFile = "drift.stale-sync-file"
61+
DescKeyDriftToolSuffix = "drift.tool-suffix"
6162
DescKeyVersionDriftRelayMessage = "version-drift.relay-message"
6263
DescKeyWriteVersionDriftFallback = "write.version-drift-fallback"
6364
)

‎internal/config/embed/text/mcp_tool.go‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,10 @@ const (
4545
DescKeyMCPToolPropSearchQuery = "mcp.tool-prop-search-query"
4646
DescKeyMCPToolPropSummary = "mcp.tool-prop-summary"
4747
)
48+
49+
// DescKeys for MCP handler steering/search output.
50+
const (
51+
DescKeyMCPSteeringSection = "mcp.steering-section"
52+
DescKeyMCPSearchHitLine = "mcp.search-hit-line"
53+
DescKeyMCPSearchNoMatch = "mcp.search-no-match"
54+
)

‎internal/config/embed/text/setup.go‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ package text
88

99
// DescKeys for setup wizard write output.
1010
const (
11-
DescKeyWriteSetupDone = "write.setup-done"
12-
DescKeyWriteSetupPrompt = "write.setup-prompt"
11+
DescKeyWriteSetupDone = "write.setup-done"
12+
DescKeyWriteSetupPrompt = "write.setup-prompt"
13+
DescKeyWriteSetupDeployComplete = "write.setup-deploy-complete"
14+
DescKeyWriteSetupDeployMCP = "write.setup-deploy-mcp"
15+
DescKeyWriteSetupDeploySteering = "write.setup-deploy-steering"
16+
DescKeyWriteSetupDeployExists = "write.setup-deploy-exists"
17+
DescKeyWriteSetupDeployCreated = "write.setup-deploy-created"
18+
DescKeyWriteSetupDeploySynced = "write.setup-deploy-synced"
19+
DescKeyWriteSetupDeploySkipSteer = "write.setup-deploy-skip-steer"
1320
)

‎internal/config/embed/text/skill.go‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ package text
88

99
// DescKeys for skill display write output.
1010
const (
11-
DescKeyWriteSkillLine = "write.skill-line"
12-
DescKeyWriteSkillsHeader = "write.skills-header"
11+
DescKeyWriteSkillLine = "write.skill-line"
12+
DescKeyWriteSkillsHeader = "write.skills-header"
13+
DescKeyWriteSkillInstalled = "write.skill-installed"
14+
DescKeyWriteSkillEntryDesc = "write.skill-entry-desc"
15+
DescKeyWriteSkillEntry = "write.skill-entry"
16+
DescKeyWriteSkillCount = "write.skill-count"
17+
DescKeyWriteSkillRemoved = "write.skill-removed"
1318
)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// / ctx: https://ctx.ist
2+
// ,'`./ do you remember?
3+
// `.,'\\
4+
// \ Copyright 2026-present Context contributors.
5+
// SPDX-License-Identifier: Apache-2.0
6+
7+
package text
8+
9+
// DescKeys for steering write output.
10+
const (
11+
DescKeyWriteSteeringCreated = "write.steering-created"
12+
DescKeyWriteSteeringSkipped = "write.steering-skipped"
13+
DescKeyWriteSteeringInitSummary = "write.steering-init-summary"
14+
DescKeyWriteSteeringFileEntry = "write.steering-file-entry"
15+
DescKeyWriteSteeringFileCount = "write.steering-file-count"
16+
DescKeyWriteSteeringPreviewHead = "write.steering-preview-head"
17+
DescKeyWriteSteeringPreviewEntry = "write.steering-preview-entry"
18+
DescKeyWriteSteeringPreviewCount = "write.steering-preview-count"
19+
DescKeyWriteSteeringSyncWritten = "write.steering-sync-written"
20+
DescKeyWriteSteeringSyncSkipped = "write.steering-sync-skipped"
21+
DescKeyWriteSteeringSyncError = "write.steering-sync-error"
22+
DescKeyWriteSteeringSyncSummary = "write.steering-sync-summary"
23+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// / ctx: https://ctx.ist
2+
// ,'`./ do you remember?
3+
// `.,'\\
4+
// \ Copyright 2026-present Context contributors.
5+
// SPDX-License-Identifier: Apache-2.0
6+
7+
package text
8+
9+
// DescKeys for trigger (hook runner) output.
10+
const (
11+
DescKeyTriggerWarn = "trigger.warn"
12+
DescKeyTriggerErrorItem = "trigger.error-item"
13+
DescKeyTriggerSkipWarn = "trigger.skip-warn"
14+
)
15+
16+
// DescKeys for write/trigger display output.
17+
const (
18+
DescKeyWriteTriggerCreated = "write.trigger-created"
19+
DescKeyWriteTriggerDisabled = "write.trigger-disabled"
20+
DescKeyWriteTriggerEnabled = "write.trigger-enabled"
21+
DescKeyWriteTriggerTypeHdr = "write.trigger-type-hdr"
22+
DescKeyWriteTriggerEntry = "write.trigger-entry"
23+
DescKeyWriteTriggerCount = "write.trigger-count"
24+
DescKeyWriteTriggerTestHdr = "write.trigger-test-hdr"
25+
DescKeyWriteTriggerTestInput = "write.trigger-test-input"
26+
DescKeyWriteTriggerCancelled = "write.trigger-cancelled"
27+
DescKeyWriteTriggerContext = "write.trigger-context"
28+
DescKeyWriteTriggerErrLine = "write.trigger-err-line"
29+
)

‎internal/drift/check_ext.go‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ func checkSyncStaleness(report *Report) {
143143
File: name,
144144
Type: IssueStaleSyncFile,
145145
Message: desc.Text(text.DescKeyDriftStaleSyncFile),
146-
Path: fmt.Sprintf("%s (tool: %s)", name, tool),
146+
Path: fmt.Sprintf(
147+
desc.Text(text.DescKeyDriftToolSuffix),
148+
name, tool),
147149
})
148150
found = true
149151
}

‎internal/mcp/handler/steering.go‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"path/filepath"
1515
"strings"
1616

17+
"github.com/ActiveMemory/ctx/internal/assets/read/desc"
18+
"github.com/ActiveMemory/ctx/internal/config/embed/text"
1719
errMcp "github.com/ActiveMemory/ctx/internal/err/mcp"
1820
ctxIo "github.com/ActiveMemory/ctx/internal/io"
1921
"github.com/ActiveMemory/ctx/internal/rc"
@@ -60,7 +62,9 @@ func (h *Handler) SteeringGet(prompt string) (string, error) {
6062

6163
var sb strings.Builder
6264
for _, sf := range filtered {
63-
fmt.Fprintf(&sb, "## %s\n\n%s\n\n", sf.Name, sf.Body)
65+
fmt.Fprintf(&sb,
66+
desc.Text(text.DescKeyMCPSteeringSection),
67+
sf.Name, sf.Body)
6468
}
6569

6670
return sb.String(), nil
@@ -105,14 +109,18 @@ func (h *Handler) Search(query string) (string, error) {
105109
lineNum++
106110
line := scanner.Text()
107111
if strings.Contains(strings.ToLower(line), queryLower) {
108-
fmt.Fprintf(&sb, "%s:%d: %s\n", e.Name(), lineNum, line)
112+
fmt.Fprintf(&sb,
113+
desc.Text(text.DescKeyMCPSearchHitLine),
114+
e.Name(), lineNum, line)
109115
matches++
110116
}
111117
}
112118
}
113119

114120
if matches == 0 {
115-
return fmt.Sprintf("No matches for %q in %s.", query, h.ContextDir), nil
121+
return fmt.Sprintf(
122+
desc.Text(text.DescKeyMCPSearchNoMatch),
123+
query, h.ContextDir), nil
116124
}
117125

118126
return sb.String(), nil

0 commit comments

Comments
 (0)