kortext 1.0.0 → 2.2.0

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.
Files changed (140) hide show
  1. package/AGENTS.md +28 -0
  2. package/README.md +91 -0
  3. package/agents/backend-developer.md +132 -0
  4. package/agents/compliance-expert.md +106 -0
  5. package/agents/copywriter.md +122 -0
  6. package/agents/db-admin.md +117 -0
  7. package/agents/delivery-manager.md +121 -0
  8. package/agents/designer.md +108 -0
  9. package/agents/devops-engineer.md +141 -0
  10. package/agents/engineering-manager.md +208 -0
  11. package/agents/frontend-developer.md +174 -0
  12. package/agents/growth-expert.md +115 -0
  13. package/agents/operation-manager.md +122 -0
  14. package/agents/product-manager.md +114 -0
  15. package/agents/qa-engineer.md +126 -0
  16. package/agents/security-engineer.md +119 -0
  17. package/hooks/audit-logger.sh +25 -0
  18. package/hooks/auto-locker.sh +74 -0
  19. package/hooks/auto-unlocker.sh +17 -0
  20. package/hooks/backlog-sync-guard.sh +12 -0
  21. package/hooks/branch-guard.sh +32 -0
  22. package/hooks/commit-msg-guard.sh +43 -0
  23. package/hooks/git-pre-commit.sh +76 -0
  24. package/hooks/git-pre-push.sh +17 -0
  25. package/hooks/handover-guard.sh +33 -0
  26. package/hooks/kortext-init.sh +194 -0
  27. package/hooks/kortext-lib.sh +141 -0
  28. package/hooks/lint-guard.sh +50 -0
  29. package/hooks/secret-scanner.sh +89 -0
  30. package/hooks/size-guard.sh +48 -0
  31. package/hooks/snapshot-guard.sh +39 -0
  32. package/hooks/write-guard.sh +77 -0
  33. package/package.json +23 -6
  34. package/rules/behavior.md +252 -0
  35. package/rules/branching.md +82 -0
  36. package/rules/commands.md +112 -0
  37. package/rules/emergency.md +160 -0
  38. package/rules/mcp.md +47 -0
  39. package/rules/models.md +93 -0
  40. package/scripts/kortext-backlog-add.py +123 -0
  41. package/scripts/kortext-backlog-health.py +112 -0
  42. package/scripts/kortext-backlog-sync.py +117 -0
  43. package/scripts/kortext-bulk-plan.py +63 -0
  44. package/scripts/kortext-cli.py +295 -0
  45. package/scripts/kortext-consistency-check.py +74 -0
  46. package/scripts/kortext-context-check.py +146 -0
  47. package/scripts/kortext-handover.py +107 -0
  48. package/scripts/kortext-item-check.py +61 -0
  49. package/scripts/kortext-item-start.py +70 -0
  50. package/scripts/kortext-item-transition.py +78 -0
  51. package/scripts/kortext-lock.py +174 -0
  52. package/scripts/kortext-session-start.py +127 -0
  53. package/scripts/lock_kortext.sh +34 -0
  54. package/settings/.claude-settings.template.json +48 -0
  55. package/settings/CHANGELOG.md +176 -0
  56. package/settings/INTEGRATION-MAP.md +276 -0
  57. package/settings/README.md +255 -0
  58. package/settings/USER-GUIDE.md +502 -0
  59. package/settings/VERSION +1 -0
  60. package/settings/config.md +8 -0
  61. package/settings/runtime-adapters.md +104 -0
  62. package/skills/backend-developer/.gitkeep +0 -0
  63. package/skills/compliance-expert/.gitkeep +0 -0
  64. package/skills/copywriter/.gitkeep +0 -0
  65. package/skills/db-admin/.gitkeep +0 -0
  66. package/skills/delivery-manager/.gitkeep +0 -0
  67. package/skills/designer/.gitkeep +0 -0
  68. package/skills/devops-engineer/.gitkeep +0 -0
  69. package/skills/engineering-manager/.gitkeep +0 -0
  70. package/skills/frontend-developer/.gitkeep +0 -0
  71. package/skills/growth-expert/.gitkeep +0 -0
  72. package/skills/operation-manager/.gitkeep +0 -0
  73. package/skills/product-manager/.gitkeep +0 -0
  74. package/skills/qa-engineer/.gitkeep +0 -0
  75. package/skills/security-engineer/.gitkeep +0 -0
  76. package/workflows/00-kortext-setup.md +53 -0
  77. package/workflows/01a-analysis-pipeline.md +117 -0
  78. package/workflows/01b-onboarding-pipeline.md +110 -0
  79. package/workflows/02-planning-pipeline.md +146 -0
  80. package/workflows/02b-spike-workflow.md +120 -0
  81. package/workflows/03-environment-setup.md +99 -0
  82. package/workflows/04-development-cycle.md +203 -0
  83. package/workflows/05-test-cycle.md +123 -0
  84. package/workflows/06-deployment-cycle.md +224 -0
  85. package/workflows/07-rollback-pipeline.md +203 -0
  86. package/workflows/08-hotfix-pipeline.md +196 -0
  87. package/workflows/09-maintenance-cycle.md +133 -0
  88. package/workspace/archive/.gitkeep +0 -0
  89. package/workspace/backups/.gitkeep +0 -0
  90. package/workspace/memory/backlog/.gitkeep +0 -0
  91. package/workspace/memory/backlog/BXX-[bug-name].md +2 -0
  92. package/workspace/memory/backlog/DXX-[debt-name].md +2 -0
  93. package/workspace/memory/backlog/README.md +31 -0
  94. package/workspace/memory/backlog/TXX-[task-name].md +2 -0
  95. package/workspace/memory/backlog/debt-dashboard.md +3 -0
  96. package/workspace/memory/backlog/epic-dashboard.md +10 -0
  97. package/workspace/memory/backlog/version-dashboard.md +7 -0
  98. package/workspace/memory/context/.gitkeep +0 -0
  99. package/workspace/memory/context/README.md +35 -0
  100. package/workspace/memory/context/[agent-name]-active.md +2 -0
  101. package/workspace/memory/decisions.md +17 -0
  102. package/workspace/memory/handover.md +40 -0
  103. package/workspace/memory/learned.md +21 -0
  104. package/workspace/references/access.md +47 -0
  105. package/workspace/references/api-reference.md +59 -0
  106. package/workspace/references/blueprint.md +29 -0
  107. package/workspace/references/content-strategy.md +39 -0
  108. package/workspace/references/db-schema.md +51 -0
  109. package/workspace/references/design-system.md +107 -0
  110. package/workspace/references/dictionary.md +42 -0
  111. package/workspace/references/file-system.md +42 -0
  112. package/workspace/references/growth-strategy.md +46 -0
  113. package/workspace/references/legal-strategy.md +35 -0
  114. package/workspace/references/required-skills.md +11 -0
  115. package/workspace/references/security-rules.md +34 -0
  116. package/workspace/references/tech-stack.md +49 -0
  117. package/workspace/references/test-strategy.md +48 -0
  118. package/workspace/reports/analysis-reports.md +40 -0
  119. package/workspace/reports/content-reports.md +29 -0
  120. package/workspace/reports/delivery-reports.md +26 -0
  121. package/workspace/reports/growth-reports.md +9 -0
  122. package/workspace/reports/legal-reports.md +29 -0
  123. package/workspace/reports/product-requirements.md +28 -0
  124. package/workspace/reports/release-notes.md +20 -0
  125. package/workspace/reports/security-reports.md +27 -0
  126. package/workspace/reports/status-reports.md +48 -0
  127. package/workspace/reports/tech-requirements.md +30 -0
  128. package/workspace/reports/test-reports.md +61 -0
  129. package/workspace/templates/BXX-[bug-name].md +34 -0
  130. package/workspace/templates/DXX-[debt-name].md +35 -0
  131. package/workspace/templates/EXX-[epic-name].md +48 -0
  132. package/workspace/templates/HXX-[hotfix-name].md +73 -0
  133. package/workspace/templates/SXX-[spike-name].md +51 -0
  134. package/workspace/templates/TXX-[task-name].md +34 -0
  135. package/workspace/templates/[agent-name]-active.md +4 -0
  136. package/workspace/templates/[original-name]_[YYYY-MM-DD_HHMMSS].md +5 -0
  137. package/workspace/templates/adr-XXX.md +66 -0
  138. package/workspace/templates/debt-dashboard.md +10 -0
  139. package/workspace/templates/epic-dashboard.md +10 -0
  140. package/workspace/templates/version-dashboard.md +10 -0
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import re
6
+ import shutil
7
+ import subprocess
8
+ from datetime import datetime
9
+ from pathlib import Path
10
+
11
+
12
+ BACKLOG_ROOT = Path("workspace/memory/backlog")
13
+ CONTEXT_ROOT = Path("workspace/memory/context")
14
+
15
+
16
+ def update_status(content: str, status: str) -> str:
17
+ return re.sub(r"> \*\*Status:\*\* .*", f"> **Status:** {status}", content, count=1)
18
+
19
+
20
+ def _atomic_commit(message: str, paths: list[str]) -> None:
21
+ # Kortext atomic operation: dosyaları add edip commit'ler.
22
+ # Git repo değilse, değişiklik yoksa veya hook reddederse sessizce geç.
23
+ if not shutil.which("git"):
24
+ return
25
+ try:
26
+ subprocess.run(["git", "add", "--", *paths], check=True, capture_output=True)
27
+ subprocess.run(
28
+ ["git", "commit", "-m", message, "--", *paths],
29
+ check=True,
30
+ capture_output=True,
31
+ )
32
+ except subprocess.CalledProcessError:
33
+ return
34
+
35
+
36
+ def main() -> None:
37
+ parser = argparse.ArgumentParser(description="Start a Kortext backlog item")
38
+ parser.add_argument("item_path")
39
+ parser.add_argument("--agent", required=True, help="e.g. backend-developer")
40
+ parser.add_argument("--summary", required=True)
41
+ parser.add_argument("--no-commit", action="store_true", help="Atomic git commit'i atla")
42
+ args = parser.parse_args()
43
+
44
+ item_path = Path(args.item_path)
45
+ if not item_path.exists():
46
+ raise SystemExit(f"Hata: Dosya bulunamadı: {item_path}")
47
+
48
+ item_id = item_path.stem.split("-", 1)[0]
49
+ content = item_path.read_text()
50
+ item_path.write_text(update_status(content, "In Progress"))
51
+
52
+ CONTEXT_ROOT.mkdir(parents=True, exist_ok=True)
53
+ timestamp = datetime.now().strftime("%H:%M")
54
+ context_path = CONTEXT_ROOT / f"{args.agent}-active.md"
55
+ context_path.write_text(
56
+ f"### +{args.agent} | {item_id} | In Progress | {timestamp} | {args.summary}\n"
57
+ )
58
+
59
+ print(f"✅ Başlatıldı: {item_id}")
60
+ print(f"✅ Context güncellendi: {context_path}")
61
+
62
+ if not args.no_commit:
63
+ _atomic_commit(
64
+ f"chore(kortext): start {item_id} [skip ci]",
65
+ [str(item_path), str(context_path)],
66
+ )
67
+
68
+
69
+ if __name__ == "__main__":
70
+ main()
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import re
6
+ import shutil
7
+ import subprocess
8
+ from pathlib import Path
9
+
10
+
11
+ ALLOWED_TRANSITIONS = {
12
+ "To Do": {"In Progress"},
13
+ "In Progress": {"Test"},
14
+ "Test": {"In Progress", "Review"},
15
+ "Review": {"In Progress", "Done"},
16
+ "Done": set(),
17
+ }
18
+
19
+
20
+ def read_status(content: str) -> str:
21
+ match = re.search(r"> \*\*Status:\*\* (.+)", content)
22
+ if not match:
23
+ raise SystemExit("Hata: Item dosyasında status alanı bulunamadı.")
24
+ return match.group(1).strip()
25
+
26
+
27
+ def write_status(content: str, status: str) -> str:
28
+ return re.sub(r"> \*\*Status:\*\* .*", f"> **Status:** {status}", content, count=1)
29
+
30
+
31
+ def _atomic_commit(message: str, paths: list[str]) -> None:
32
+ # Kortext atomic operation: dosyaları add edip commit'ler.
33
+ if not shutil.which("git"):
34
+ return
35
+ try:
36
+ subprocess.run(["git", "add", "--", *paths], check=True, capture_output=True)
37
+ subprocess.run(
38
+ ["git", "commit", "-m", message, "--", *paths],
39
+ check=True,
40
+ capture_output=True,
41
+ )
42
+ except subprocess.CalledProcessError:
43
+ return
44
+
45
+
46
+ def main() -> None:
47
+ parser = argparse.ArgumentParser(description="Transition a Kortext item status")
48
+ parser.add_argument("item_path")
49
+ parser.add_argument("--to", required=True, choices=sorted(ALLOWED_TRANSITIONS))
50
+ parser.add_argument("--no-commit", action="store_true", help="Atomic git commit'i atla")
51
+ args = parser.parse_args()
52
+
53
+ item_path = Path(args.item_path)
54
+ if not item_path.exists():
55
+ raise SystemExit(f"Hata: Dosya bulunamadı: {item_path}")
56
+
57
+ content = item_path.read_text()
58
+ current = read_status(content)
59
+ allowed = ALLOWED_TRANSITIONS.get(current)
60
+ if allowed is None:
61
+ raise SystemExit(f"Hata: Geçersiz mevcut status: {current}")
62
+ if args.to not in allowed:
63
+ raise SystemExit(f"Hata: Geçersiz geçiş: {current} -> {args.to}")
64
+
65
+ item_path.write_text(write_status(content, args.to))
66
+ print(f"✅ Geçiş yapıldı: {current} -> {args.to}")
67
+
68
+ if not args.no_commit:
69
+ item_id = item_path.stem.split("-", 1)[0]
70
+ slug = args.to.lower().replace(" ", "-")
71
+ _atomic_commit(
72
+ f"chore(kortext): transition {item_id} -> {slug} [skip ci]",
73
+ [str(item_path)],
74
+ )
75
+
76
+
77
+ if __name__ == "__main__":
78
+ main()
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Kortext File Lock
4
+ -----------------
5
+ Paylaşımlı dosyalara (handover.md, epic-dashboard.md vb.) eş zamanlı yazma
6
+ çakışmasını önlemek için dosya kilidi mekanizması sağlar.
7
+
8
+ Kullanım:
9
+ # Kilitlemek için:
10
+ python kortext-lock.py acquire --file workspace/memory/handover.md --agent backend-developer
11
+
12
+ # Kilidi serbest bırakmak için:
13
+ python kortext-lock.py release --file workspace/memory/handover.md
14
+
15
+ # Kilit durumunu kontrol etmek için:
16
+ python kortext-lock.py status --file workspace/memory/handover.md
17
+ """
18
+ from __future__ import annotations
19
+
20
+ import argparse
21
+ import os
22
+ import sys
23
+ from datetime import datetime, timedelta
24
+ from pathlib import Path
25
+
26
+
27
+ ROOT = Path(__file__).resolve().parents[1]
28
+ LOCK_DIR = ROOT / "workspace/.locks"
29
+
30
+ # Saniye cinsinden lock timeout. Env var ile override edilebilir.
31
+ # Default: 300 saniye = 5 dakika.
32
+ LOCK_TIMEOUT_SECONDS = int(os.environ.get("KORTEXT_LOCK_TIMEOUT_SECONDS", "300"))
33
+ LOCK_TIMEOUT_MINUTES = LOCK_TIMEOUT_SECONDS / 60
34
+
35
+
36
+ def lock_path(target_file: str) -> Path:
37
+ safe_name = target_file.replace("/", "_").replace("\\", "_")
38
+ return LOCK_DIR / f"{safe_name}.lock"
39
+
40
+
41
+ def acquire(target_file: str, agent: str) -> None:
42
+ LOCK_DIR.mkdir(parents=True, exist_ok=True)
43
+ lp = lock_path(target_file)
44
+
45
+ # Stale lock kontrolü — saniye bazında karşılaştırılır.
46
+ if lp.exists():
47
+ content = lp.read_text(errors="ignore")
48
+ lines = content.splitlines()
49
+ # Zaman damgasını parse et
50
+ time_line = next((l for l in lines if l.startswith("time:")), None)
51
+ if time_line:
52
+ try:
53
+ lock_time = datetime.fromisoformat(time_line.split(":", 1)[1].strip())
54
+ age = datetime.now() - lock_time
55
+ if age > timedelta(seconds=LOCK_TIMEOUT_SECONDS):
56
+ print(
57
+ f"⚠️ Stale kilit tespit edildi ({round(age.total_seconds()/60, 1)} dakika). "
58
+ f"Otomatik kaldırılıyor..."
59
+ )
60
+ lp.unlink()
61
+ else:
62
+ owner_line = next((l for l in lines if l.startswith("agent:")), "agent: bilinmiyor")
63
+ owner = owner_line.split(":", 1)[1].strip()
64
+ # Türkçe hata mesajı stderr'e — fail durumunda exit 1.
65
+ print(
66
+ f"🔒 Kilit alınamadı: {target_file} — sahibi: +{owner}, "
67
+ f"son güncelleme: {lock_time.strftime('%Y-%m-%d %H:%M:%S')}",
68
+ file=sys.stderr,
69
+ )
70
+ print(
71
+ f" Otomatik açılır: {round(LOCK_TIMEOUT_MINUTES, 1)} dakika sonra",
72
+ file=sys.stderr,
73
+ )
74
+ sys.exit(1)
75
+ except (ValueError, IndexError):
76
+ # Parse edilemezse stale say
77
+ lp.unlink()
78
+
79
+ # Kilidi al
80
+ now = datetime.now()
81
+ lp.write_text(
82
+ f"agent: {agent}\n"
83
+ f"file: {target_file}\n"
84
+ f"time: {now.isoformat()}\n"
85
+ )
86
+ print(f"✅ Kilit alındı: {target_file} (+{agent})")
87
+
88
+
89
+ def release(target_file: str) -> None:
90
+ lp = lock_path(target_file)
91
+ if lp.exists():
92
+ lp.unlink()
93
+ print(f"✅ Kilit kaldırıldı: {target_file}")
94
+ else:
95
+ print(f"ℹ️ Kilit zaten yok: {target_file}")
96
+
97
+
98
+ def status(target_file: str) -> None:
99
+ lp = lock_path(target_file)
100
+ if not lp.exists():
101
+ print(f"🔓 Serbest: {target_file}")
102
+ return
103
+
104
+ content = lp.read_text(errors="ignore")
105
+ lines = content.splitlines()
106
+ agent_line = next((l for l in lines if l.startswith("agent:")), "agent: bilinmiyor")
107
+ time_line = next((l for l in lines if l.startswith("time:")), None)
108
+ agent = agent_line.split(":", 1)[1].strip()
109
+ if time_line:
110
+ try:
111
+ lock_time = datetime.fromisoformat(time_line.split(":", 1)[1].strip())
112
+ age = datetime.now() - lock_time
113
+ stale = age > timedelta(seconds=LOCK_TIMEOUT_SECONDS)
114
+ stale_flag = " ⚠️ STALE" if stale else ""
115
+ print(f"🔒 Kilitli: {target_file}")
116
+ print(f" Sahibi: +{agent}")
117
+ print(f" Süre : {round(age.total_seconds()/60, 1)} dakika{stale_flag}")
118
+ except (ValueError, IndexError):
119
+ print(f"🔒 Kilitli (parse hatası): {target_file}")
120
+ else:
121
+ print(f"🔒 Kilitli: {target_file} (+{agent})")
122
+
123
+
124
+ def list_all() -> None:
125
+ if not LOCK_DIR.exists():
126
+ print("ℹ️ Aktif kilit yok.")
127
+ return
128
+ locks = list(LOCK_DIR.glob("*.lock"))
129
+ if not locks:
130
+ print("ℹ️ Aktif kilit yok.")
131
+ return
132
+ print(f"🔒 Aktif kilitler ({len(locks)} adet):")
133
+ for lp in sorted(locks):
134
+ content = lp.read_text(errors="ignore")
135
+ lines = content.splitlines()
136
+ agent_line = next((l for l in lines if l.startswith("agent:")), "agent: ?")
137
+ file_line = next((l for l in lines if l.startswith("file:")), "file: ?")
138
+ agent = agent_line.split(":", 1)[1].strip()
139
+ file_ref = file_line.split(":", 1)[1].strip()
140
+ print(f" • {file_ref} → +{agent}")
141
+
142
+
143
+ def main() -> None:
144
+ parser = argparse.ArgumentParser(description="Kortext File Lock Manager")
145
+ sub = parser.add_subparsers(dest="command")
146
+
147
+ acq = sub.add_parser("acquire", help="Dosya kilidi al")
148
+ acq.add_argument("--file", required=True, help="Kilitlenecek dosya yolu")
149
+ acq.add_argument("--agent", required=True, help="Kilidi alan ajan (örn: backend-developer)")
150
+
151
+ rel = sub.add_parser("release", help="Dosya kilidini kaldır")
152
+ rel.add_argument("--file", required=True, help="Kilidi kaldırılacak dosya yolu")
153
+
154
+ stat = sub.add_parser("status", help="Dosya kilit durumu")
155
+ stat.add_argument("--file", required=True, help="Kontrol edilecek dosya yolu")
156
+
157
+ sub.add_parser("list", help="Tüm aktif kilitleri listele")
158
+
159
+ args = parser.parse_args()
160
+
161
+ if args.command == "acquire":
162
+ acquire(args.file, args.agent)
163
+ elif args.command == "release":
164
+ release(args.file)
165
+ elif args.command == "status":
166
+ status(args.file)
167
+ elif args.command == "list":
168
+ list_all()
169
+ else:
170
+ parser.print_help()
171
+
172
+
173
+ if __name__ == "__main__":
174
+ main()
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Kortext Session Start
4
+ ---------------------
5
+ Her oturum açılışında çalışır. Context dosyalarını okur, handover'ı kontrol eder
6
+ ve SESSION_BRIEF üretir. Ajan bu özeti görmeden göreve başlamamalıdır.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ from datetime import datetime, timedelta
12
+ from pathlib import Path
13
+
14
+
15
+ ROOT = Path(__file__).resolve().parents[1]
16
+ CONTEXT_DIR = ROOT / "workspace/memory/context"
17
+ HANDOVER_PATH = ROOT / "workspace/memory/handover.md"
18
+ BACKLOG_DIR = ROOT / "workspace/memory/backlog"
19
+
20
+ # Stale eşiği saat cinsinden. Env var ile override edilebilir.
21
+ STALE_HOURS = int(os.environ.get("KORTEXT_STALE_HOURS_CONTEXT", "24"))
22
+
23
+
24
+ def read_context_files() -> list[dict]:
25
+ """Tüm aktif context dosyalarını okur."""
26
+ agents = []
27
+ if not CONTEXT_DIR.exists():
28
+ return agents
29
+ for f in sorted(CONTEXT_DIR.glob("*-active.md")):
30
+ if f.name.startswith("["): # şablon dosyalarını atla
31
+ continue
32
+ content = f.read_text(errors="ignore").strip()
33
+ mtime = datetime.fromtimestamp(f.stat().st_mtime)
34
+ age_hours = (datetime.now() - mtime).total_seconds() / 3600
35
+ agents.append({
36
+ "file": f.name,
37
+ "content": content,
38
+ "age_hours": round(age_hours, 1),
39
+ "stale": age_hours > STALE_HOURS,
40
+ })
41
+ return agents
42
+
43
+
44
+ def read_last_handover() -> str:
45
+ """handover.md dosyasından en son handover bloğunu döndürür."""
46
+ if not HANDOVER_PATH.exists():
47
+ return "(handover.md bulunamadı)"
48
+ text = HANDOVER_PATH.read_text(errors="ignore")
49
+ # İlk ## Handover: bloğunu bul
50
+ lines = text.splitlines()
51
+ block: list[str] = []
52
+ in_block = False
53
+ for line in lines:
54
+ if line.startswith("## Handover:"):
55
+ if in_block:
56
+ break # Sadece ilk (en yeni) bloğu al
57
+ in_block = True
58
+ if in_block:
59
+ block.append(line)
60
+ return "\n".join(block) if block else "(kayıtlı handover yok)"
61
+
62
+
63
+ def count_in_progress_items() -> list[str]:
64
+ """Backlog'da In Progress olan itemları döndürür."""
65
+ items = []
66
+ if not BACKLOG_DIR.exists():
67
+ return items
68
+ for f in BACKLOG_DIR.glob("*.md"):
69
+ text = f.read_text(errors="ignore")
70
+ if "**Status:** In Progress" in text:
71
+ items.append(f.stem)
72
+ return items
73
+
74
+
75
+ def main() -> None:
76
+ now = datetime.now().strftime("%d.%m.%Y %H:%M")
77
+ print("=" * 60)
78
+ print(f" KORTEXT SESSION BRIEF — {now}")
79
+ print("=" * 60)
80
+
81
+ # 1. Aktif ajanlar
82
+ agents = read_context_files()
83
+ print(f"\n📋 AKTİF AJANLAR ({len(agents)} dosya):")
84
+ if not agents:
85
+ print(" → Context dosyası yok. Temiz başlangıç.")
86
+ for agent in agents:
87
+ stale_flag = " ⚠️ STALE" if agent["stale"] else ""
88
+ print(f" • {agent['file']} ({agent['age_hours']}s önce güncellendi{stale_flag})")
89
+ # İlk satırı özetle
90
+ first_line = agent["content"].splitlines()[0] if agent["content"] else ""
91
+ if first_line:
92
+ print(f" {first_line}")
93
+
94
+ # 2. In Progress itemlar
95
+ in_progress = count_in_progress_items()
96
+ print(f"\n🔄 IN PROGRESS İTEMLAR ({len(in_progress)} adet):")
97
+ if not in_progress:
98
+ print(" → Yok.")
99
+ for item in in_progress:
100
+ print(f" • {item}")
101
+
102
+ # 3. Son handover
103
+ print(f"\n📨 SON HANDOVER:")
104
+ handover = read_last_handover()
105
+ # İlk 10 satırı göster
106
+ preview_lines = handover.splitlines()[:10]
107
+ for line in preview_lines:
108
+ print(f" {line}")
109
+ if len(handover.splitlines()) > 10:
110
+ print(f" ... ({len(handover.splitlines())} satır — tam okuma için handover.md)")
111
+
112
+ # 4. Stale uyarıları
113
+ stale_agents = [a for a in agents if a["stale"]]
114
+ if stale_agents:
115
+ print(f"\n⚠️ STALE CONTEXT UYARISI ({len(stale_agents)} dosya):")
116
+ for a in stale_agents:
117
+ print(f" • {a['file']} — {a['age_hours']} saat önce güncellendi")
118
+ print(" → Bu dosyalar hala In Progress görünüyor. Kontrol et.")
119
+
120
+ print("\n" + "=" * 60)
121
+ print(" Context yüklendi. Göreve başlamadan önce yukarıdaki")
122
+ print(" bilgileri oku ve durumu anla.")
123
+ print("=" * 60)
124
+
125
+
126
+ if __name__ == "__main__":
127
+ main()
@@ -0,0 +1,34 @@
1
+ #!/bin/bash
2
+
3
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
+ KORTEXT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
5
+ KORTEXT_ROOT="$(cd "$KORTEXT_DIR/.." && pwd)"
6
+
7
+ # Bu script Kortext Framework'ün kritik dosyalarını sadece okunabilir hale getirir.
8
+
9
+ # Kök dizin dosyaları
10
+ FILES=("$KORTEXT_DIR/AGENTS.md")
11
+
12
+ # Korumaya alınacak Framework klasörleri
13
+ DIRS="$KORTEXT_DIR/agents $KORTEXT_DIR/rules $KORTEXT_DIR/workflows"
14
+
15
+ echo "Kortext Framework dosyaları kilitleniyor..."
16
+
17
+ # Dosyaları kilitle
18
+ for FILE in "${FILES[@]}"; do
19
+ if [ -f "$FILE" ]; then
20
+ echo "- $FILE kilitleniyor..."
21
+ chmod 444 "$FILE"
22
+ fi
23
+ done
24
+
25
+ # Klasörleri ve içindekileri kilitle (Yazma yetkisini kaldır, okuma ve erişim yetkisini koru)
26
+ for DIR in $DIRS; do
27
+ if [ -d "$DIR" ]; then
28
+ echo "- $DIR klasörü ve içeriği kilitleniyor..."
29
+ chmod -R a-w "$DIR"
30
+ chmod -R a+rX "$DIR"
31
+ fi
32
+ done
33
+
34
+ echo "İşlem tamamlandı. Framework dosyaları artık sadece okunabilir."
@@ -0,0 +1,48 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "Write|Edit",
6
+ "hooks": [
7
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/write-guard.sh" },
8
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/secret-scanner.sh" },
9
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/auto-locker.sh" },
10
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/snapshot-guard.sh" }
11
+ ]
12
+ },
13
+ {
14
+ "matcher": "Bash",
15
+ "hooks": [
16
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/secret-scanner.sh" }
17
+ ]
18
+ }
19
+ ],
20
+ "PostToolUse": [
21
+ {
22
+ "matcher": "Write|Edit",
23
+ "hooks": [
24
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/auto-unlocker.sh" },
25
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/audit-logger.sh" }
26
+ ]
27
+ },
28
+ {
29
+ "matcher": "*",
30
+ "hooks": [
31
+ { "type": "command", "command": "${KORTEXT_ROOT}/hooks/audit-logger.sh" }
32
+ ]
33
+ }
34
+ ],
35
+ "SessionStart": [
36
+ {
37
+ "hooks": [
38
+ { "type": "command", "command": "python3 ${KORTEXT_ROOT}/scripts/kortext-session-start.py" }
39
+ ]
40
+ }
41
+ ]
42
+ },
43
+ "env": {
44
+ "KORTEXT_HOOK_MODE": "permissive",
45
+ "KORTEXT_INTERACTION_LANGUAGE": "tr",
46
+ "KORTEXT_RUNTIME": "claude_code"
47
+ }
48
+ }