Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/BEARING.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "BEARING"
generated_at: 2026-04-07T05:30:14.479Z
generated_at: 2026-04-07T05:55:49.964Z
generator: "method sync ship (renderBearing)"
generated_from_commit: "03d889ddbe57ecb6b336ba2a62815f863f85bfd1"
generated_from_commit: "e0ede9beb70f0be809fe95782025e9ebca97fb2e"
provenance_level: artifact_history
---

Expand Down
14 changes: 12 additions & 2 deletions docs/CLI.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "CLI Reference"
generated_at: 2026-04-07T05:30:14.481Z
generator: "method sync ship (generateCliReference)"
generator: "method sync ship"
generated_from_commit: "03d889ddbe57ecb6b336ba2a62815f863f85bfd1"
provenance_level: artifact_history
---
Expand All @@ -14,6 +14,7 @@ operations. Run `method help` for a quick summary or

## Commands

<!-- generate:cli-commands -->
### `method init [path]`

Scaffold a METHOD workspace in the given directory.
Expand Down Expand Up @@ -50,10 +51,19 @@ GitHub Options:
--pull Update local backlog with GitHub changes (labels, comments, status).
Perform Ship Sync or synchronize the backlog with GitHub Issues.

## Exit Codes
### Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Error (bad arguments, missing workspace, failed operation) |
| 2 | Drift found (from `method drift`) |
<!-- /generate -->

## Configuration

The CLI reads `.method.json` from the workspace root for:

- `paths` — custom directory layout (see `ARCHITECTURE.md`)
- `github_token` / `github_repo` — GitHub adapter credentials
- Environment overrides: `GITHUB_TOKEN`, `GITHUB_REPO`
18 changes: 18 additions & 0 deletions docs/GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
---
title: "Guide"
generator: "method sync ship"
provenance_level: artifact_history
---

# Guide

This document holds practical advice for working in a METHOD repo. It
is intentionally lighter than doctrine in `README.md` or
`docs/method/process.md`.
Expand Down Expand Up @@ -39,3 +43,17 @@ Some things are worth saying before they are worth standardizing.
`README.md` and `docs/method/process.md` describe the load-bearing
contract of METHOD. This guide is for patterns that help in practice
but are not yet strong enough to claim as universal rules.

## Signposts

<!-- generate:signpost-inventory -->
| Signpost | Type | Description |
|----------|------|-------------|
| `README.md` | Hand-authored | Core doctrine and filesystem shape. |
| `ARCHITECTURE.md` | Hand-authored | How the source code is organized. |
| `docs/BEARING.md` | Generated | Current direction and recent ships. |
| `docs/VISION.md` | Generated | Bounded executive synthesis. |
| `docs/CLI.md` | Generated | CLI command reference. |
| `docs/MCP.md` | Generated | MCP tool reference. |
| `docs/GUIDE.md` | Hybrid | Operator advice with generated sections. |
<!-- /generate -->
10 changes: 9 additions & 1 deletion docs/MCP.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "MCP Reference"
generated_at: 2026-04-07T05:30:14.482Z
generator: "method sync ship (generateMcpReference)"
generator: "method sync ship"
generated_from_commit: "03d889ddbe57ecb6b336ba2a62815f863f85bfd1"
provenance_level: artifact_history
---
Expand All @@ -20,6 +20,7 @@ workspace-agnostic — a single instance can serve multiple projects.

## Tools

<!-- generate:mcp-tools -->
### `method_status`

Get the current status of the METHOD workspace (backlog lanes, active cycles, legend health)
Expand Down Expand Up @@ -80,3 +81,10 @@ Automate terminal evidence capture for a cycle
**Parameters:**

- `cycle` (optional) `string`
<!-- /generate -->

## Error Handling

All tools return `isError: true` with a text message on failure.
Common errors: `workspace is required`, `not a METHOD workspace`,
`No active cycles found`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: "Hybrid Signpost Generation"
legend: PROCESS
---

# Hybrid Signpost Generation

Source: dogfood discussion — fully-generated signposts lose hand-authored
prose; fully-manual signposts drift from code.
Legend: PROCESS

## Sponsors

- Human: Process Steward
- Agent: Signpost Generator

## Hill

Replace the fully-generated signpost approach with a hybrid model.
Hand-authored prose stays. Sections marked with
`<!-- generate:NAME -->` / `<!-- /generate -->` get their content
replaced on ship sync.

## Playback Questions

### Human

- [ ] Ship sync replaces content between generate markers without
touching surrounding prose.
- [ ] CLI.md, MCP.md, and GUIDE.md use generate markers for their
reference sections.
- [ ] Hand-written content outside markers survives regeneration.

### Agent

- [ ] A `replaceGeneratedSections` function finds marker pairs and
replaces their content using a registry of named generators.
- [ ] Generators exist for `cli-commands`, `mcp-tools`, and
`signpost-inventory`.
- [ ] Tests prove markers are respected and content outside is
preserved.

## Accessibility and Assistive Reading

Not in scope.

## Localization and Directionality

Not in scope.

## Agent Inspectability and Explainability

Generate markers are HTML comments — invisible in rendered markdown
but visible in source, making the contract explicit.

## Non-goals

- [ ] Generating ARCHITECTURE.md content (stays fully hand-authored).
- [ ] Generating README.md content.
- [ ] Nested or conditional generation markers.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: "Hybrid Signpost Generation"
outcome: hill-met
drift_check: yes
---

# Hybrid Signpost Generation Retro

Design: `docs/design/0028-hybrid-signpost-generation/hybrid-signpost-generation.md`
Outcome: hill-met
Drift check: yes

## Summary

Replaced fully-generated signposts with a hybrid model using
`<!-- generate:NAME -->` / `<!-- /generate -->` markers. Hand-authored
prose survives regeneration. Ship sync replaces only the content
between markers. Three generators implemented: cli-commands,
mcp-tools, signpost-inventory.

## Playback Witness

- [Verification Witness](./witness/verification.md)

## Drift

- None recorded.

## New Debt

- `captureIdea` still does not write YAML frontmatter on new inbox items.

## Cool Ideas

- Add a `generate:backlog-summary` section for GUIDE.md.
- Add marker support to ARCHITECTURE.md for auto-generated source listing.

## Backlog Maintenance

- [x] Inbox processed
- [x] Priorities reviewed
- [x] Dead work buried or merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: "Verification Witness for Cycle 28"
---

# Verification Witness for Cycle 28

This witness proves that `Hybrid Signpost Generation` now carries the required
behavior and adheres to the repo invariants.

## Test Results

```
> method@0.2.0 test
> vitest run --config vitest.config.ts


RUN v4.1.2 ./method


Test Files 12 passed (12)
Tests 127 passed (127)
Start at 22:56:15
Duration 987ms (transform 884ms, setup 0ms, import 2.85s, tests 1.05s, environment 1ms)
```

## Drift Results

```
Playback-question drift found.
Scanned 1 active cycle, 6 playback questions, 140 test descriptions.
Search basis: exact normalized match in tests/**/*.test.* and tests/**/*.spec.* descriptions.

docs/design/0028-hybrid-signpost-generation/hybrid-signpost-generation.md
- Human: Ship sync replaces content between generate markers without touching surrounding prose.
Near miss: "replaces content between generate markers without touching surrounding prose"
- Human: CLI.md, MCP.md, and GUIDE.md use generate markers for their reference sections.
No exact normalized test description match found.
- Human: Hand-written content outside markers survives regeneration.
No exact normalized test description match found.
- Agent: A `replaceGeneratedSections` function finds marker pairs and replaces their content using a registry of named generators.
No exact normalized test description match found.
- Agent: Generators exist for `cli-commands`, `mcp-tools`, and `signpost-inventory`.
No exact normalized test description match found.
- Agent: Tests prove markers are respected and content outside is preserved.
No exact normalized test description match found.
```

## Manual Verification

- [x] Automated capture completed successfully.
90 changes: 90 additions & 0 deletions src/generate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { CLI_TOPICS, usage } from './cli-args.js';
import { MCP_TOOLS } from './mcp.js';

export type GeneratorFn = () => string;
export type GeneratorRegistry = Record<string, GeneratorFn>;

const MARKER_PATTERN = /<!-- generate:(\S+) -->\n[\s\S]*?<!-- \/generate -->/gu;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Regex silently fails on CRLF line endings.

The pattern mandates a literal \n after the opening marker. Files with Windows-style \r\n line endings will never match, causing silent no-op behavior. This is a landmine waiting for a contributor on Windows or a file that passes through a tool that normalizes to CRLF.

🛠️ Proposed fix to handle both LF and CRLF
-const MARKER_PATTERN = /<!-- generate:(\S+) -->\n[\s\S]*?<!-- \/generate -->/gu;
+const MARKER_PATTERN = /<!-- generate:(\S+) -->\r?\n[\s\S]*?<!-- \/generate -->/gu;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const MARKER_PATTERN = /<!-- generate:(\S+) -->\n[\s\S]*?<!-- \/generate -->/gu;
const MARKER_PATTERN = /<!-- generate:(\S+) -->\r?\n[\s\S]*?<!-- \/generate -->/gu;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/generate.ts` at line 7, The MARKER_PATTERN regex in src/generate.ts
mandates a literal "\n" after the opening marker so it fails on CRLF files;
update the MARKER_PATTERN constant to allow an optional carriage return before
the newline (replace the literal "\n" with a CR-optional newline pattern such as
"\r?\n") while preserving the existing [\s\S]*? and the /gu flags so markers
match both LF and CRLF line endings.


export function replaceGeneratedSections(
content: string,
generators: GeneratorRegistry,
): string {
return content.replace(MARKER_PATTERN, (match, name: string) => {
const generator = generators[name];
if (generator === undefined) {
return match;
}
const generated = generator();
return `<!-- generate:${name} -->\n${generated}<!-- /generate -->`;
Comment on lines +18 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Fragile contract: relies on generators to include trailing newline.

The output format assumes generated ends with \n, otherwise the closing marker smashes onto the last content line:

<!-- generate:foo -->
some content<!-- /generate -->

All three current generators happen to comply, but this is implicit. A future generator omitting the trailing newline will produce malformed output with no warning.

🛡️ Defensive normalization
     const generated = generator();
-    return `<!-- generate:${name} -->\n${generated}<!-- /generate -->`;
+    const normalized = generated.endsWith('\n') ? generated : `${generated}\n`;
+    return `<!-- generate:${name} -->\n${normalized}<!-- /generate -->`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const generated = generator();
return `<!-- generate:${name} -->\n${generated}<!-- /generate -->`;
const generated = generator();
const normalized = generated.endsWith('\n') ? generated : `${generated}\n`;
return `<!-- generate:${name} -->\n${normalized}<!-- /generate -->`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/generate.ts` around lines 18 - 19, The template assembly in generate.ts
assumes the string returned by calling generator() ends with a newline, which is
fragile; modify the code around the generated variable (the result of
generator()) so you normalize it before embedding—e.g., compute generated =
generator(); if it does not endWith('\n') append a '\n'—then return the template
string using that normalized generated value so the closing marker always
appears on its own line.

});
}

export function cliCommandsGenerator(): string {
const lines: string[] = [];
for (const topic of CLI_TOPICS) {
const text = usage(topic);
const usageLine = text.split('\n')[0] ?? '';
const description = text.split('\n').slice(1).filter((l) => l.trim().length > 0);
lines.push(`### \`${usageLine.replace(/^Usage: /u, '')}\``);
lines.push('');
for (const line of description) {
lines.push(line);
}
if (description.length > 0) {
lines.push('');
}
}
lines.push('### Exit Codes');
lines.push('');
lines.push('| Code | Meaning |');
lines.push('|------|---------|');
lines.push('| 0 | Success |');
lines.push('| 1 | Error (bad arguments, missing workspace, failed operation) |');
lines.push('| 2 | Drift found (from `method drift`) |');
Comment on lines +38 to +44

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Exit codes table is hardcoded - potential drift risk.

Exit code semantics are duplicated here rather than derived from a single source of truth. If method drift changes its exit code or new codes are added, this table will silently drift.

Consider whether exit codes should be co-located with their definitions (e.g., constants in errors.ts or cli-args.ts) and referenced here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/generate.ts` around lines 38 - 44, The exit codes table in generate.ts is
hardcoded and can drift from the canonical definitions; update generate.ts to
derive the table from the single source of truth (e.g., import the exit code
constants or map from errors.ts or cli-args.ts) instead of using literal
lines.push entries, and programmatically iterate over that exported
constants/map to build the Markdown rows so changes to the constants (including
those used by method drift) automatically update the generated table.

lines.push('');
return lines.join('\n');
}

export function mcpToolsGenerator(): string {
const lines: string[] = [];
for (const tool of MCP_TOOLS) {
lines.push(`### \`${tool.name}\``);
lines.push('');
lines.push(tool.description);
lines.push('');

const params = Object.entries(tool.inputSchema.properties)
.filter(([key]) => key !== 'workspace');
const required = new Set(tool.inputSchema.required.filter((k) => k !== 'workspace'));

if (params.length > 0) {
lines.push('**Parameters:**');
lines.push('');
for (const [key, schema] of params) {
const req = required.has(key) ? '(required)' : '(optional)';
const desc = ('description' in schema && schema.description) ? ` — ${schema.description}` : '';
const enumValues = ('enum' in schema && schema.enum) ? ` (${schema.enum.join(', ')})` : '';
lines.push(`- \`${key}\` ${req} \`${schema.type}\`${enumValues}${desc}`);
}
lines.push('');
}
}
return lines.join('\n');
}

export function signpostInventoryGenerator(): string {
const lines: string[] = [
'| Signpost | Type | Description |',
'|----------|------|-------------|',
'| `README.md` | Hand-authored | Core doctrine and filesystem shape. |',
'| `ARCHITECTURE.md` | Hand-authored | How the source code is organized. |',
'| `docs/BEARING.md` | Generated | Current direction and recent ships. |',
'| `docs/VISION.md` | Generated | Bounded executive synthesis. |',
'| `docs/CLI.md` | Generated | CLI command reference. |',
'| `docs/MCP.md` | Generated | MCP tool reference. |',
'| `docs/GUIDE.md` | Hybrid | Operator advice with generated sections. |',
'',
];
return lines.join('\n');
}
Loading
Loading