auto-context-cli 1.0.5__tar.gz → 1.0.7__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.
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/PKG-INFO +3 -3
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/README.md +2 -2
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/pyproject.toml +1 -1
- auto_context_cli-1.0.7/src/auto_context/__init__.py +16 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/init_cmd.py +145 -5
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/mcp.py +7 -2
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/memory.py +12 -1
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/update_cmd.py +19 -3
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/config.py +11 -12
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/main.py +4 -2
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/scanner.py +4 -3
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/security.py +10 -5
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/AGENTS.template.md +5 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/GEMINI.template.md +5 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/maintain_context.template.md +5 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rules/code-standards.md +6 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rules/hub-satellite-architecture.md +2 -2
- auto_context_cli-1.0.7/src/auto_context/templates/rules/registry.json +226 -0
- auto_context_cli-1.0.5/src/auto_context/__init__.py +0 -3
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/.gitignore +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/LICENSE +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/__init__.py +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/import_cmd.py +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/scan_cmd.py +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/commands/share.py +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/context.local.template.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/context.template.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/mcp_config.template.json +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/profile.template.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rule.template.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rules/readme-docs-sync.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rules/security-boundaries.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/skill.template.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/skills/browser-testing/SKILL.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/skills/docker-ops/SKILL.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/skills/git-workflow/SKILL.md +0 -0
- {auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/skills/server-diagnostics/SKILL.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: auto-context-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.7
|
|
4
4
|
Summary: Autonomous context & instruction manager for AI coding assistants
|
|
5
5
|
Author: Arghya Biswas
|
|
6
6
|
License: MIT
|
|
@@ -20,7 +20,7 @@ Description-Content-Type: text/markdown
|
|
|
20
20
|
|
|
21
21
|
[](https://pypi.org/project/auto-context-cli/)
|
|
22
22
|
[](https://pypi.org/project/auto-context-cli/)
|
|
23
|
-
[](https://github.com/Cyber-arghya/auto-context/releases/tag/v1.0.
|
|
23
|
+
[](https://github.com/Cyber-arghya/auto-context/releases/tag/v1.0.7)
|
|
24
24
|
[](https://opensource.org/licenses/MIT)
|
|
25
25
|
[](#-quick-one-line-install)
|
|
26
26
|
[](#-supported-ai-assistants)
|
|
@@ -83,7 +83,7 @@ Auto-Context supports both modern subcommands (`init-context <command>`) and sta
|
|
|
83
83
|
| :--- | :--- | :--- |
|
|
84
84
|
| `init-context init [DIR]` | `init-context [DIR]` | Scaffolds 5-tier context in active or specified directory. |
|
|
85
85
|
| `init-context scan [DIR]` | `init-context --scan` | Stack-adaptive codebase scanner: generates satellites (.agents/context/). |
|
|
86
|
-
| `init-context rule <name>` | `init-context -r <name
|
|
86
|
+
| `init-context rule <name>` | `init-context -r <name> [-a]` | Scaffolds a rule or appends to a domain with `registry.json` duplicate protection. |
|
|
87
87
|
| `init-context skill <name>` | `init-context -s <name>` | Scaffolds a new agent skill directory with triggers & runbook. |
|
|
88
88
|
| `init-context promote <name>` | — | Promotes local workspace rule/skill to Global Plugin & Central Memory. |
|
|
89
89
|
| `init-context update` | — | Modular, non-breaking update for CLI, global plugin & system rules. |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://pypi.org/project/auto-context-cli/)
|
|
8
8
|
[](https://pypi.org/project/auto-context-cli/)
|
|
9
|
-
[](https://github.com/Cyber-arghya/auto-context/releases/tag/v1.0.
|
|
9
|
+
[](https://github.com/Cyber-arghya/auto-context/releases/tag/v1.0.7)
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
11
|
[](#-quick-one-line-install)
|
|
12
12
|
[](#-supported-ai-assistants)
|
|
@@ -69,7 +69,7 @@ Auto-Context supports both modern subcommands (`init-context <command>`) and sta
|
|
|
69
69
|
| :--- | :--- | :--- |
|
|
70
70
|
| `init-context init [DIR]` | `init-context [DIR]` | Scaffolds 5-tier context in active or specified directory. |
|
|
71
71
|
| `init-context scan [DIR]` | `init-context --scan` | Stack-adaptive codebase scanner: generates satellites (.agents/context/). |
|
|
72
|
-
| `init-context rule <name>` | `init-context -r <name
|
|
72
|
+
| `init-context rule <name>` | `init-context -r <name> [-a]` | Scaffolds a rule or appends to a domain with `registry.json` duplicate protection. |
|
|
73
73
|
| `init-context skill <name>` | `init-context -s <name>` | Scaffolds a new agent skill directory with triggers & runbook. |
|
|
74
74
|
| `init-context promote <name>` | — | Promotes local workspace rule/skill to Global Plugin & Central Memory. |
|
|
75
75
|
| `init-context update` | — | Modular, non-breaking update for CLI, global plugin & system rules. |
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""auto-context: Autonomous context & instruction manager for AI coding assistants."""
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# Ensure UTF-8 stream handling across all operating systems (guards Windows cp1252 charmap crashes)
|
|
5
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
6
|
+
try:
|
|
7
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
8
|
+
except Exception:
|
|
9
|
+
pass
|
|
10
|
+
if hasattr(sys.stderr, "reconfigure"):
|
|
11
|
+
try:
|
|
12
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
13
|
+
except Exception:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
__version__ = "1.0.6"
|
|
@@ -167,6 +167,10 @@ def init(
|
|
|
167
167
|
for rule_file in (templates / "rules").glob("*.md"):
|
|
168
168
|
_copy_if_missing(rule_file, rules_dest / rule_file.name, force=force, dry_run=dry_run)
|
|
169
169
|
|
|
170
|
+
reg_tmpl = templates / "rules" / "registry.json"
|
|
171
|
+
if reg_tmpl.exists():
|
|
172
|
+
_copy_if_missing(reg_tmpl, rules_dest / "registry.json", force=force, dry_run=dry_run)
|
|
173
|
+
|
|
170
174
|
maintain_tmpl = templates / "maintain_context.template.md"
|
|
171
175
|
if maintain_tmpl.exists():
|
|
172
176
|
content = _render(maintain_tmpl, variables)
|
|
@@ -218,10 +222,10 @@ def init(
|
|
|
218
222
|
".env.*.local",
|
|
219
223
|
])
|
|
220
224
|
|
|
221
|
-
# ── Stack-Adaptive Satellites
|
|
225
|
+
# ── Stack-Adaptive Satellites & Executive Hub Sync ────────────────────
|
|
222
226
|
try:
|
|
223
|
-
from auto_context import
|
|
224
|
-
|
|
227
|
+
from auto_context.commands import scan_cmd
|
|
228
|
+
scan_cmd.scan(target=project_dir, force=force)
|
|
225
229
|
except Exception:
|
|
226
230
|
pass
|
|
227
231
|
|
|
@@ -234,14 +238,116 @@ def init(
|
|
|
234
238
|
|
|
235
239
|
# ── rule command ──────────────────────────────────────────────────────────────
|
|
236
240
|
|
|
241
|
+
def _load_registry(registry_file: Path) -> dict:
|
|
242
|
+
if registry_file.exists():
|
|
243
|
+
try:
|
|
244
|
+
import json
|
|
245
|
+
return json.loads(registry_file.read_text(encoding="utf-8"))
|
|
246
|
+
except Exception:
|
|
247
|
+
pass
|
|
248
|
+
tmpl = get_templates_dir() / "rules" / "registry.json"
|
|
249
|
+
if tmpl.exists():
|
|
250
|
+
try:
|
|
251
|
+
import json
|
|
252
|
+
return json.loads(tmpl.read_text(encoding="utf-8"))
|
|
253
|
+
except Exception:
|
|
254
|
+
pass
|
|
255
|
+
return {"version": "1.0.0", "domains": {}}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _find_duplicate_rule(registry: dict, text_or_title: str) -> Optional[tuple[str, str, str]]:
|
|
259
|
+
import re
|
|
260
|
+
clean_query = re.sub(r"[^a-zA-Z0-9\s]", "", text_or_title).lower().strip()
|
|
261
|
+
query_words = set(w for w in clean_query.split() if len(w) > 3)
|
|
262
|
+
|
|
263
|
+
for d_key, domain in registry.get("domains", {}).items():
|
|
264
|
+
d_file = domain.get("file", f"{d_key}.md")
|
|
265
|
+
for r in domain.get("rules", []):
|
|
266
|
+
r_title = r.get("title", "")
|
|
267
|
+
r_id = r.get("id", "")
|
|
268
|
+
clean_title = re.sub(r"[^a-zA-Z0-9\s]", "", r_title).lower().strip()
|
|
269
|
+
|
|
270
|
+
if clean_query == clean_title or (len(clean_query) > 6 and clean_query in clean_title) or (len(clean_title) > 6 and clean_title in clean_query):
|
|
271
|
+
return d_key, r_title, d_file
|
|
272
|
+
if r_id and r_id in clean_query.replace(" ", "-"):
|
|
273
|
+
return d_key, r_title, d_file
|
|
274
|
+
|
|
275
|
+
r_keywords = set(k.lower() for k in r.get("keywords", []))
|
|
276
|
+
if query_words and len(query_words.intersection(r_keywords)) >= 2:
|
|
277
|
+
return d_key, r_title, d_file
|
|
278
|
+
|
|
279
|
+
return None
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _register_rule_in_registry(registry_file: Path, domain_key: str, rule_title: str, file_name: str) -> None:
|
|
283
|
+
import json
|
|
284
|
+
import re
|
|
285
|
+
from datetime import date
|
|
286
|
+
|
|
287
|
+
registry = _load_registry(registry_file)
|
|
288
|
+
if "domains" not in registry:
|
|
289
|
+
registry["domains"] = {}
|
|
290
|
+
|
|
291
|
+
if domain_key not in registry["domains"]:
|
|
292
|
+
registry["domains"][domain_key] = {
|
|
293
|
+
"file": file_name,
|
|
294
|
+
"name": domain_key.replace("-", " ").title(),
|
|
295
|
+
"description": f"Domain rules for {domain_key}",
|
|
296
|
+
"rules": []
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
clean_first_line = rule_title.strip().splitlines()[0].strip("* ").strip()
|
|
300
|
+
slug = re.sub(r"[^a-zA-Z0-9\s-]", "", clean_first_line).strip().lower().replace(" ", "-")
|
|
301
|
+
clean_words = [w for w in re.sub(r"[^a-zA-Z0-9\s]", "", clean_first_line).lower().split() if len(w) > 3]
|
|
302
|
+
|
|
303
|
+
existing_ids = [r.get("id") for r in registry["domains"][domain_key].get("rules", [])]
|
|
304
|
+
if slug not in existing_ids:
|
|
305
|
+
registry["domains"][domain_key]["rules"].append({
|
|
306
|
+
"id": slug,
|
|
307
|
+
"title": clean_first_line,
|
|
308
|
+
"keywords": clean_words
|
|
309
|
+
})
|
|
310
|
+
registry["last_updated"] = date.today().isoformat()
|
|
311
|
+
registry_file.parent.mkdir(parents=True, exist_ok=True)
|
|
312
|
+
registry_file.write_text(json.dumps(registry, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _append_guideline_to_file(dest_file: Path, text_to_append: str) -> None:
|
|
316
|
+
import re
|
|
317
|
+
content = dest_file.read_text(encoding="utf-8")
|
|
318
|
+
existing_nums = [int(m) for m in re.findall(r"(?m)^(\d+)\.\s+\*", content)]
|
|
319
|
+
next_num = (max(existing_nums) + 1) if existing_nums else 1
|
|
320
|
+
|
|
321
|
+
clean_guideline = text_to_append.strip()
|
|
322
|
+
if not re.match(r"^\d+\.\s+", clean_guideline):
|
|
323
|
+
if not clean_guideline.startswith("**"):
|
|
324
|
+
lines = clean_guideline.splitlines()
|
|
325
|
+
title = lines[0]
|
|
326
|
+
rest = lines[1:] if len(lines) > 1 else []
|
|
327
|
+
entry = f"{next_num}. **{title}**\n"
|
|
328
|
+
for r in rest:
|
|
329
|
+
entry += f" {r}\n"
|
|
330
|
+
else:
|
|
331
|
+
entry = f"{next_num}. {clean_guideline}\n"
|
|
332
|
+
else:
|
|
333
|
+
entry = f"{clean_guideline}\n"
|
|
334
|
+
|
|
335
|
+
if not content.endswith("\n"):
|
|
336
|
+
content += "\n"
|
|
337
|
+
content += entry
|
|
338
|
+
dest_file.write_text(content, encoding="utf-8")
|
|
339
|
+
|
|
340
|
+
|
|
237
341
|
def new_rule(
|
|
238
342
|
name: Annotated[str, typer.Argument(help="Rule name (e.g. code-standards).")],
|
|
239
343
|
target: Annotated[Optional[Path], typer.Option("--target", "-t")] = None,
|
|
240
344
|
global_: Annotated[bool, typer.Option("--global", "-g", help="Install into global plugin.")] = False,
|
|
241
345
|
force: Annotated[bool, typer.Option("--force", "-f")] = False,
|
|
346
|
+
append: Annotated[bool, typer.Option("--append", "-a", help="Append guideline to existing rule domain.")] = False,
|
|
347
|
+
guideline: Annotated[Optional[str], typer.Option("--guideline", help="Guideline text to append to rule.")] = None,
|
|
242
348
|
dry_run: Annotated[bool, typer.Option("--dry-run", "-d")] = False,
|
|
243
349
|
) -> None:
|
|
244
|
-
"""Scaffold a new agent rule file."""
|
|
350
|
+
"""Scaffold a new agent rule file or append to an existing domain rule with duplicate guard."""
|
|
245
351
|
clean_name = name.lower().replace(" ", "-").replace("_", "-").removesuffix(".md")
|
|
246
352
|
title = clean_name.replace("-", " ").title()
|
|
247
353
|
|
|
@@ -251,9 +357,43 @@ def new_rule(
|
|
|
251
357
|
else (target or Path.cwd()).resolve() / AGENTS_SUBDIR / "rules"
|
|
252
358
|
)
|
|
253
359
|
dest_file = dest_dir / f"{clean_name}.md"
|
|
360
|
+
registry_file = dest_dir / "registry.json"
|
|
254
361
|
|
|
255
362
|
if dest_file.exists() and not force:
|
|
256
|
-
|
|
363
|
+
if append or guideline:
|
|
364
|
+
text_to_append = guideline or "New domain constraint and best practice."
|
|
365
|
+
|
|
366
|
+
# Check duplicate against registry
|
|
367
|
+
dup = _find_duplicate_rule(_load_registry(registry_file), text_to_append)
|
|
368
|
+
if dup:
|
|
369
|
+
dup_domain, dup_title, dup_file = dup
|
|
370
|
+
console.print(Panel(
|
|
371
|
+
f"[bold yellow]⚠️ Duplicate Rule Detected — Skipped![/]\n"
|
|
372
|
+
f"[white]The guideline '[cyan]{text_to_append}[/]' matches existing rule:\n"
|
|
373
|
+
f"[green]'{dup_title}'[/] inside [yellow]{dup_file}[/] (Domain: [cyan]{dup_domain}[/]).\n\n"
|
|
374
|
+
f"[dim]Registry checked: {registry_file}[/]",
|
|
375
|
+
border_style="yellow",
|
|
376
|
+
))
|
|
377
|
+
return
|
|
378
|
+
|
|
379
|
+
if not dry_run:
|
|
380
|
+
_append_guideline_to_file(dest_file, text_to_append)
|
|
381
|
+
_register_rule_in_registry(registry_file, clean_name, text_to_append, dest_file.name)
|
|
382
|
+
if global_ and config.MEMORY_DIR.exists():
|
|
383
|
+
mem_dest = config.MEMORY_DIR / "rules" / f"{clean_name}.md"
|
|
384
|
+
if mem_dest.exists():
|
|
385
|
+
_append_guideline_to_file(mem_dest, text_to_append)
|
|
386
|
+
_register_rule_in_registry(config.MEMORY_DIR / "rules" / "registry.json", clean_name, text_to_append, dest_file.name)
|
|
387
|
+
console.print(Panel(
|
|
388
|
+
f"[bold green]✨ Rule Domain Updated & Registered![/]\n"
|
|
389
|
+
f"[yellow] Rule:[/] {clean_name}\n"
|
|
390
|
+
f"[cyan] File:[/] {dest_file}\n"
|
|
391
|
+
f"[cyan] Registry:[/] {registry_file}\n"
|
|
392
|
+
f"[green] Added:[/] {text_to_append}",
|
|
393
|
+
border_style="green",
|
|
394
|
+
))
|
|
395
|
+
return
|
|
396
|
+
console.print(f"[yellow][!] Rule already exists:[/] {dest_file}\n Use --append (-a) with --guideline to add to this domain, or --force to overwrite.")
|
|
257
397
|
raise typer.Exit(1)
|
|
258
398
|
|
|
259
399
|
tmpl = get_templates_dir() / "rule.template.md"
|
|
@@ -10,8 +10,10 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
12
|
import os
|
|
13
|
-
import stat
|
|
14
13
|
from pathlib import Path
|
|
14
|
+
import shlex
|
|
15
|
+
import stat
|
|
16
|
+
import sys
|
|
15
17
|
from typing import Annotated, Optional
|
|
16
18
|
|
|
17
19
|
import typer
|
|
@@ -199,7 +201,10 @@ def add_mcp(
|
|
|
199
201
|
elif command:
|
|
200
202
|
server_cfg = {"command": command}
|
|
201
203
|
if args:
|
|
202
|
-
|
|
204
|
+
try:
|
|
205
|
+
server_cfg["args"] = shlex.split(args, posix=(sys.platform != "win32"))
|
|
206
|
+
except Exception:
|
|
207
|
+
server_cfg["args"] = args.split()
|
|
203
208
|
if env_var:
|
|
204
209
|
server_cfg.setdefault("env", {})[env_var] = f"${{{env_var}}}"
|
|
205
210
|
if not global_:
|
|
@@ -146,6 +146,14 @@ def _write_profile(repo_name: str) -> None:
|
|
|
146
146
|
|
|
147
147
|
# ── local harvester ─────────────────────────────────────────────────────────
|
|
148
148
|
|
|
149
|
+
LOCAL_SYSTEM_RULES: frozenset[str] = frozenset({
|
|
150
|
+
"maintain_context.md",
|
|
151
|
+
"AGENTS.md",
|
|
152
|
+
"GEMINI.md",
|
|
153
|
+
"context.local.md",
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
|
|
149
157
|
def _sync_local_to_memory(project_dir: Path) -> int:
|
|
150
158
|
"""Harvest newly created local project rules & skills into central memory."""
|
|
151
159
|
harvested = 0
|
|
@@ -154,7 +162,10 @@ def _sync_local_to_memory(project_dir: Path) -> int:
|
|
|
154
162
|
if local_rules.exists():
|
|
155
163
|
(MEMORY_DIR / "rules").mkdir(parents=True, exist_ok=True)
|
|
156
164
|
for rfile in local_rules.glob("*.md"):
|
|
157
|
-
#
|
|
165
|
+
# Exclude project-specific local instructions from polluting central memory
|
|
166
|
+
if rfile.name in LOCAL_SYSTEM_RULES or rfile.name.endswith(".local.md"):
|
|
167
|
+
continue
|
|
168
|
+
|
|
158
169
|
dest = MEMORY_DIR / "rules" / rfile.name
|
|
159
170
|
if not dest.exists():
|
|
160
171
|
shutil.copy2(rfile, dest)
|
|
@@ -237,10 +237,20 @@ def update_global_plugin() -> int:
|
|
|
237
237
|
core_files = [
|
|
238
238
|
("plugin.json", plugin_dir / "plugin.json"),
|
|
239
239
|
("plugin/rules/AGENTS.md", rules_dir / "AGENTS.md"),
|
|
240
|
+
("plugin/rules/code-standards.md", rules_dir / "code-standards.md"),
|
|
241
|
+
("plugin/rules/security-boundaries.md", rules_dir / "security-boundaries.md"),
|
|
242
|
+
("plugin/rules/hub-satellite-architecture.md", rules_dir / "hub-satellite-architecture.md"),
|
|
243
|
+
("plugin/rules/readme-docs-sync.md", rules_dir / "readme-docs-sync.md"),
|
|
244
|
+
("plugin/rules/registry.json", rules_dir / "registry.json"),
|
|
240
245
|
("plugin/skills/auto-context/SKILL.md", skills_dir / "SKILL.md"),
|
|
246
|
+
("plugin/skills/browser-testing/SKILL.md", plugin_dir / "skills" / "browser-testing" / "SKILL.md"),
|
|
247
|
+
("plugin/skills/docker-ops/SKILL.md", plugin_dir / "skills" / "docker-ops" / "SKILL.md"),
|
|
248
|
+
("plugin/skills/git-workflow/SKILL.md", plugin_dir / "skills" / "git-workflow" / "SKILL.md"),
|
|
249
|
+
("plugin/skills/server-diagnostics/SKILL.md", plugin_dir / "skills" / "server-diagnostics" / "SKILL.md"),
|
|
241
250
|
]
|
|
242
251
|
|
|
243
252
|
for rel_path, dest_path in core_files:
|
|
253
|
+
dest_path.parent.mkdir(parents=True, exist_ok=True)
|
|
244
254
|
url = f"{config.RAW_GITHUB_BASE}/{rel_path}"
|
|
245
255
|
content = _download_text(url)
|
|
246
256
|
if content:
|
|
@@ -252,10 +262,16 @@ def update_global_plugin() -> int:
|
|
|
252
262
|
tmpl_dir = config.get_templates_dir()
|
|
253
263
|
fallback_map = {
|
|
254
264
|
"AGENTS.md": tmpl_dir / "AGENTS.template.md",
|
|
255
|
-
"SKILL.md": tmpl_dir / "skill.template.md",
|
|
265
|
+
"SKILL.md": tmpl_dir / "skills" / dest_path.parent.name / "SKILL.md" if (tmpl_dir / "skills" / dest_path.parent.name / "SKILL.md").exists() else tmpl_dir / "skill.template.md",
|
|
266
|
+
"code-standards.md": tmpl_dir / "rules" / "code-standards.md",
|
|
267
|
+
"security-boundaries.md": tmpl_dir / "rules" / "security-boundaries.md",
|
|
268
|
+
"hub-satellite-architecture.md": tmpl_dir / "rules" / "hub-satellite-architecture.md",
|
|
269
|
+
"readme-docs-sync.md": tmpl_dir / "rules" / "readme-docs-sync.md",
|
|
270
|
+
"registry.json": tmpl_dir / "rules" / "registry.json",
|
|
256
271
|
}
|
|
257
|
-
|
|
258
|
-
|
|
272
|
+
fb = fallback_map.get(dest_path.name)
|
|
273
|
+
if fb and fb.exists():
|
|
274
|
+
shutil.copy2(fb, dest_path)
|
|
259
275
|
console.print(f" [green][✓] Restored from bundled template:[/] {dest_path.name}")
|
|
260
276
|
updated_count += 1
|
|
261
277
|
|
|
@@ -10,22 +10,21 @@ from pathlib import Path
|
|
|
10
10
|
|
|
11
11
|
def get_templates_dir() -> Path:
|
|
12
12
|
"""
|
|
13
|
-
Return the templates directory in a
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
importlib.resources.files() is the PEP 451-compliant way to locate data
|
|
17
|
-
files that are bundled inside a Python package, regardless of whether the
|
|
18
|
-
package is installed as a wheel, a zip, or an editable source tree.
|
|
13
|
+
Return the templates directory in a crash-proof, persistent way
|
|
14
|
+
that works during development, wheel installs, and virtual environments.
|
|
19
15
|
"""
|
|
16
|
+
pkg_tmpl = Path(__file__).parent / "templates"
|
|
17
|
+
if pkg_tmpl.is_dir():
|
|
18
|
+
return pkg_tmpl
|
|
19
|
+
|
|
20
20
|
try:
|
|
21
|
-
# Python 3.9+ path — works in wheel and editable installs
|
|
22
21
|
ref = _pkg_resources.files("auto_context").joinpath("templates")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return p
|
|
22
|
+
if isinstance(ref, Path) and ref.is_dir():
|
|
23
|
+
return ref
|
|
26
24
|
except Exception:
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
return pkg_tmpl
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
# ── User home-relative roots ───────────────────────────────────────────────────
|
|
@@ -54,6 +54,8 @@ def root(
|
|
|
54
54
|
env: Annotated[Optional[str], typer.Option("--env", help="Environment variables (KEY=val,KEY2=val2).")] = None,
|
|
55
55
|
global_: Annotated[bool, typer.Option("--global", "-g", help="Target global plugin scope.")] = False,
|
|
56
56
|
force: Annotated[bool, typer.Option("--force", "-f", help="Overwrite existing files.")] = False,
|
|
57
|
+
append: Annotated[bool, typer.Option("--append", "-a", help="Append to existing domain rule.")] = False,
|
|
58
|
+
guideline: Annotated[Optional[str], typer.Option("--guideline", help="Guideline text to append to rule.")] = None,
|
|
57
59
|
dry_run: Annotated[bool, typer.Option("--dry-run", "-d", help="Preview without writing.")] = False,
|
|
58
60
|
scan: Annotated[bool, typer.Option("--scan", help="Run stack-adaptive scanner on target directory.")] = False,
|
|
59
61
|
version: bool = typer.Option(False, "--version", "-v", help="Show version and exit."),
|
|
@@ -69,7 +71,7 @@ def root(
|
|
|
69
71
|
try:
|
|
70
72
|
v = pkg_version("auto-context")
|
|
71
73
|
except Exception:
|
|
72
|
-
v = "1.0.
|
|
74
|
+
v = "1.0.7"
|
|
73
75
|
console.print(f"init-context v{v}")
|
|
74
76
|
raise typer.Exit()
|
|
75
77
|
|
|
@@ -78,7 +80,7 @@ def root(
|
|
|
78
80
|
|
|
79
81
|
# ── Legacy flag routing ────────────────────────────────────────────────────
|
|
80
82
|
if new_rule:
|
|
81
|
-
init_cmd.new_rule(name=new_rule, target=target, global_=global_, force=force, dry_run=dry_run)
|
|
83
|
+
init_cmd.new_rule(name=new_rule, target=target, global_=global_, force=force, append=append, guideline=guideline, dry_run=dry_run)
|
|
82
84
|
return
|
|
83
85
|
|
|
84
86
|
if new_skill:
|
|
@@ -404,9 +404,9 @@ def generate_satellites(project_dir: Path, force: bool = False) -> dict[str, Pat
|
|
|
404
404
|
write_idempotent(schema_path, schema_content, "Schema Satellite")
|
|
405
405
|
generated["schema"] = schema_path
|
|
406
406
|
|
|
407
|
-
# 3. gotchas.md (Critical Traps & Anti-Patterns —
|
|
407
|
+
# 3. gotchas.md (Critical Traps & Anti-Patterns — Preserved even with --force to prevent knowledge loss)
|
|
408
408
|
gotchas_path = satellites_dir / "gotchas.md"
|
|
409
|
-
if not gotchas_path.exists()
|
|
409
|
+
if not gotchas_path.exists():
|
|
410
410
|
gotchas_content = (
|
|
411
411
|
"# Critical Gotchas, Anti-Patterns & Architecture Invariants\n\n"
|
|
412
412
|
"> Institutional knowledge and non-obvious traps that cannot be guessed from reading code.\n\n"
|
|
@@ -414,8 +414,9 @@ def generate_satellites(project_dir: Path, force: bool = False) -> dict[str, Pat
|
|
|
414
414
|
"1. **Port Invariants:** Inspect discovered ports before binding local services.\n"
|
|
415
415
|
"2. **Secret Isolation:** Production secrets belong in `.env`; dummy dev accounts belong in `context.local.md`.\n"
|
|
416
416
|
"3. **State Boundaries:** Verify migrations before initiating build or release cycles.\n"
|
|
417
|
+
"4. **Verified Executable Runbooks:** Never accept or generate slash-separated placeholder commands (`cmd1 / cmd2`). Runbooks must only contain 100% executable commands parsed from manifests or verified CLI tools.\n"
|
|
417
418
|
)
|
|
418
419
|
write_idempotent(gotchas_path, gotchas_content, "Gotchas Satellite")
|
|
419
|
-
|
|
420
|
+
generated["gotchas"] = gotchas_path
|
|
420
421
|
|
|
421
422
|
return generated
|
|
@@ -33,20 +33,25 @@ PROHIBITED_EXTENSIONS: frozenset[str] = frozenset({
|
|
|
33
33
|
".pem", ".key", ".pkcs12", ".p12", ".pfx", ".kdbx",
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
+
IGNORE_AUDIT_DIRS: frozenset[str] = frozenset({
|
|
37
|
+
".git", "node_modules", ".venv", "venv", "__pycache__",
|
|
38
|
+
"dist", "build", ".next", ".turbo", ".nuxt", ".cache", ".idea", ".vscode"
|
|
39
|
+
})
|
|
40
|
+
|
|
36
41
|
# ── Secret patterns (name → compiled regex) ──────────────────────────────────
|
|
37
42
|
_RAW_PATTERNS: list[tuple[str, str]] = [
|
|
38
43
|
("GitHub Token", r"(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}"),
|
|
39
44
|
("GitHub Fine-grained PAT", r"github_pat_[A-Za-z0-9_]{50,}"),
|
|
40
45
|
("Stripe Live Key", r"sk_live_[0-9a-zA-Z]{24,}"),
|
|
41
|
-
("OpenAI API Key", r"sk-[a-zA-Z0-9_\-]{32,}"),
|
|
42
|
-
("Anthropic API Key", r"sk-ant-[a-zA-Z0-9_\-]{32,}"),
|
|
43
46
|
("OpenAI Project Key", r"sk-proj-[a-zA-Z0-9_\-]{40,}"),
|
|
47
|
+
("Anthropic API Key", r"sk-ant-[a-zA-Z0-9_\-]{32,}"),
|
|
48
|
+
("OpenAI API Key", r"sk-[a-zA-Z0-9_\-]{32,}"),
|
|
44
49
|
("Google API Key", r"AIza[0-9A-Za-z\-_]{35}"),
|
|
45
50
|
("AWS Access Key ID", r"AKIA[0-9A-Z]{16}"),
|
|
46
51
|
("Private Key Block", r"-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----"),
|
|
47
52
|
("Hardcoded Secret/Password",
|
|
48
53
|
r'(?i)(?:password|secret|api[_-]?key|access[_-]?token)\s*[:=]\s*[\'"]'
|
|
49
|
-
r'(?!(?:YOUR_|REPLACE_|MOCK_|TEST_|DUMMY_|\{\{
|
|
54
|
+
r'(?!(?:YOUR_|REPLACE_|MOCK_|TEST_|DUMMY_|\{\{|\<|\$\{))'
|
|
50
55
|
r'[A-Za-z0-9_\-\.\$\!\@\#\%\^\&\*\(\)\+]{8,}[\'"]'),
|
|
51
56
|
]
|
|
52
57
|
|
|
@@ -120,8 +125,8 @@ def audit_path(path: Path, *, single_file: bool = False) -> list[Violation]:
|
|
|
120
125
|
violations.extend(_scan_file(path))
|
|
121
126
|
else:
|
|
122
127
|
for child in path.rglob("*"):
|
|
123
|
-
# Skip
|
|
124
|
-
if
|
|
128
|
+
# Skip VCS and bulky dependency directories
|
|
129
|
+
if any(part in IGNORE_AUDIT_DIRS for part in child.parts):
|
|
125
130
|
continue
|
|
126
131
|
if child.is_file():
|
|
127
132
|
violations.extend(_scan_file(child))
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/AGENTS.template.md
RENAMED
|
@@ -45,3 +45,8 @@ Never blindly delete or truncate context:
|
|
|
45
45
|
- `init-context -s <name> [-g]`: Create skill.
|
|
46
46
|
- `init-context update`: Safely sync public rules and upstream capabilities (non-breaking).
|
|
47
47
|
- `init-context memory push`: Push updates to central memory.
|
|
48
|
+
|
|
49
|
+
### 7. First-Principles Gatekeeper: Idempotency, KISS, DRY & The Brutal Truth Filter
|
|
50
|
+
- **Strict Idempotency Proof ($f(f(x)) = f(x)$):** All code generation, filesystem operations, and context sync commands must be 100% idempotent. Running them once or 100 times must yield the exact same deterministic state without duplication or side-effects.
|
|
51
|
+
- **Modular, KISS & DRY:** Maintain clean separation of concerns. Prohibit copy-paste duplication, unnecessary abstractions, and monolithic bloat across all project code and context.
|
|
52
|
+
- **The Brutal Truth Filter:** Every idea, design proposal, or architectural suggestion must pass first-principles scrutiny. If an idea or approach fails "The Brutal Truth Filter" (adds needless complexity, breaks DRY/KISS, or solves the wrong problem), **immediately DROP the idea** and proactively notify the user with clear technical rationale instead of blindly building flawed requests.
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/GEMINI.template.md
RENAMED
|
@@ -45,3 +45,8 @@ Never blindly delete or truncate context:
|
|
|
45
45
|
- `init-context -s <name> [-g]`: Create skill.
|
|
46
46
|
- `init-context update`: Safely sync public rules and upstream capabilities (non-breaking).
|
|
47
47
|
- `init-context memory push`: Push updates to central memory.
|
|
48
|
+
|
|
49
|
+
### 7. First-Principles Gatekeeper: Idempotency, KISS, DRY & The Brutal Truth Filter
|
|
50
|
+
- **Strict Idempotency Proof ($f(f(x)) = f(x)$):** All code generation, filesystem operations, and context sync commands must be 100% idempotent. Running them once or 100 times must yield the exact same deterministic state without duplication or side-effects.
|
|
51
|
+
- **Modular, KISS & DRY:** Maintain clean separation of concerns. Prohibit copy-paste duplication, unnecessary abstractions, and monolithic bloat across all project code and context.
|
|
52
|
+
- **The Brutal Truth Filter:** Every idea, design proposal, or architectural suggestion must pass first-principles scrutiny. If an idea or approach fails "The Brutal Truth Filter" (adds needless complexity, breaks DRY/KISS, or solves the wrong problem), **immediately DROP the idea** and proactively notify the user with clear technical rationale instead of blindly building flawed requests.
|
|
@@ -46,3 +46,8 @@ Never blindly delete or truncate context:
|
|
|
46
46
|
- `init-context scan`: Refresh stack-adaptive satellites (`routes.md`, `schema.md`, `gotchas.md`).
|
|
47
47
|
- `init-context update`: Safely sync public rules and upstream capabilities (non-breaking).
|
|
48
48
|
- `init-context memory push`: Push updates to central memory.
|
|
49
|
+
|
|
50
|
+
### 7. First-Principles Gatekeeper: Idempotency, KISS, DRY & The Brutal Truth Filter
|
|
51
|
+
- **Strict Idempotency Proof ($f(f(x)) = f(x)$):** All code generation, filesystem operations, and context sync commands must be 100% idempotent. Running them once or 100 times must yield the exact same deterministic state without duplication or side-effects.
|
|
52
|
+
- **Modular, KISS & DRY:** Maintain clean separation of concerns. Prohibit copy-paste duplication, unnecessary abstractions, and monolithic bloat across all project code and context.
|
|
53
|
+
- **The Brutal Truth Filter:** Every idea, design proposal, or architectural suggestion must pass first-principles scrutiny. If an idea or approach fails "The Brutal Truth Filter" (adds needless complexity, breaks DRY/KISS, or solves the wrong problem), **immediately DROP the idea** and proactively notify the user with clear technical rationale instead of blindly building flawed requests.
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rules/code-standards.md
RENAMED
|
@@ -22,3 +22,9 @@ Maintain readable, maintainable, modular, and type-safe codebases with clear err
|
|
|
22
22
|
- Log actionable error messages that include relevant context (e.g. invalid inputs, resource identifiers).
|
|
23
23
|
4. **Conventional Git Commits:**
|
|
24
24
|
- Write semantic commit messages (`feat:`, `fix:`, `docs:`, `refactor:`, `chore:`).
|
|
25
|
+
5. **Static Type Annotations & Null Safety:**
|
|
26
|
+
- Enforce explicit type annotations for public functions, parameters, and return types.
|
|
27
|
+
- Prohibit unchecked null / undefined dereferencing.
|
|
28
|
+
6. **Named Constants Over Magic Values:**
|
|
29
|
+
- Replace literal strings and magic numbers with descriptive, uppercase module-level constants.
|
|
30
|
+
7. **Immutable Data Structures**
|
|
@@ -23,8 +23,8 @@ Prevent monolithic context file bloat, eliminate token waste, ensure 100% idempo
|
|
|
23
23
|
- User-written notes, secrets, and manual entries outside anchored zones must remain 100% untouched.
|
|
24
24
|
- Check content hashes before disk writes to avoid unnecessary I/O.
|
|
25
25
|
|
|
26
|
-
3. **The Brutal Truth Filter (Zero Dead Logs):**
|
|
27
|
-
- If an idea, log entry, or feature fails first-principles scrutiny,
|
|
26
|
+
3. **The Brutal Truth Filter (Zero Dead Logs & Flawed Ideas):**
|
|
27
|
+
- If an idea, design approach, log entry, or feature proposal fails first-principles scrutiny, breaks KISS/DRY principles, or does not pass 'The Brutal Truth Filter', **immediately drop the idea and notify the user** with honest technical reasons.
|
|
28
28
|
- Prohibit chronological bug cemeteries (`history.md` dumps of trivial solved bugs).
|
|
29
29
|
- In their place, maintain **`gotchas.md`**: high-impact institutional knowledge, non-obvious architecture traps, port collisions, and edge-case invariants.
|
|
30
30
|
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"last_updated": "2026-11-02",
|
|
4
|
+
"description": "Registry of unique rules and guidelines to prevent duplicates and enforce domain consolidation.",
|
|
5
|
+
"domains": {
|
|
6
|
+
"code-standards": {
|
|
7
|
+
"file": "code-standards.md",
|
|
8
|
+
"name": "Code Quality & Architecture Standards",
|
|
9
|
+
"description": "Clean code, defensive programming, typing, naming, and error handling",
|
|
10
|
+
"rules": [
|
|
11
|
+
{
|
|
12
|
+
"id": "defensive-coding-early-return",
|
|
13
|
+
"title": "Defensive Coding & Early Return",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"guard clauses",
|
|
16
|
+
"early return",
|
|
17
|
+
"nested indentation",
|
|
18
|
+
"input validation",
|
|
19
|
+
"defensive coding"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "clean-code-srp",
|
|
24
|
+
"title": "Clean Code & Self-Documenting Logic",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"single responsibility",
|
|
27
|
+
"srp",
|
|
28
|
+
"clean code",
|
|
29
|
+
"variable names",
|
|
30
|
+
"docstrings"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "structured-error-handling",
|
|
35
|
+
"title": "Structured Error Handling",
|
|
36
|
+
"keywords": [
|
|
37
|
+
"exception handling",
|
|
38
|
+
"empty catch",
|
|
39
|
+
"error logging",
|
|
40
|
+
"try catch"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "conventional-git-commits",
|
|
45
|
+
"title": "Conventional Git Commits",
|
|
46
|
+
"keywords": [
|
|
47
|
+
"commit messages",
|
|
48
|
+
"feat",
|
|
49
|
+
"fix",
|
|
50
|
+
"docs",
|
|
51
|
+
"chore",
|
|
52
|
+
"refactor"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "static-type-annotations",
|
|
57
|
+
"title": "Static Type Annotations & Null Safety",
|
|
58
|
+
"keywords": [
|
|
59
|
+
"type hints",
|
|
60
|
+
"type annotations",
|
|
61
|
+
"null safety",
|
|
62
|
+
"typing",
|
|
63
|
+
"null pointer"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "named-constants-over-magic-values",
|
|
68
|
+
"title": "Named Constants Over Magic Values",
|
|
69
|
+
"keywords": [
|
|
70
|
+
"magic numbers",
|
|
71
|
+
"literal strings",
|
|
72
|
+
"constants",
|
|
73
|
+
"magic values"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "immutable-data-structures",
|
|
78
|
+
"title": "Immutable Data Structures",
|
|
79
|
+
"keywords": [
|
|
80
|
+
"immutable",
|
|
81
|
+
"data",
|
|
82
|
+
"structures"
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"security-boundaries": {
|
|
88
|
+
"file": "security-boundaries.md",
|
|
89
|
+
"name": "Security Boundaries & Secret Safety",
|
|
90
|
+
"description": "Secret protection, API keys, sandbox isolation, and network exposure",
|
|
91
|
+
"rules": [
|
|
92
|
+
{
|
|
93
|
+
"id": "zero-hardcoded-secrets",
|
|
94
|
+
"title": "Zero Hardcoded Secrets",
|
|
95
|
+
"keywords": [
|
|
96
|
+
"api keys",
|
|
97
|
+
"passwords",
|
|
98
|
+
"tokens",
|
|
99
|
+
"private keys",
|
|
100
|
+
"secrets",
|
|
101
|
+
".env"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "local-sandbox-test-data-isolation",
|
|
106
|
+
"title": "Local Sandbox Test Data Isolation",
|
|
107
|
+
"keywords": [
|
|
108
|
+
"context.local.md",
|
|
109
|
+
"mock credentials",
|
|
110
|
+
"dummy logins",
|
|
111
|
+
"test accounts",
|
|
112
|
+
"git-ignored"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"id": "public-exposure-boundaries",
|
|
117
|
+
"title": "Public Exposure Boundaries",
|
|
118
|
+
"keywords": [
|
|
119
|
+
"port binding",
|
|
120
|
+
"127.0.0.1",
|
|
121
|
+
"localhost",
|
|
122
|
+
"exposure",
|
|
123
|
+
"tunneling"
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
"hub-satellite-architecture": {
|
|
129
|
+
"file": "hub-satellite-architecture.md",
|
|
130
|
+
"name": "Hub & Satellite Modular Architecture & Idempotency Proof",
|
|
131
|
+
"description": "Context budget, satelittes, deterministic idempotency, and gotchas invariants",
|
|
132
|
+
"rules": [
|
|
133
|
+
{
|
|
134
|
+
"id": "hub-satellite-token-budget",
|
|
135
|
+
"title": "Hub & Satellite Pattern (Strict Token Budget)",
|
|
136
|
+
"keywords": [
|
|
137
|
+
"context.md",
|
|
138
|
+
"satellites",
|
|
139
|
+
"routes.md",
|
|
140
|
+
"schema.md",
|
|
141
|
+
"gotchas.md",
|
|
142
|
+
"token budget"
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "strict-idempotency-proof",
|
|
147
|
+
"title": "Strict Idempotency Proof",
|
|
148
|
+
"keywords": [
|
|
149
|
+
"idempotency",
|
|
150
|
+
"anchored blocks",
|
|
151
|
+
"re-running",
|
|
152
|
+
"deterministic",
|
|
153
|
+
"hash check"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "brutal-truth-filter",
|
|
158
|
+
"title": "The Brutal Truth Filter (Zero Dead Logs)",
|
|
159
|
+
"keywords": [
|
|
160
|
+
"gotchas.md",
|
|
161
|
+
"anti-patterns",
|
|
162
|
+
"dead logs",
|
|
163
|
+
"bug cemeteries",
|
|
164
|
+
"invariants"
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"id": "kiss-dry-heuristics",
|
|
169
|
+
"title": "KISS & DRY Heuristics",
|
|
170
|
+
"keywords": [
|
|
171
|
+
"convention heuristics",
|
|
172
|
+
"graceful degradation",
|
|
173
|
+
"lightweight scanners"
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
"readme-docs-sync": {
|
|
179
|
+
"file": "readme-docs-sync.md",
|
|
180
|
+
"name": "Mandatory README & Documentation Synchronization",
|
|
181
|
+
"description": "Documentation synchronization for CLI commands, options, and workflows",
|
|
182
|
+
"rules": [
|
|
183
|
+
{
|
|
184
|
+
"id": "zero-undocumented-features",
|
|
185
|
+
"title": "Zero Undocumented Features",
|
|
186
|
+
"keywords": [
|
|
187
|
+
"readme",
|
|
188
|
+
"documentation",
|
|
189
|
+
"docs sync",
|
|
190
|
+
"bengali guide",
|
|
191
|
+
"options table"
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"id": "clear-executable-instructions",
|
|
196
|
+
"title": "Clear & Executable Instructions",
|
|
197
|
+
"keywords": [
|
|
198
|
+
"executable commands",
|
|
199
|
+
"cli examples",
|
|
200
|
+
"options tables",
|
|
201
|
+
"syntax"
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"id": "safety-non-breaking-boundaries",
|
|
206
|
+
"title": "Safety & Non-Breaking Boundaries",
|
|
207
|
+
"keywords": [
|
|
208
|
+
"non-breaking",
|
|
209
|
+
"protection guarantees",
|
|
210
|
+
"custom rules preserve"
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"id": "release-version-alignment",
|
|
215
|
+
"title": "Release Version Alignment",
|
|
216
|
+
"keywords": [
|
|
217
|
+
"version bump",
|
|
218
|
+
"pyproject.toml",
|
|
219
|
+
"tags",
|
|
220
|
+
"release badges"
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/context.template.md
RENAMED
|
File without changes
|
|
File without changes
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/profile.template.md
RENAMED
|
File without changes
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/rule.template.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{auto_context_cli-1.0.5 → auto_context_cli-1.0.7}/src/auto_context/templates/skill.template.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|