From 7ba2ceb9ad899fdd5ffed3d52d6c4502ac494831 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:02:47 +0000 Subject: [PATCH 1/4] Initial plan From 2fc91a560420fa0e0db44826fd1c310a995cde41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:07:06 +0000 Subject: [PATCH 2/4] Plan fix for daily Rig sampler Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../02-review-git-diff.ts | 5 ++ .../03-diagnose-test-failure.ts | 21 +++++ .../04-generate-readme.ts | 16 ++++ .../05-write-readme-intent.ts | 14 ++++ .../06-list-source-files.ts | 15 ++++ .../07-summarize-many-files.ts | 10 +++ .../08-extract-package-scripts.ts | 8 ++ .../09-classify-issue.ts | 14 ++++ .../10-triage-pr.ts | 14 ++++ .../100-workspace-config-drift-2.ts | 28 +++++++ .../101-commit-format-suggester-2.ts | 17 ++++ .../102-runtime-env-checker-2.ts | 29 +++++++ .../103-hotspot-file-analyzer-2.ts | 15 ++++ .../104-loc-statistics.ts | 35 ++++++++ .../105-import-cycle-detector-2.ts | 18 +++++ .../106-ts-export-usage.ts | 32 ++++++++ .../107-git-rename-tracker.ts | 17 ++++ .../108-yaml-lint-checker.ts | 36 +++++++++ .../109-two-phase-complexity-review.ts | 29 +++++++ .../11-release-notes.ts | 13 +++ .../110-workspace-config-drift-3.ts | 43 ++++++++++ .../111-conventional-commit-suggester.ts | 27 +++++++ .../112-runtime-env-health.ts | 35 ++++++++ .../113-git-hotspot-analyzer.ts | 26 ++++++ .../114-loc-statistics-gatherer.ts | 35 ++++++++ .../115-import-cycle-detector.ts | 37 +++++++++ .../116-barrel-file-generator.ts | 42 ++++++++++ .../117-git-hook-inventory.ts | 38 +++++++++ .../118-pr-review-checklist.ts | 39 +++++++++ .../119-source-map-analyzer.ts | 43 ++++++++++ .../12-security-scan-review.ts | 13 +++ .../120-git-hotspot-v2.ts | 47 +++++++++++ .../121-loc-stats-gatherer.ts | 44 ++++++++++ .../122-import-cycle-detector.ts | 36 +++++++++ .../123-coverage-badge-updater.ts | 30 +++++++ .../124-dep-license-auditor.ts | 45 +++++++++++ .../125-test-coverage-mapper.ts | 50 ++++++++++++ .../126-tsconfig-options-auditor.ts | 57 +++++++++++++ .../127-git-commit-annotator.ts | 52 ++++++++++++ .../128-npm-script-dep-mapper.ts | 57 +++++++++++++ .../129-markdown-link-checker.ts | 57 +++++++++++++ .../13-test-plan.ts | 15 ++++ .../130-git-hotspot-analyzer.ts | 15 ++++ .../131-loc-statistics-gatherer.ts | 37 +++++++++ .../132-import-cycle-detector.ts | 26 ++++++ .../133-coverage-badge-updater.ts | 22 +++++ .../134-dep-license-auditor.ts | 37 +++++++++ .../135-test-coverage-mapper.ts | 35 ++++++++ .../136-pkg-version-drift.ts | 27 +++++++ .../137-git-author-stats.ts | 24 ++++++ .../138-ts-path-alias-validator.ts | 37 +++++++++ .../139-markdown-frontmatter-checker.ts | 40 +++++++++ .../14-changelog-categorizer.ts | 12 +++ .../140-git-hotspot-analyzer.ts | 36 +++++++++ .../141-loc-statistics-gatherer.ts | 45 +++++++++++ .../142-import-cycle-detector.ts | 34 ++++++++ .../143-coverage-badge-updater.ts | 29 +++++++ .../144-dep-license-auditor.ts | 50 ++++++++++++ .../145-test-coverage-mapper.ts | 51 ++++++++++++ .../146-file-permission-scanner.ts | 41 ++++++++++ .../147-git-submodule-health.ts | 49 +++++++++++ .../148-ts-decorator-scanner.ts | 47 +++++++++++ .../149-dotfile-inventory.ts | 36 +++++++++ .../15-api-diff-summary.ts | 12 +++ .../150-git-hotspot-analyzer-v3.ts | 38 +++++++++ .../151-loc-statistics-v2.ts | 52 ++++++++++++ .../152-import-cycle-detector-v3.ts | 34 ++++++++ .../153-coverage-badge-updater-v2.ts | 35 ++++++++ .../154-dep-license-auditor-v2.ts | 37 +++++++++ .../155-test-coverage-mapper-v2.ts | 51 ++++++++++++ .../156-regex-pattern-tester.ts | 59 ++++++++++++++ .../157-commit-churn-classifier.ts | 27 +++++++ .../158-npm-package-size.ts | 44 ++++++++++ .../159-ts-branch-coverage.ts | 58 +++++++++++++ .../16-docs-gap-analysis.ts | 12 +++ .../160-dead-code-detector.ts | 44 ++++++++++ .../161-openapi-spec-validator.ts | 48 +++++++++++ .../162-api-endpoint-extractor.ts | 36 +++++++++ .../163-source-file-annotator.ts | 37 +++++++++ .../164-stale-dependency-detector.ts | 42 ++++++++++ .../165-git-tag-timeline.ts | 46 +++++++++++ .../166-env-variable-type-inferrer.ts | 40 +++++++++ .../167-makefile-target-extractor.ts | 43 ++++++++++ .../168-test-fixture-generator.ts | 41 ++++++++++ .../169-server-uptime-log-parser.ts | 41 ++++++++++ .../17-refactor-plan.ts | 12 +++ .../170-stale-dep-detector.ts | 36 +++++++++ .../171-git-tag-timeline.ts | 36 +++++++++ .../172-service-health-probe.ts | 19 +++++ .../173-git-template-renderer.ts | 31 +++++++ .../174-changelog-entry-gen.ts | 29 +++++++ .../175-todo-comment-tracker.ts | 19 +++++ .../176-css-variable-extractor.ts | 28 +++++++ .../177-openapi-route-coverage.ts | 32 ++++++++ .../178-import-style-checker.ts | 37 +++++++++ .../179-git-tag-semver-validator.ts | 40 +++++++++ .../18-patch-writer-output.ts | 12 +++ .../180-git-tag-timeline-reporter.ts | 31 +++++++ .../181-service-health-probe.ts | 20 +++++ .../182-git-metadata-template-renderer.ts | 27 +++++++ .../183-changelog-entry-generator.ts | 32 ++++++++ .../184-todo-fixme-tracker.ts | 20 +++++ .../185-multi-file-glob-summarizer.ts | 20 +++++ .../186-shell-script-analyzer.ts | 39 +++++++++ .../187-lock-file-drift-detector.ts | 53 ++++++++++++ .../188-git-conflict-marker-scanner.ts | 20 +++++ .../189-proto-field-extractor.ts | 50 ++++++++++++ .../19-fix-then-review.ts | 12 +++ .../190-commit-msg-rewriter.ts | 17 ++++ .../190-git-tag-timeline-reporter.ts | 50 ++++++++++++ .../191-env-key-checker.ts | 24 ++++++ .../191-service-health-probe.ts | 37 +++++++++ .../192-git-metadata-template-renderer.ts | 41 ++++++++++ .../192-json-schema-migration-planner.ts | 31 +++++++ .../193-changelog-entry-generator.ts | 29 +++++++ .../193-dockerfile-security-auditor.ts | 28 +++++++ .../194-npm-audit-simplifier.ts | 16 ++++ .../194-todo-fixme-tracker.ts | 40 +++++++++ .../195-git-stash-inventory.ts | 15 ++++ .../195-multi-file-glob-summarizer.ts | 39 +++++++++ .../196-git-remote-inspector.ts | 48 +++++++++++ .../196-http-endpoint-health-checker.ts | 42 ++++++++++ .../197-git-blame-ownership.ts | 37 +++++++++ .../197-ts-enum-extractor.ts | 40 +++++++++ .../198-json-config-merger.ts | 58 +++++++++++++ .../198-ts-generic-type-extractor.ts | 28 +++++++ .../199-shell-script-validator.ts | 33 ++++++++ .../199-source-complexity-heatmap.ts | 40 +++++++++ .../20-issue-reproducer.ts | 14 ++++ .../200-npm-audit-simplifier.ts | 16 ++++ .../201-git-stash-inventory.ts | 17 ++++ .../202-ts-interface-conflict-checker.ts | 45 +++++++++++ .../203-git-worktree-mapper.ts | 44 ++++++++++ .../204-test-naming-enforcer.ts | 18 +++++ .../205-pkg-dependency-graph.ts | 36 +++++++++ .../206-ci-flake-triager.ts | 17 ++++ .../207-config-drift-reconciler.ts | 20 +++++ .../208-release-note-enricher.ts | 33 ++++++++ .../209-docs-refactor-coordinator.ts | 31 +++++++ .../21-ci-log-diagnosis.ts | 14 ++++ .../210-test-file-naming-enforcer.ts | 39 +++++++++ .../211-pkg-dependency-graph-extractor.ts | 36 +++++++++ .../212-ts-export-usage-counter.ts | 40 +++++++++ .../213-git-rename-tracker.ts | 17 ++++ .../214-yaml-lint-checker.ts | 41 ++++++++++ .../215-two-phase-complexity-review.ts | 30 +++++++ .../216-dockerfile-layer-analyzer.ts | 41 ++++++++++ .../217-git-worktree-status.ts | 38 +++++++++ .../218-ts-interface-conflict-checker.ts | 52 ++++++++++++ .../219-npm-audit-simplifier.ts | 39 +++++++++ .../22-config-normalizer.ts | 12 +++ .../220-git-rename-tracker-v2.ts | 21 +++++ .../221-yaml-workflow-linter.ts | 41 ++++++++++ .../222-two-phase-complexity-review-v2.ts | 33 ++++++++ .../223-barrel-file-generator-v2.ts | 31 +++++++ .../224-git-hook-inventory-v2.ts | 30 +++++++ .../225-pr-review-checklist-v2.ts | 28 +++++++ .../226-js-ast-node-counter.ts | 40 +++++++++ .../227-git-tag-date-mapper.ts | 44 ++++++++++ .../228-circular-import-detector.ts | 49 +++++++++++ .../229-package-json-scorer.ts | 46 +++++++++++ .../23-schema-inference.ts | 11 +++ .../230-git-rename-tracker-v3.ts | 25 ++++++ .../231-yaml-workflow-linter-v2.ts | 41 ++++++++++ .../232-two-phase-complexity-review-v3.ts | 69 ++++++++++++++++ .../233-barrel-file-generator-v3.ts | 39 +++++++++ .../234-git-hook-inventory-v3.ts | 44 ++++++++++ .../235-pr-review-checklist-v3.ts | 30 +++++++ .../236-vitest-coverage-parser.ts | 61 ++++++++++++++ .../237-git-log-stats-aggregator.ts | 48 +++++++++++ .../238-ts-import-depth-analyzer.ts | 48 +++++++++++ .../239-env-file-completeness-checker.ts | 47 +++++++++++ .../24-error-message-improver.ts | 15 ++++ .../240-git-commit-annotator.ts | 36 +++++++++ .../241-npm-script-dep-mapper.ts | 54 +++++++++++++ .../242-markdown-link-checker.ts | 55 +++++++++++++ .../243-package-version-drift.ts | 31 +++++++ .../244-git-author-stats.ts | 28 +++++++ .../245-ts-path-alias-validator.ts | 39 +++++++++ .../246-stale-branch-detector.ts | 43 ++++++++++ .../247-license-header-checker.ts | 50 ++++++++++++ .../248-yaml-config-diff.ts | 53 ++++++++++++ .../249-monorepo-workspace-lister.ts | 53 ++++++++++++ .../25-migration-guide.ts | 12 +++ .../250-git-commit-annotator.ts | 47 +++++++++++ .../251-npm-script-dep-mapper.ts | 47 +++++++++++ .../252-markdown-link-checker.ts | 56 +++++++++++++ .../253-package-version-drift.ts | 35 ++++++++ .../254-git-author-stats.ts | 33 ++++++++ .../255-ts-path-alias-validator.ts | 44 ++++++++++ .../256-gh-actions-timing-analyzer.ts | 52 ++++++++++++ .../257-binary-file-detector.ts | 53 ++++++++++++ .../258-ts-interface-inheritance-graph.ts | 50 ++++++++++++ .../259-dep-license-matrix.ts | 58 +++++++++++++ .../26-design-review.ts | 16 ++++ .../260-git-submodule-health.ts | 49 +++++++++++ .../261-ts-decorator-scanner.ts | 45 +++++++++++ .../262-dotfile-inventory.ts | 48 +++++++++++ .../263-regex-pattern-tester.ts | 59 ++++++++++++++ .../264-commit-churn-classifier.ts | 27 +++++++ .../265-npm-package-size.ts | 41 ++++++++++ .../266-tsconfig-option-analyzer.ts | 52 ++++++++++++ .../267-git-patch-summarizer.ts | 50 ++++++++++++ .../268-npm-lifecycle-analyzer.ts | 47 +++++++++++ .../269-ts-jsdoc-coverage.ts | 70 ++++++++++++++++ .../27-dependency-upgrade-plan.ts | 14 ++++ .../270-dotfile-inventory-mapper.ts | 53 ++++++++++++ .../271-regex-pattern-tester.ts | 54 +++++++++++++ .../272-commit-churn-classifier.ts | 36 +++++++++ .../273-npm-package-size-estimator.ts | 39 +++++++++ .../274-ts-branch-coverage-analyzer.ts | 52 ++++++++++++ .../275-env-variable-type-inferrer.ts | 41 ++++++++++ .../276-git-hook-installer.ts | 50 ++++++++++++ .../277-ts-type-guard-generator.ts | 42 ++++++++++ .../278-json-fixture-anonymizer.ts | 46 +++++++++++ .../279-csv-to-markdown-table.ts | 40 +++++++++ .../28-license-check.ts | 16 ++++ .../280-commit-churn-classifier.ts | 27 +++++++ .../281-npm-package-size-estimator.ts | 37 +++++++++ .../282-ts-branch-coverage-analyzer.ts | 40 +++++++++ .../283-env-variable-type-inferrer.ts | 37 +++++++++ .../284-makefile-target-extractor.ts | 58 +++++++++++++ .../285-test-fixture-generator.ts | 37 +++++++++ .../286-toml-config-analyzer.ts | 40 +++++++++ .../287-git-checkpoint-summarizer.ts | 40 +++++++++ .../288-ts-literal-union-extractor.ts | 44 ++++++++++ .../289-markdown-heading-validator.ts | 52 ++++++++++++ .../29-bug-report-draft.ts | 16 ++++ .../290-commit-churn-classifier.ts | 26 ++++++ .../291-npm-package-size-estimator.ts | 33 ++++++++ .../292-ts-branch-coverage-analyzer.ts | 38 +++++++++ .../293-env-variable-type-inferrer.ts | 31 +++++++ .../294-makefile-target-extractor.ts | 37 +++++++++ .../295-test-fixture-generator.ts | 33 ++++++++ .../296-git-file-ownership-mapper.ts | 44 ++++++++++ .../297-workflow-input-validator.ts | 48 +++++++++++ .../298-ts-dead-export-finder.ts | 44 ++++++++++ .../299-package-json-scripts-documenter.ts | 44 ++++++++++ .../30-github-action-review.ts | 12 +++ .../300-server-uptime-log-parser.ts | 42 ++++++++++ .../301-css-variable-extractor.ts | 37 +++++++++ .../302-openapi-route-coverage.ts | 47 +++++++++++ .../303-import-style-checker.ts | 40 +++++++++ .../304-git-tag-semver-validator.ts | 47 +++++++++++ .../305-shell-script-safety-analyzer.ts | 44 ++++++++++ .../306-git-diff-stats-summarizer.ts | 45 +++++++++++ .../307-dotenv-template-generator.ts | 46 +++++++++++ .../308-ts-class-hierarchy-extractor.ts | 52 ++++++++++++ .../309-git-bisect-helper.ts | 41 ++++++++++ .../31-monorepo-package-map.ts | 12 +++ .../310-lock-file-drift-detector.ts | 66 +++++++++++++++ .../310-workflow-audit-verify.ts | 29 +++++++ .../311-git-conflict-marker-scanner.ts | 28 +++++++ .../312-proto-field-extractor.ts | 50 ++++++++++++ .../313-git-remote-url-inspector.ts | 46 +++++++++++ .../314-ts-enum-value-extractor.ts | 44 ++++++++++ .../315-json-config-merger.ts | 81 +++++++++++++++++++ .../316-markdown-toc-generator.ts | 42 ++++++++++ .../317-git-author-email-domains.ts | 33 ++++++++ .../318-ts-barrel-re-exporter.ts | 19 +++++ .../319-workflow-step-duration-estimator.ts | 65 +++++++++++++++ .../32-command-planner.ts | 19 +++++ .../33-readonly-investigator.ts | 15 ++++ .../34-intent-options.ts | 11 +++ .../35-call-options.ts | 11 +++ .../36-subagent-delegation.ts | 15 ++++ .../37-output-with-nullable.ts | 22 +++++ .../38-exact-literal-output.ts | 12 +++ .../39-unknown-raw-output.ts | 13 +++ .../40-record-output.ts | 11 +++ .../41-parse-coverage.ts | 14 ++++ .../42-json-repair.ts | 14 ++++ .../43-snapshot-test-updater.ts | 12 +++ .../44-flaky-test-analysis.ts | 12 +++ .../45-code-owner-suggestion.ts | 12 +++ .../46-prompt-intent-inspection.ts | 11 +++ .../47-prompt-intents.ts | 11 +++ .../48-custom-engine.ts | 8 ++ .../49-timeout-signal-helper.ts | 8 ++ .../50-end-to-end-release-agent.ts | 26 ++++++ .../51-subagent-task-harness.ts | 21 +++++ .../52-claude-design.ts | 25 ++++++ .../53-ralf-loop.ts | 22 +++++ .../54-large-scale-summarization.ts | 13 +++ .../55-file-change-lint-middleware.ts | 23 ++++++ .../55-genaiscript-glossary-port.ts | 8 ++ .../56-genaiscript-refactor-batch-port.ts | 10 +++ .../57-genaiscript-issue-review-port.ts | 8 ++ .../58-genaiscript-travel-plan-port.ts | 11 +++ .../59-genaiscript-city-info-port.ts | 8 ++ .../60-genaiscript-schema-cities-port.ts | 8 ++ .../60-workflow-parallel-linter.ts | 24 ++++++ .../61-genaiscript-list-files-port.ts | 8 ++ .../62-genaiscript-todo-port.ts | 8 ++ .../63-genaiscript-slide-deck-port.ts | 8 ++ .../64-genaiscript-grumpy-review-port.ts | 8 ++ .../65-source-file-annotator.ts | 23 ++++++ .../66-ci-workflow-health.ts | 29 +++++++ .../67-glob-file-summarizer.ts | 17 ++++ .../68-changelog-generator.ts | 31 +++++++ .../69-todo-comment-tracker.ts | 20 +++++ .../70-multi-file-subagent-summarizer.ts | 29 +++++++ .../71-package-script-health.ts | 31 +++++++ .../72-ts-function-signatures.ts | 33 ++++++++ .../73-git-branch-pruner.ts | 22 +++++ .../74-prettier-eslint-compat.ts | 45 +++++++++++ .../75-workflow-validator.ts | 36 +++++++++ .../76-commit-msg-rewriter.ts | 21 +++++ .../77-env-key-checker.ts | 28 +++++++ .../78-build-log-analyzer.ts | 20 +++++ .../79-ts-type-alias-mapper.ts | 27 +++++++ .../80-git-contributor-mapper.ts | 14 ++++ .../81-markdown-doc-summarizer.ts | 23 ++++++ .../82-workspace-config-drift.ts | 29 +++++++ .../83-commit-format-suggester.ts | 17 ++++ .../84-json-schema-migration.ts | 31 +++++++ .../85-dockerfile-security-audit.ts | 41 ++++++++++ .../86-npm-audit-simplifier.ts | 16 ++++ .../87-git-stash-inventory.ts | 15 ++++ .../88-git-contributor-mapper.ts | 14 ++++ .../89-markdown-doc-summarizer.ts | 23 ++++++ .../90-workspace-config-drift.ts | 29 +++++++ .../91-commit-format-suggester.ts | 17 ++++ .../92-runtime-env-checker.ts | 32 ++++++++ .../93-hotspot-file-analyzer.ts | 16 ++++ .../94-ts-interface-conflict-checker.ts | 45 +++++++++++ .../95-git-worktree-mapper.ts | 44 ++++++++++ .../96-test-naming-enforcer.ts | 18 +++++ .../97-pkg-dependency-graph.ts | 36 +++++++++ .../98-async-tool-node-builtins.ts | 35 ++++++++ .../99-bash-each.ts | 25 ++++++ .../tsconfig.json | 6 ++ 332 files changed, 10838 insertions(+) create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts create mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts new file mode 100644 index 0000000..bff8b9b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts @@ -0,0 +1,5 @@ +import { p } from "rig"; + +// Agent role: review the repository diff and return a structured summary. + +export default p`Review ${p.bash("git diff --stat")} and ${p.bash("git status --short")} and return a concise summary with key findings.`; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts new file mode 100644 index 0000000..fe7d6b6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts @@ -0,0 +1,21 @@ +import { agent, s } from "rig"; +// Agent role: review input.diff for correctness and regression risks. Return only the declared output shape. +const reviewer = agent({ + model: "typecheck", + output: s.object({ + summary: s.string, + risk: s.enum("low", "medium", "high"), + findings: s.array(s.object({ + severity: s.enum("info", "warning", "error"), + message: s.string, + file: s.optional(s.string), + line: s.optional(s.number) + })), + tests: s.array(s.string) + }), + instructions: ` + Review input.diff for correctness and regression risks. + Return only the declared output shape. + `, +}); +export default reviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts new file mode 100644 index 0000000..e1284ef --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts @@ -0,0 +1,16 @@ +import { agent, s } from "rig"; +// Agent role: diagnose the failing test result. Do not edit files. +const diagnose = agent({ + model: "typecheck", + output: s.object({ + rootCause: s.string, + confidence: s.number, + relevantFiles: s.array(s.string), + nextSteps: s.array(s.string) + }), + instructions: ` + Diagnose the failing test result. + Do not edit files. + `, +}); +export default diagnose; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts new file mode 100644 index 0000000..991121b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; +// Agent role: generate a concise README for the package. Include install, usage, and API sections. +const readmeWriter = agent({ + model: "typecheck", + output: s.object({ + path: s.enum("README.md"), + contents: s.string + }), + instructions: ` + Generate a concise README for the package. + Include install, usage, and API sections. + `, +}); +export default readmeWriter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts new file mode 100644 index 0000000..3c92bec --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts @@ -0,0 +1,15 @@ +import { agent, p, s } from "rig"; + +// Agent role: list TypeScript source files and return a categorized summary. +const listSourceFiles = agent({ + model: "typecheck", + instructions: p`List and categorize the TypeScript files in this workspace. + +Files: ${p.glob("src/**/*.ts")}`, + output: s.object({ + files: s.array(s.path), + summary: s.string, + }), +}); + +export default listSourceFiles; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts new file mode 100644 index 0000000..313f6a3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts @@ -0,0 +1,10 @@ +import { agent, s } from "rig"; +// Agent role: summarize the repository file list in one sentence. +const summarizeFiles = agent({ + model: "typecheck", + instructions: "Summarize the repository file list in one sentence.", + output: s.object({ + summary: s.string, + }), +}); +export default summarizeFiles; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts new file mode 100644 index 0000000..77143b9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts @@ -0,0 +1,8 @@ +import { agent, p, s } from "rig"; +// Agent role: extract package scripts and summarize what they do. +const extractScripts = agent({ + model: "typecheck", + instructions: p`Read ${p.read("package.json")} and summarize the package scripts. Use ${p.bash("find src -name '*.ts' -type f | sort")} only to call out source files that look relevant.`, + output: s.object({ scriptsByName: s.record(s.string), summary: s.string, relatedFiles: s.array(s.string) }), +}); +export default extractScripts; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts new file mode 100644 index 0000000..4be51bb --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; + +// Agent role: classify the issue. + +const classifyIssue = agent({ + model: "typecheck", + instructions: "Classify the issue.", + output: s.object({ + label: s.enum("bug", "feature", "question", "docs"), + confidence: s.enum("low", "medium", "high"), + }), +}); + +export default classifyIssue; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts new file mode 100644 index 0000000..178dd68 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; +// Agent role: classify the GitHub issue and suggest labels. +const classifyIssue = agent({ + model: "typecheck", + output: s.object({ + kind: s.enum("bug", "feature", "question", "chore"), + priority: s.enum("p0", "p1", "p2", "p3"), + rationale: s.string, + labels: s.array(s.string) + }), + instructions: `Classify the GitHub issue and suggest labels.`, +}); + +export default classifyIssue; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts new file mode 100644 index 0000000..2cdbcbe --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts @@ -0,0 +1,28 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseJson = defineTool("parseJson", { + description: "Parse a JSON string and return parsed object or error", + parameters: s.object({ content: s.string, filename: s.string }), + handler({ content, filename }) { + try { + return { ok: true, parsed: JSON.parse(content), filename }; + } catch (e) { + return { ok: false, error: String(e), filename }; + } + }, +}); + +// Agent role: detect configuration drift across workspace config files. +const workspaceConfigDrift = agent({ + model: "typecheck", + instructions: p`Read and analyze these config files: tsconfig.json ${p.readOptional("tsconfig.json", "{}")}, .eslintrc.json ${p.readOptional(".eslintrc.json", "{}")}, .prettierrc ${p.readOptional(".prettierrc", "{}")}. Use the parseJson tool to validate each. For each config file, identify fields that deviate from sensible defaults (e.g. missing strict mode in tsconfig, missing semi in prettier). Return a record keyed by filename with driftedFields and status.`, + output: s.record(s.object({ + driftedFields: s.array(s.string), + status: s.enum("ok", "warning", "error"), + })), + tools: [parseJson], + maxTurns: 4, + addons: repair(), +}); + +export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts new file mode 100644 index 0000000..6ce037e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair, steering } from "rig"; + +// Agent role: suggest conventional commit format for recent git commit messages. +const commitFormatSuggester = agent({ + model: "typecheck", + instructions: p`Review the last 10 git commits: ${p.bash("git log --oneline -10")}. For each commit, determine its conventional category (feat/fix/chore/docs/test/refactor/style), then propose an improved commit message following the conventional commits spec. Return an array with one entry per commit.`, + output: s.array(s.object({ + hash: s.string, + original: s.string, + suggested: s.string, + category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), + })), + maxTurns: 4, + addons: [steering({ message: "Every commit must have a suggested message in conventional format." }), repair()], +}); + +export default commitFormatSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts new file mode 100644 index 0000000..fe4bb0d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts @@ -0,0 +1,29 @@ +import { agent, p, s, defineTool } from "rig"; + +const checkThresholds = defineTool("checkThresholds", { + description: "Validate Node.js version and heap against minimum thresholds", + parameters: s.object({ nodeVersion: s.string, heapMB: s.number }), + handler({ nodeVersion, heapMB }) { + const issues: string[] = []; + const major = parseInt(nodeVersion.replace("v", "").split(".")[0], 10); + if (major < 18) issues.push(`Node.js ${nodeVersion} is below v18 minimum`); + if (heapMB < 256) issues.push(`Heap ${heapMB}MB is below 256MB minimum`); + return { issues }; + }, +}); + +// Agent role: inspect the runtime environment and report overall health. +const runtimeEnvChecker = agent({ + model: "typecheck", + instructions: p`Inspect the runtime environment: Node version ${p.bash("node --version")}, OS info ${p.bash("uname -a")}, and heap memory ${p.bash("node -p \"Math.round(process.memoryUsage().heapTotal/1024/1024)\"")}MB. Use the checkThresholds tool to validate. Report health as ok, degraded, or critical.`, + output: s.object({ + health: s.enum("ok", "degraded", "critical"), + nodeVersion: s.string, + platform: s.string, + heapMB: s.number, + issues: s.array(s.string), + }), + tools: [checkThresholds], +}); + +export default runtimeEnvChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts new file mode 100644 index 0000000..027a5ed --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts @@ -0,0 +1,15 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: identify hot-spot files by measuring commit churn and contributor spread. +const hotspotFileAnalyzer = agent({ + model: "typecheck", + instructions: p`Find hot-spot files using commit history: ${p.bash("git log --name-only --format='' HEAD~100..HEAD | grep -v '^$' | sort | uniq -c | sort -rn | head -20")}. For each of the top 10 files, get top contributors via ${p.bash("git shortlog -sn --no-merges HEAD~100..HEAD | head -10")}. Compute a churnScore (0-100) based on commit frequency and list topContributors per file.`, + output: s.record(s.object({ + churnScore: s.number, + topContributors: s.array(s.string), + })), + maxTurns: 5, + addons: steering({ message: "Every file entry must have a numeric churnScore 0-100 and at least one topContributor." }), +}); + +export default hotspotFileAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts new file mode 100644 index 0000000..b47d328 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts @@ -0,0 +1,35 @@ +import { agent, p, s, defineTool } from "rig"; + +const aggregateByExtension = defineTool("aggregateByExtension", { + description: "Parse wc -l output lines and aggregate total line count and file count by extension", + parameters: s.object({ wcOutput: s.string }), + handler({ wcOutput }) { + const totals: Record = {}; + for (const line of wcOutput.split("\n")) { + const match = line.trim().match(/^(\d+)\s+(.+)$/); + if (!match) continue; + const count = parseInt(match[1], 10); + const path = match[2]; + if (path === "total") continue; + const ext = path.includes(".") ? "." + path.split(".").pop() : "(no ext)"; + if (!totals[ext]) totals[ext] = { lineCount: 0, fileCount: 0 }; + totals[ext].lineCount += count; + totals[ext].fileCount += 1; + } + return totals; + }, +}); + +// Agent role: gather lines-of-code statistics per file extension and classify complexity. +const locStatistics = agent({ + model: "typecheck", + instructions: p`Gather LOC statistics. First list files: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f \\( -name '*.ts' -o -name '*.js' -o -name '*.md' -o -name '*.json' \\) | head -200")}. Then count lines: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f \\( -name '*.ts' -o -name '*.js' -o -name '*.md' -o -name '*.json' \\) -exec wc -l {} + 2>/dev/null | tail -20")}. Use the aggregateByExtension tool to sum lines and files per extension. Classify each extension as small (<500 lines), medium (<2000), large (<10000), or xlarge (≥10000).`, + output: s.record(s.object({ + lineCount: s.number, + fileCount: s.number, + complexity: s.enum("small", "medium", "large", "xlarge"), + })), + tools: [aggregateByExtension], +}); + +export default locStatistics; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts new file mode 100644 index 0000000..a9d2a28 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts @@ -0,0 +1,18 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: detect circular import cycles in TypeScript source files. +const importCycleDetector = agent({ + model: "typecheck", + instructions: p`Detect circular imports in TypeScript files. Check using: ${p.bash("npx --yes madge --circular --extensions ts . 2>&1 || echo 'madge-unavailable'")}. If madge is unavailable, fall back to analyzing imports manually: ${p.bash("grep -rn \"^import\" --include='*.ts' . | grep -v node_modules | head -50")}. For each detected cycle, list the file path chain and assign severity: high (3+ files), medium (2 files shared between critical paths), low (leaf-only cycles).`, + output: s.object({ + hasCycles: s.boolean, + cycles: s.array(s.object({ + path: s.array(s.string), + severity: s.enum("high", "medium", "low"), + })), + }), + maxTurns: 5, + addons: repair(), +}); + +export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts new file mode 100644 index 0000000..0c92ce1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts @@ -0,0 +1,32 @@ +import { agent, p, s, defineTool } from "rig"; + +const scanUsage = defineTool("scanUsage", { + description: "Count how many times a symbol name appears across TypeScript files (approximate usage)", + parameters: s.object({ symbol: s.string }), + async handler({ symbol }) { + const { execSync } = await import("node:child_process"); + try { + const result = execSync( + `grep -rn --include="*.ts" "\\b${symbol}\\b" . | grep -v "^.*export " | grep -v node_modules | wc -l`, + { encoding: "utf8" } + ).trim(); + return { count: parseInt(result, 10) || 0 }; + } catch { + return { count: 0 }; + } + }, +}); + +// Agent role: count usage of exported TypeScript symbols and classify coverage level. +const tsExportUsage = agent({ + model: "typecheck", + instructions: p`Find all exported symbols in TypeScript files: ${p.bash("grep -rn --include='*.ts' 'export (function|class|const|type|interface)' . | grep -v node_modules | head -40")}. For each symbol name, use the scanUsage tool to count references. Classify coverageLevel as none (0 usages), low (1-2), medium (3-9), high (≥10). Record the file where the symbol was last found as lastFile if available.`, + output: s.record(s.object({ + usageCount: s.number, + coverageLevel: s.enum("none", "low", "medium", "high"), + lastFile: s.optional(s.string), + })), + tools: [scanUsage], +}); + +export default tsExportUsage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts new file mode 100644 index 0000000..a629cc7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: track file renames in git history and produce a structured rename log. +const gitRenameTracker = agent({ + model: "typecheck", + instructions: p`Retrieve git file rename history: ${p.bash("git log --diff-filter=R --summary --pretty=format:'%h %ai' | head -60 2>/dev/null || echo 'No renames found'")}. Parse each rename entry (lines containing "rename from/to") and associate it with the commit hash and date from the preceding format line. Return an array of rename events sorted newest first.`, + output: s.array(s.object({ + hash: s.string, + date: s.string, + oldPath: s.string, + newPath: s.string, + })), + maxTurns: 4, + addons: repair(), +}); + +export default gitRenameTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts new file mode 100644 index 0000000..daf30e4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts @@ -0,0 +1,36 @@ +import { agent, p, s, defineTool } from "rig"; + +const validateYaml = defineTool("validateYaml", { + description: "Structurally validate a YAML file's content for common issues and required top-level keys", + parameters: s.object({ filename: s.string, content: s.string }), + handler({ filename, content }) { + const issues: string[] = []; + const lines = content.split("\n"); + const lineCount = lines.length; + const isWorkflow = filename.includes(".github/workflows"); + if (isWorkflow) { + if (!content.includes("name:")) issues.push("Missing 'name' key"); + if (!content.includes("on:") && !content.includes("\"on\":")) issues.push("Missing 'on' trigger"); + if (!content.includes("jobs:")) issues.push("Missing 'jobs' key"); + } + if (content.includes("\t")) issues.push("Contains tab characters (use spaces in YAML)"); + const trailingWhitespace = lines.filter((l: string) => l !== l.trimEnd()).length; + if (trailingWhitespace > 0) issues.push(`${trailingWhitespace} lines with trailing whitespace`); + const status = issues.length === 0 ? "pass" : issues.some((i: string) => i.startsWith("Missing")) ? "fail" : "warn"; + return { issues, lineCount, status }; + }, +}); + +// Agent role: lint YAML files in the repository and report structural issues. +const yamlLintChecker = agent({ + model: "typecheck", + instructions: p`Find YAML files in this repository: ${p.bash("find . -name '*.yml' -o -name '*.yaml' | grep -v node_modules | grep -v .git | head -20")}. For each file, read its content and use the validateYaml tool to check for structural issues. Compile results keyed by relative file path.`, + output: s.record(s.object({ + issues: s.array(s.string), + lineCount: s.number, + status: s.enum("pass", "warn", "fail"), + })), + tools: [validateYaml], +}); + +export default yamlLintChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts new file mode 100644 index 0000000..9b341b2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts @@ -0,0 +1,29 @@ +import { agent, p, s } from "rig"; + +// Agent role: extract TypeScript function names and line counts from source files. +const extractor = agent({ + name: "extractor", + model: "typecheck", + instructions: p`Scan TypeScript source files: ${p.bash("grep -rn --include='*.ts' 'function \\|=>.*(\\|async ' . | grep -v node_modules | grep -v '.test.' | head -60")}. For each function found, estimate its line count by looking at surrounding context. Return a JSON object mapping function names to their approximate line counts.`, + output: s.record(s.number), +}); + +// Agent role: classify function complexity based on line counts and produce a summary report. +const complexityReviewer = agent({ + name: "complexityReviewer", + model: "typecheck", + instructions: p`Delegate to extractor to obtain a JSON record of function names to line counts. Classify each function as: simple (<10 lines), moderate (10-29), complex (30-59), or critical (≥60). Count the total number of complex+critical functions for the summary.`, + output: s.object({ + functions: s.record(s.object({ + lineCount: s.number, + complexity: s.enum("simple", "moderate", "complex", "critical"), + })), + summary: s.object({ + totalFunctions: s.number, + complexCount: s.number, + }), + }), + agents: { extractor }, +}); + +export default complexityReviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts new file mode 100644 index 0000000..a44ca23 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts @@ -0,0 +1,13 @@ +import { agent, s } from "rig"; +// Agent role: triage the pull request and recommend reviewers. +const triage = agent({ + model: "typecheck", + output: s.object({ + area: s.enum("runtime", "docs", "tests", "ci", "unknown"), + risk: s.enum("low", "medium", "high"), + reviewers: s.array(s.string), + reason: s.string + }), + instructions: `Triage the pull request and recommend reviewers.`, +}); +export default triage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts new file mode 100644 index 0000000..abf3e4e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts @@ -0,0 +1,43 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +// Agent role: detect drift in workspace config files against a baseline. +const workspaceConfigDrift = agent({ + model: "typecheck", + maxTurns: 6, + addons: repair(), + input: s.object({ + baselineFile: s.path, + }), + instructions: p`Read the baseline config from ${p.readInput("baselineFile")}. +Compare it against the current workspace configs: +- tsconfig.json: ${p.readOptional("tsconfig.json", "{}")} +- .eslintrc.json: ${p.readOptional(".eslintrc.json", "{}")} +- .prettierrc: ${p.readOptional(".prettierrc", "{}")} + +Use the parseJson tool to parse each config. For each file, identify fields that differ from +the baseline. Return only the declared output.`, + tools: [ + defineTool("parseJson", { + description: "Parse a JSON string and return the keys", + parameters: s.object({ content: s.string }), + handler({ content }) { + try { + return Object.keys(JSON.parse(content)); + } catch { + return []; + } + }, + }), + ], + output: s.object({ + results: s.record( + s.object({ + driftedFields: s.array(s.string), + status: s.enum("ok", "warning", "error"), + }) + ), + overallStatus: s.enum("ok", "warning", "error"), + }), +}); + +export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts new file mode 100644 index 0000000..951e78f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts @@ -0,0 +1,27 @@ +import { agent, p, s, repair, steering } from "rig"; + +// Agent role: suggest conventional-format rewrites for recent git commit messages. +const conventionalCommitSuggester = agent({ + model: "typecheck", + maxTurns: 6, + addons: [steering({ message: "Ensure each suggestion follows the conventional commits spec: (?): using imperative mood." }), repair()], + instructions: p`Review the recent git log and suggest conventional commit message rewrites: +${p.bash("git log --oneline -20")} + +For each commit, identify the best category (feat/fix/chore/docs/test/refactor/style) and +rewrite the message to follow the conventional commits spec in imperative mood. +Write the full report to output. Return only the declared output.`, + output: s.object({ + suggestions: s.array( + s.object({ + hash: s.string, + original: s.string, + suggested: s.string, + category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), + }) + ), + totalReviewed: s.int, + }), +}); + +export default conventionalCommitSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts new file mode 100644 index 0000000..0e3a448 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts @@ -0,0 +1,35 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: inspect the runtime environment and report health status. +const runtimeEnvHealth = agent({ + model: "typecheck", + instructions: p`Inspect the runtime environment using the collected info: +Node.js version: ${p.bash("node --version")} +OS info: ${p.bash("uname -a")} +Memory: ${p.bash("free -m 2>/dev/null || vm_stat 2>/dev/null || echo 'unknown'")} + +Use the checkThreshold tool to validate Node.js version (minimum v18) and available memory +(minimum 256 MB). Return only the declared output.`, + tools: [ + defineTool("checkThreshold", { + description: "Check if a numeric value meets a minimum threshold", + parameters: s.object({ + value: s.number, + minimum: s.number, + label: s.string, + }), + handler({ value, minimum, label }) { + return { label, ok: value >= minimum, value, minimum }; + }, + }), + ], + output: s.object({ + nodeVersion: s.string, + os: s.string, + memoryMb: s.number, + health: s.enum("ok", "degraded", "critical"), + issues: s.array(s.string), + }), +}); + +export default runtimeEnvHealth; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts new file mode 100644 index 0000000..1988c19 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts @@ -0,0 +1,26 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: identify hot-spot files by git churn and top contributors. +const gitHotspotAnalyzer = agent({ + model: "typecheck", + addons: steering({ message: "Focus only on the top 10 files by change frequency. Skip binary files and node_modules." }), + instructions: p`Analyze git history to find the most frequently changed files. + +Changed files from git log: +${p.bash("git log --follow --name-only --format='' -- . | sort | uniq -c | sort -rn | head -20")} + +For the top files identified, get contributor info: +${p.bash("git shortlog -sn --all -- . 2>/dev/null | head -10")} + +Select the top 10 files by churn score. For each file compute a churnScore +(number of commits) and list topContributors. Return only the declared output as a record +keyed by file path.`, + output: s.record( + s.object({ + churnScore: s.number, + topContributors: s.array(s.string), + }) + ), +}); + +export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts new file mode 100644 index 0000000..5596850 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts @@ -0,0 +1,35 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: gather lines-of-code statistics per file extension. +const locStatisticsGatherer = agent({ + model: "typecheck", + instructions: p`Count lines of code by file extension in this workspace. + +Source files found: +${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' \\( -name '*.ts' -o -name '*.js' -o -name '*.py' -o -name '*.go' -o -name '*.rs' \\) 2>/dev/null | head -200")} + +Line counts: +${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' \\( -name '*.ts' -o -name '*.js' -o -name '*.py' \\) -exec wc -l {} + 2>/dev/null | tail -5")} + +Use the classifyComplexity tool to determine overall complexity. Aggregate results by extension. +Return only the declared output.`, + tools: [ + defineTool("classifyComplexity", { + description: "Classify total line count into complexity bucket", + parameters: s.object({ totalLines: s.int }), + handler({ totalLines }) { + if (totalLines < 1000) return "small"; + if (totalLines < 10000) return "medium"; + if (totalLines < 100000) return "large"; + return "xlarge"; + }, + }), + ], + output: s.object({ + byExtension: s.record(s.object({ lineCount: s.int, fileCount: s.int })), + totalLines: s.int, + complexity: s.enum("small", "medium", "large", "xlarge"), + }), +}); + +export default locStatisticsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts new file mode 100644 index 0000000..622abcd --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts @@ -0,0 +1,37 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: detect circular import cycles in the TypeScript project. +const importCycleDetector = agent({ + model: "typecheck", + maxTurns: 6, + addons: repair(), + instructions: p`Detect circular imports in this TypeScript project. + +TypeScript config: +${p.bash("cat tsconfig.json 2>/dev/null || echo '{}'")} + +Circular imports (via madge): +${p.bash("npx --yes madge --circular --extensions ts . 2>/dev/null || echo 'madge not available or no cycles found'")} + +Alternatively, check for potential cycles by scanning imports: +${p.bash("grep -r --include='*.ts' 'from.*\\.' . 2>/dev/null | grep -v node_modules | head -50")} + +Identify any circular import chains. For each cycle, classify severity: +- high: cycles in core/shared modules +- medium: cycles in feature modules +- low: cycles in utility or test files + +Return only the declared output.`, + output: s.object({ + hasCycles: s.boolean, + cycles: s.array( + s.object({ + path: s.array(s.string), + severity: s.enum("high", "medium", "low"), + }) + ), + cycleCount: s.int, + }), +}); + +export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts new file mode 100644 index 0000000..19ba718 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts @@ -0,0 +1,42 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: generate barrel index.ts files for TypeScript source directories. +const barrelFileGenerator = agent({ + model: "typecheck", + input: s.object({ + srcDir: s.path, + }), + instructions: p`Generate barrel index.ts files for TypeScript source directories. + +Source files found (excluding index.ts): +${p.bash("find . -name '*.ts' ! -name 'index.ts' ! -name '*.test.ts' ! -name '*.spec.ts' -not -path '*/node_modules/*' 2>/dev/null | head -100")} + +Use the classifyExports tool to identify exported symbols in files. Then generate barrel +content for each directory that has exported symbols. Write each barrel file using p.write. + +Count the total number of files scanned, barrel files that would be written, export count, +and directories involved. Return only the declared output.`, + tools: [ + defineTool("classifyExports", { + description: "Scan a TypeScript file path and detect export patterns", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { execSync } = await import("node:child_process"); + try { + const out = execSync(`grep -n "^export " "${filePath}" 2>/dev/null || true`, { encoding: "utf-8" }); + return { filePath, exportLines: out.trim().split("\n").filter(Boolean).length }; + } catch { + return { filePath, exportLines: 0 }; + } + }, + }), + ], + output: s.object({ + filesScanned: s.int, + barrelFilesWritten: s.int, + exportCount: s.int, + directories: s.array(s.string), + }), +}); + +export default barrelFileGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts new file mode 100644 index 0000000..e43e1a7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts @@ -0,0 +1,38 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: inventory git hooks and classify each as active, stub, or missing. +const gitHookInventory = agent({ + model: "typecheck", + instructions: p`Inventory the git hooks in this repository. + +Available hooks in .git/hooks: +${p.bash("ls .git/hooks/ 2>/dev/null || echo 'no hooks directory'")} + +Sample hooks content: +${p.bash("for f in .git/hooks/pre-commit .git/hooks/commit-msg .git/hooks/pre-push; do echo \"=== $f ===\"; cat \"$f\" 2>/dev/null || echo 'missing'; done")} + +Use the classifyHook tool to classify each hook. Return a record keyed by hook name +with status, summary, and whether it runs asynchronously (uses & or async patterns). +Return only the declared output.`, + tools: [ + defineTool("classifyHook", { + description: "Classify a git hook by its content", + parameters: s.object({ name: s.string, content: s.string }), + handler({ content }) { + if (!content || content === "missing") return { status: "missing", isAsync: false }; + const isSample = content.includes("sample") || content.trim() === "#!/bin/sh"; + const isAsync = content.includes(" &") || content.includes("async"); + return { status: isSample ? "stub" : "active", isAsync }; + }, + }), + ], + output: s.record( + s.object({ + summary: s.string, + status: s.enum("active", "stub", "missing"), + isAsync: s.boolean, + }) + ), +}); + +export default gitHookInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts new file mode 100644 index 0000000..5c58d40 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts @@ -0,0 +1,39 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: generate a PR review checklist from the recent git diff. +const prReviewChecklist = agent({ + model: "typecheck", + maxTurns: 6, + addons: repair(), + instructions: p`Generate a PR review checklist based on the changes in this branch. + +Changed files: +${p.bash("git diff --name-only HEAD~1 2>/dev/null || git diff --name-only HEAD 2>/dev/null || echo 'no diff available'")} + +Diff summary: +${p.bash("git diff --stat HEAD~1 2>/dev/null || git diff --stat HEAD 2>/dev/null || echo 'no diff stats'")} + +Key changes: +${p.bash("git diff HEAD~1 -- . 2>/dev/null | head -200 || echo 'no diff content'")} + +For each concern in the changes, produce a checklist item with: +- A clear action item description +- Category (test/docs/security/performance/style) +- Priority (high/medium/low) + +Also list the changed files and indicate if the PR is ready for review. +Return only the declared output.`, + output: s.object({ + checklist: s.array( + s.object({ + item: s.string, + category: s.enum("test", "docs", "security", "performance", "style"), + priority: s.enum("high", "medium", "low"), + }) + ), + changedFiles: s.array(s.string), + ready: s.boolean, + }), +}); + +export default prReviewChecklist; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts new file mode 100644 index 0000000..6143673 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts @@ -0,0 +1,43 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: analyze JavaScript source map files and classify their mapping density. +const sourceMapAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze JavaScript source map files in this workspace. + +Source map files found: +${p.bash("find . -name '*.js.map' -not -path '*/node_modules/*' 2>/dev/null | head -50")} + +Use the parseSourceMap tool to read and analyze each source map file. +For each file, determine sourceCount, mapping density, and whether sourcesContent is present. +Return a record keyed by source map file path. Return only the declared output.`, + tools: [ + defineTool("parseSourceMap", { + description: "Parse a source map file and extract metadata", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf-8"); + const map = JSON.parse(content); + const sourceCount: number = Array.isArray(map.sources) ? map.sources.length : 0; + const mappingLen: number = typeof map.mappings === "string" ? map.mappings.length : 0; + const density = mappingLen < 100 ? "sparse" : mappingLen < 1000 ? "medium" : "dense"; + const hasSourcesContent = Array.isArray(map.sourcesContent) && map.sourcesContent.length > 0; + return { sourceCount, density, hasSourcesContent }; + } catch { + return { sourceCount: 0, density: "sparse", hasSourcesContent: false }; + } + }, + }), + ], + output: s.record( + s.object({ + sourceCount: s.int, + mappingDensity: s.enum("sparse", "medium", "dense"), + hasSourcesContent: s.boolean, + }) + ), +}); + +export default sourceMapAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts new file mode 100644 index 0000000..0dabc83 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts @@ -0,0 +1,13 @@ +import { agent, s } from "rig"; +// Agent role: write release notes from commits. Omit empty sections as empty arrays. +const releaseNotes = agent({ + model: "typecheck", + output: s.object({ + version: s.optional(s.string), + highlights: s.array(s.string), + breaking: s.array(s.string), + fixes: s.array(s.string) + }), + instructions: `Write release notes from commits. Omit empty sections as empty arrays.`, +}); +export default releaseNotes; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts new file mode 100644 index 0000000..71979e7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const getFileCommitCount = defineTool("getFileCommitCount", { + description: "Count how many commits touched a specific file", + parameters: s.object({ file: s.string }), + handler: async ({ file }) => { + const { execSync } = await import("node:child_process"); + try { + const result = execSync(`git log --follow --oneline -- "${file}" 2>/dev/null | wc -l`, { encoding: "utf8" }); + return result.trim(); + } catch { + return "0"; + } + }, +}); + +// Agent role: analyze git history to identify hot-spot files by commit frequency and contributor count +const gitHotspotAnalyzer = agent({ + name: "gitHotspotAnalyzer", + model: "typecheck", + maxTurns: 3, + addons: repair(), + instructions: p`Analyze the git history to identify file hot-spots. + +Changed files: ${p.bash("git log --follow --name-only --format='' -- . 2>/dev/null | sort | uniq -c | sort -rn | head -30")} + +Contributors: ${p.bash("git shortlog -sn --no-merges 2>/dev/null | head -10")} + +Use the getFileCommitCount tool to look up commit counts for the top files. +For each file, determine its hotspot level based on commit count: +- critical: 50+ commits +- high: 20–49 commits +- medium: 5–19 commits +- low: fewer than 5 commits + +Return a record keyed by file path with commitCount, topContributors array, and hotspotLevel.`, + output: s.record( + s.object({ + commitCount: s.int, + topContributors: s.array(s.string), + hotspotLevel: s.enum("low", "medium", "high", "critical"), + }) + ), + tools: [getFileCommitCount], +}); + +export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts new file mode 100644 index 0000000..3e557c7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool } from "rig"; + +const countLinesByExtension = defineTool("countLinesByExtension", { + description: "Count total lines for files with a given extension", + parameters: s.object({ extension: s.string }), + handler: async ({ extension }) => { + const { execSync } = await import("node:child_process"); + try { + const result = execSync( + `find . -type f -name "*.${extension}" -not -path "*/node_modules/*" | xargs wc -l 2>/dev/null | tail -1`, + { encoding: "utf8" } + ); + return result.trim(); + } catch { + return "0"; + } + }, +}); + +// Agent role: gather lines-of-code statistics per file extension and rate the overall complexity +const locStatsGatherer = agent({ + name: "locStatsGatherer", + model: "typecheck", + instructions: p`Gather lines-of-code statistics for this workspace. + +File extension counts: ${p.bash("find . -type f -not -path '*/node_modules/*' -not -path '*/.git/*' | sed 's/.*\\.//' | sort | uniq -c | sort -rn | head -20")} + +TypeScript files: ${p.bash("find . -type f -name '*.ts' -not -path '*/node_modules/*' | head -100")} + +Total line count: ${p.bash("find . -type f -name '*.ts' -not -path '*/node_modules/*' | xargs wc -l 2>/dev/null | tail -1")} + +Use the countLinesByExtension tool to get line counts for the top extensions. +Compute byExtension record with fileCount and lineCount per extension. +Set complexityRating based on totalLines: small (<1000), medium (1000–10000), large (10000–100000), xlarge (100000+).`, + output: s.object({ + byExtension: s.record(s.object({ fileCount: s.int, lineCount: s.int })), + totalLines: s.int, + largestExtension: s.string, + complexityRating: s.enum("small", "medium", "large", "xlarge"), + }), + tools: [countLinesByExtension], +}); + +export default locStatsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts new file mode 100644 index 0000000..d8fc697 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts @@ -0,0 +1,36 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: detect import cycles in a TypeScript project and assess their severity +const importCycleDetector = agent({ + name: "importCycleDetector", + model: "typecheck", + maxTurns: 3, + addons: repair(), + instructions: p`Detect circular imports in this TypeScript project. + +Madge circular analysis: ${p.bash("npx madge --circular --extensions ts . 2>/dev/null || echo 'madge not available, use heuristic analysis'")} + +TypeScript config: ${p.readOptional("tsconfig.json", "{}")} + +Source files: ${p.bash("find . -type f -name '*.ts' -not -path '*/node_modules/*' | head -30")} + +Identify any circular import cycles. For each cycle, list the file path array forming the cycle and rate severity: +- high: cycles involving core modules or many files +- medium: cycles involving 3–5 files +- low: simple two-file cycles + +Set hasCycles to true if any cycles exist. Provide a recommendation for resolving them.`, + output: s.object({ + hasCycles: s.boolean, + cycles: s.array( + s.object({ + path: s.array(s.string), + severity: s.enum("high", "medium", "low"), + }) + ), + cycleCount: s.int, + recommendation: s.string, + }), +}); + +export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts new file mode 100644 index 0000000..d41c11b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts @@ -0,0 +1,30 @@ +import { agent, p, s } from "rig"; + +// Agent role: read coverage data and generate shields.io badge markdown, writing it to a file +const coverageBadgeUpdater = agent({ + name: "coverageBadgeUpdater", + model: "typecheck", + instructions: p`Read coverage data and generate badge markdown for README. + +Coverage summary: ${p.readOptional("coverage/coverage-summary.json", "{}")} + +Current README: ${p.read("README.md")} + +Parse the coverage summary JSON. Extract per-category percentages (lines, statements, functions, branches). +Compute the overall percentage as the average. +Set rating: green (>=80%), yellow (60–79%), red (<60%). +Generate shields.io badge markdown for each category and overall. +Set badgesWritten to true. +The badgeMarkdown field will be written to coverage-badge.md. + +${p.writeOutput("badgeMarkdown", "coverage-badge.md")}`, + output: s.object({ + coverageByCategory: s.record(s.number), + overallPct: s.number, + rating: s.enum("green", "yellow", "red"), + badgesWritten: s.boolean, + badgeMarkdown: s.string, + }), +}); + +export default coverageBadgeUpdater; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts new file mode 100644 index 0000000..5368c2b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyLicense = defineTool("classifyLicense", { + description: "Classify a license string as permissive, copyleft, or unknown", + parameters: s.object({ license: s.string }), + handler: ({ license }) => { + const l = license.toLowerCase(); + const permissive = ["mit", "apache", "bsd", "isc", "0bsd", "unlicense", "wtfpl", "cc0", "zlib"]; + const copyleft = ["gpl", "lgpl", "agpl", "mpl", "eupl", "cddl"]; + if (permissive.some((p) => l.includes(p))) return "permissive"; + if (copyleft.some((c) => l.includes(c))) return "copyleft"; + return "unknown"; + }, +}); + +// Agent role: audit npm dependency licenses and flag copyleft or unknown licenses +const depLicenseAuditor = agent({ + name: "depLicenseAuditor", + model: "typecheck", + instructions: p`Audit the licenses of npm dependencies in this project. + +Direct dependencies: ${p.bash("npm ls --json --depth=0 2>/dev/null | head -200")} + +License fields: ${p.bash("cat node_modules/*/package.json 2>/dev/null | grep -E '\"license\"' | sort -u | head -50")} + +For each direct dependency, use the classifyLicense tool to classify its license as permissive, copyleft, or unknown. +Assign riskLevel: copyleft=review, unknown=review, permissive=safe; if license is missing set riskLevel=blocked. +Set hasCopyleft to true if any package has classification=copyleft.`, + output: s.object({ + packages: s.array( + s.object({ + name: s.string, + version: s.string, + license: s.string, + classification: s.enum("permissive", "copyleft", "unknown"), + riskLevel: s.enum("safe", "review", "blocked"), + }) + ), + hasCopyleft: s.boolean, + totalPackages: s.int, + }), + tools: [classifyLicense], +}); + +export default depLicenseAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts new file mode 100644 index 0000000..7128ec6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const findTestFile = defineTool("findTestFile", { + description: "Find the best matching test file for a given source file using filename heuristics", + parameters: s.object({ + sourceFile: s.string, + testFiles: s.array(s.string), + }), + handler: ({ sourceFile, testFiles }) => { + const baseName = sourceFile.replace(/\.ts$/, "").replace(/.*\//, ""); + const matches = testFiles.filter( + (t) => + t.includes(baseName + ".test") || + t.includes(baseName + ".spec") || + t.includes(baseName.replace(/([A-Z])/g, "-$1").toLowerCase()) + ); + return JSON.stringify(matches); + }, +}); + +// Agent role: map source files to their test files using filename heuristics +const testCoverageMapper = agent({ + name: "testCoverageMapper", + model: "typecheck", + maxTurns: 2, + addons: repair(), + instructions: p`Map source files to their corresponding test files using filename heuristics. + +Source files: ${p.bash("find . -type f -name '*.ts' -not -name '*.test.ts' -not -name '*.spec.ts' -not -path '*/node_modules/*' | head -50")} + +Test files: ${p.bash("find . -type f \\( -name '*.test.ts' -o -name '*.spec.ts' \\) -not -path '*/node_modules/*' | head -50")} + +For each source file, use the findTestFile tool to look up matching test files. +Set coverage: +- covered: one or more test files found +- partial: test file found but name match is weak +- uncovered: no test files found + +Return a record keyed by source file path.`, + output: s.record( + s.object({ + coverage: s.enum("covered", "uncovered", "partial"), + testFiles: s.array(s.string), + reason: s.string, + }) + ), + tools: [findTestFile], +}); + +export default testCoverageMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts new file mode 100644 index 0000000..a2a9fb2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts @@ -0,0 +1,57 @@ +import { agent, p, s, defineTool, steering, repair } from "rig"; + +const checkOption = defineTool("checkOption", { + description: "Check whether a tsconfig compiler option matches the recommended value", + parameters: s.object({ + option: s.string, + value: s.unknown, + recommended: s.unknown, + }), + handler: ({ value, recommended }) => { + return JSON.stringify(value) === JSON.stringify(recommended) ? "pass" : "fail"; + }, +}); + +// Agent role: audit TypeScript compiler options against best-practice recommendations +const tsconfigOptionsAuditor = agent({ + name: "tsconfigOptionsAuditor", + model: "typecheck", + addons: [steering(), repair()], + instructions: p`Audit TypeScript compiler options in this project against best-practice recommendations. + +tsconfig.json: ${p.readOptional("tsconfig.json", "{}")} + +tsconfig.base.json: ${p.readOptional("tsconfig.base.json", "{}")} + +Check the following recommended settings using the checkOption tool: +- strict: true +- noImplicitAny: true +- strictNullChecks: true +- noUnusedLocals: true +- noUnusedParameters: true +- exactOptionalPropertyTypes: true +- noFallthroughCasesInSwitch: true +- esModuleInterop: true +- skipLibCheck: true +- forceConsistentCasingInFileNames: true + +Determine complianceLevel: strict (9–10 pass), moderate (6–8 pass), loose (3–5 pass), unconfigured (<3 pass). +Return all options checked with status and reason.`, + output: s.object({ + options: s.array( + s.object({ + name: s.string, + currentValue: s.unknown, + recommendedValue: s.unknown, + status: s.enum("pass", "fail", "missing", "warn"), + reason: s.string, + }) + ), + complianceLevel: s.enum("strict", "moderate", "loose", "unconfigured"), + totalChecked: s.int, + passCount: s.int, + }), + tools: [checkOption], +}); + +export default tsconfigOptionsAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts new file mode 100644 index 0000000..ffd9298 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts @@ -0,0 +1,52 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize a single git commit into a category and impact rating +const commitSummarizer = agent({ + name: "commitSummarizer", + model: "typecheck", + instructions: p`Analyze the git commit message provided in the input and classify it. + +Commit info: ${p.inputField("commitLine")} + +Classify the commit into a category (feat, fix, chore, docs, refactor, test, perf). +Write a concise one-sentence summary. +Rate the impact as low, medium, or high based on likely scope of change.`, + input: s.object({ commitLine: s.string }), + output: s.object({ + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + summary: s.string, + impact: s.enum("low", "medium", "high"), + }), +}); + +// Agent role: annotate recent git commits with category, summary, and impact, writing a markdown report +const gitCommitAnnotator = agent({ + name: "gitCommitAnnotator", + model: "typecheck", + agents: { commitSummarizer }, + instructions: p`Annotate the 20 most recent git commits with category, summary, and impact. + +Recent commits: ${p.bash("git log --oneline -20")} + +For each commit line, delegate to the commitSummarizer subagent. +Collect all annotations and build a markdown report with a table of hash, category, summary, and impact. +Set totalAnnotated to the number of commits annotated. +The report field will be written to commit-annotations.md. + +${p.writeOutput("report", "commit-annotations.md")}`, + output: s.object({ + annotations: s.array( + s.object({ + hash: s.string, + original: s.string, + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + summary: s.string, + impact: s.enum("low", "medium", "high"), + }) + ), + report: s.string, + totalAnnotated: s.int, + }), +}); + +export default gitCommitAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts new file mode 100644 index 0000000..1102bbf --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts @@ -0,0 +1,57 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseScriptDeps = defineTool("parseScriptDeps", { + description: "Parse pre/post hooks and npm run references for a script", + parameters: s.object({ + scriptName: s.string, + scriptBody: s.string, + allScripts: s.record(s.string), + }), + handler: ({ scriptName, scriptBody, allScripts }) => { + const deps: string[] = []; + const runRefs = scriptBody.match(/npm run ([\w:-]+)/g) || []; + runRefs.forEach((r) => deps.push(r.replace("npm run ", ""))); + const preName = "pre" + scriptName; + const postName = "post" + scriptName; + if (allScripts[preName]) deps.push(preName); + if (allScripts[postName]) deps.push(postName); + return JSON.stringify(deps); + }, +}); + +// Agent role: map npm script dependencies by analyzing pre/post hooks and npm run references +const npmScriptDepMapper = agent({ + name: "npmScriptDepMapper", + model: "typecheck", + maxTurns: 2, + addons: repair(), + instructions: p`Map npm script dependencies by analyzing the package.json scripts. + +package.json: ${p.read("package.json")} + +For each script, use the parseScriptDeps tool to find its dependencies (npm run references and pre/post hooks). +Classify each script category: +- build: scripts that compile or bundle +- test: scripts that run tests +- lint: scripts that lint or format +- dev: scripts for development +- deploy: scripts for deployment +- util: utility scripts +- hook: pre/post lifecycle hooks +- other: anything else + +Set hasPreHook and hasPostHook based on whether pre or post scripts exist. +Return a record keyed by script name.`, + output: s.record( + s.object({ + command: s.string, + dependsOn: s.array(s.string), + category: s.enum("build", "test", "lint", "dev", "deploy", "util", "hook", "other"), + hasPreHook: s.boolean, + hasPostHook: s.boolean, + }) + ), + tools: [parseScriptDeps], +}); + +export default npmScriptDepMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts new file mode 100644 index 0000000..d8e4dce --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts @@ -0,0 +1,57 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const checkUrl = defineTool("checkUrl", { + description: "Check HTTP status of a URL using curl", + parameters: s.object({ url: s.string }), + handler: async ({ url }) => { + const { execSync } = await import("node:child_process"); + try { + const code = execSync( + `curl --head --silent --max-time 5 -o /dev/null -w "%{http_code}" "${url}" 2>/dev/null`, + { encoding: "utf8", timeout: 8000 } + ).trim(); + return code; + } catch { + return "timeout"; + } + }, +}); + +// Agent role: check HTTP status of links found in markdown files +const markdownLinkChecker = agent({ + name: "markdownLinkChecker", + model: "typecheck", + addons: repair(), + instructions: p`Find and check HTTP links in markdown files. + +Markdown files: ${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -20")} + +URLs found: ${p.bash("grep -roh 'https\\?://[^)\"\\s]*' . --include='*.md' 2>/dev/null | sort -u | head -50")} + +For each unique URL, use the checkUrl tool to get the HTTP status code. +Classify status: +- ok: 200–299 +- redirect: 301, 302, 307, 308 +- broken: 400–599 +- timeout: curl timed out +- skipped: non-http or malformed URL + +Set allValid to true only if no links are broken. +Include foundInFile for each link if determinable.`, + output: s.object({ + links: s.array( + s.object({ + url: s.url, + status: s.enum("ok", "broken", "redirect", "timeout", "skipped"), + httpCode: s.optional(s.int), + foundInFile: s.optional(s.path), + }) + ), + totalChecked: s.int, + brokenCount: s.int, + allValid: s.boolean, + }), + tools: [checkUrl], +}); + +export default markdownLinkChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts new file mode 100644 index 0000000..1a80a67 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts @@ -0,0 +1,15 @@ +import { agent, s } from "rig"; +// Agent role: review dependency security posture from the provided outputs. +const securityReview = agent({ + model: "typecheck", + output: s.object({ + status: s.enum("clean", "needs-action", "unknown"), + findings: s.array(s.object({ + package: s.string, + severity: s.string, + action: s.string + })) + }), + instructions: `Review dependency security posture from the provided outputs.`, +}); +export default securityReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts new file mode 100644 index 0000000..41e706e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts @@ -0,0 +1,15 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: analyze which files are hot-spots by measuring commit churn and top contributors. +const gitHotspotAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze file churn in this repository. List all tracked files: ${p.bash("git ls-files --exclude-standard | head -100")}. Get commit counts per file: ${p.bash("git log --follow --name-only --format='' -- . | sort | uniq -c | sort -rn | head -40")}. Get top contributors per file via: ${p.bash("git shortlog -sn --no-merges HEAD~50..HEAD 2>/dev/null || git shortlog -sn --no-merges | head -20")}. For each hot-spot file compute a churnScore 0–100 (based on commit frequency relative to max) and list topContributors.`, + output: s.record(s.object({ + churnScore: s.number, + topContributors: s.array(s.string), + })), + maxTurns: 5, + addons: [steering({ message: "Every file must have a numeric churnScore between 0 and 100 and at least one topContributor entry." })], +}); + +export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts new file mode 100644 index 0000000..885bbfb --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts @@ -0,0 +1,37 @@ +import { agent, p, s, defineTool } from "rig"; + +const aggregateByExtension = defineTool("aggregateByExtension", { + description: "Parse wc -l output and aggregate line and file counts by extension", + parameters: s.object({ wcOutput: s.string }), + handler: ({ wcOutput }) => { + const totals: Record = {}; + for (const line of wcOutput.trim().split("\n")) { + const match = line.trim().match(/^(\d+)\s+(.+)$/); + if (!match) continue; + const count = parseInt(match[1], 10); + const filePath = match[2]; + if (filePath === "total") continue; + const ext = filePath.includes(".") ? "." + filePath.split(".").pop()! : "(none)"; + if (!totals[ext]) totals[ext] = { lineCount: 0, fileCount: 0 }; + totals[ext].lineCount += count; + totals[ext].fileCount += 1; + } + return JSON.stringify(totals); + }, +}); + +// Agent role: gather lines-of-code statistics per file extension and classify overall complexity. +const locStatisticsGatherer = agent({ + model: "typecheck", + instructions: p`Gather lines-of-code statistics for this repository. List files: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f | head -200")}. Count lines per file: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f -exec wc -l {} + 2>/dev/null | tail -30")}. Use aggregateByExtension to sum lineCount and fileCount per extension. Compute complexityRating: small (<1000 total lines), medium (<5000), large (<20000), xlarge (>=20000).`, + output: s.object({ + byExtension: s.record(s.object({ + lineCount: s.int, + fileCount: s.int, + })), + complexityRating: s.enum("small", "medium", "large", "xlarge"), + }), + tools: [aggregateByExtension], +}); + +export default locStatisticsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts new file mode 100644 index 0000000..e8e2e91 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts @@ -0,0 +1,26 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: detect circular import cycles in the TypeScript project and classify severity. +const importCycleDetector = agent({ + model: "typecheck", + maxTurns: 6, + addons: [repair()], + instructions: p`Detect circular imports in this TypeScript project. + +TypeScript config: ${p.bash("cat tsconfig.json 2>/dev/null || echo '{}'")} + +Circular dependency check: ${p.bash("npx --yes madge --circular --extensions ts . 2>/dev/null || echo 'madge unavailable'")} + +Import graph sample: ${p.bash("grep -r --include='*.ts' -h 'from ' . 2>/dev/null | grep -v node_modules | head -60")} + +Identify all circular import chains. For each cycle, list the path as an array of module names and classify severity: high (core/shared modules), medium (feature modules), low (utility/test files). Set hasCycles to true if any cycles were found.`, + output: s.object({ + hasCycles: s.boolean, + cycles: s.array(s.object({ + path: s.array(s.string), + severity: s.enum("high", "medium", "low"), + })), + }), +}); + +export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts new file mode 100644 index 0000000..587d496 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts @@ -0,0 +1,22 @@ +import { agent, p, s } from "rig"; + +// Agent role: read coverage summary and generate shields.io badge markdown, writing it to a coverage report file. +const coverageBadgeUpdater = agent({ + model: "typecheck", + instructions: p`Read coverage data and generate shields.io badge markdown. + +Coverage summary: ${p.readOptional("coverage/coverage-summary.json", "{}")} + +Current README: ${p.readOptional("README.md", "")} + +Parse the coverage summary JSON. Extract per-category percentages for statements, branches, functions, and lines. Compute overallPct as the average. Set rating: green (>=80%), yellow (60–79%), red (<60%). Generate shields.io badge markdown for each category and the overall percentage. Write the badge markdown to the output field badgeMarkdown. Set badgesWritten to true after generating. ${p.writeOutput("badgeMarkdown", "coverage-badges.md")}`, + output: s.object({ + coverageByCategory: s.record(s.number), + overallPct: s.number, + rating: s.enum("green", "yellow", "red"), + badgesWritten: s.boolean, + badgeMarkdown: s.string, + }), +}); + +export default coverageBadgeUpdater; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts new file mode 100644 index 0000000..7f363f9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts @@ -0,0 +1,37 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyLicense = defineTool("classifyLicense", { + description: "Classify a license identifier as permissive, copyleft, or unknown", + parameters: s.object({ license: s.string }), + handler: ({ license }) => { + const l = license.toLowerCase(); + const permissive = ["mit", "isc", "apache", "bsd", "0bsd", "unlicense", "cc0", "wtfpl", "zlib"]; + const copyleft = ["gpl", "lgpl", "agpl", "mpl", "eupl", "cddl"]; + if (permissive.some((p) => l.includes(p))) return "permissive"; + if (copyleft.some((c) => l.includes(c))) return "copyleft"; + return "unknown"; + }, +}); + +// Agent role: audit npm dependency licenses and flag copyleft or unknown packages. +const depLicenseAuditor = agent({ + model: "typecheck", + instructions: p`Audit the licenses of all direct npm dependencies. + +Direct dependencies: ${p.bash("npm ls --json --depth=0 2>/dev/null | head -300")} + +License fields from node_modules: ${p.bash("node -e \"const fs=require('fs'); const d='./node_modules'; if(fs.existsSync(d)) { fs.readdirSync(d).filter(n=>!n.startsWith('.')).slice(0,60).forEach(n=>{ try{const p=JSON.parse(fs.readFileSync(d+'/'+n+'/package.json','utf8')); console.log(n+'|'+(p.license||'NONE'))}catch(e){} }) }\" 2>/dev/null")} + +For each direct dependency, use classifyLicense to classify its license. Set hasCopyleft to true if any package has classification copyleft.`, + output: s.object({ + packages: s.array(s.object({ + name: s.string, + license: s.string, + classification: s.enum("permissive", "copyleft", "unknown"), + })), + hasCopyleft: s.boolean, + }), + tools: [classifyLicense], +}); + +export default depLicenseAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts new file mode 100644 index 0000000..87dfe01 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts @@ -0,0 +1,35 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const matchTestFile = defineTool("matchTestFile", { + description: "Find matching test files for a source file using filename heuristics", + parameters: s.object({ sourceFile: s.string, testFiles: s.array(s.string) }), + handler: ({ sourceFile, testFiles }) => { + const base = sourceFile.replace(/\.tsx?$/, "").replace(/.*\//, ""); + const matches = testFiles.filter( + (t) => t.includes(base + ".test") || t.includes(base + ".spec") + ); + return JSON.stringify({ matches, partial: matches.length === 0 ? testFiles.filter((t) => t.includes(base)).slice(0, 2) : [] }); + }, +}); + +// Agent role: map each TypeScript source file to its test files using filename heuristics. +const testCoverageMapper = agent({ + model: "typecheck", + maxTurns: 4, + addons: [repair()], + instructions: p`Map source files to their test counterparts. + +Source files: ${p.bash("find . -type f -name '*.ts' -not -name '*.test.ts' -not -name '*.spec.ts' -not -path '*/node_modules/*' | head -50")} + +Test files: ${p.bash("find . -type f \\( -name '*.test.ts' -o -name '*.spec.ts' \\) -not -path '*/node_modules/*' | head -50")} + +For each source file use matchTestFile to find matches. Classify coverage: covered (matches found), partial (weak match), uncovered (none). Return a record keyed by source file path.`, + output: s.record(s.object({ + coverage: s.enum("covered", "uncovered", "partial"), + testFiles: s.array(s.string), + reason: s.string, + })), + tools: [matchTestFile], +}); + +export default testCoverageMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts new file mode 100644 index 0000000..071d21e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts @@ -0,0 +1,27 @@ +import { agent, p, s } from "rig"; + +// Agent role: compare installed npm package versions against latest published versions and report drift. +const pkgVersionDrift = agent({ + model: "typecheck", + instructions: p`Compare installed npm package versions to the latest published versions. + +Package manifest: ${p.read("package.json")} + +Installed versions: ${p.bash("npm ls --depth=0 --json 2>/dev/null | head -200")} + +Latest versions for key packages: ${p.bash("npm outdated --json 2>/dev/null | head -200 || echo '{}'")} + +For each dependency, classify driftLevel: ok (up to date), patch (patch version behind), minor (minor version behind), major (major version behind). Write a human-readable drift summary report via ${p.writeOutput("report", "version-drift-report.md")}. Set reportWritten to true.`, + output: s.object({ + packages: s.array(s.object({ + name: s.string, + current: s.string, + latest: s.string, + driftLevel: s.enum("ok", "patch", "minor", "major"), + })), + reportWritten: s.boolean, + report: s.string, + }), +}); + +export default pkgVersionDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts new file mode 100644 index 0000000..ac28932 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts @@ -0,0 +1,24 @@ +import { agent, p, s } from "rig"; + +// Agent role: aggregate commit statistics per git author, including first/last commit dates and total counts. +const gitAuthorStats = agent({ + model: "typecheck", + instructions: p`Aggregate git commit statistics per author. + +Commit counts by author: ${p.bash("git shortlog -sne --all 2>/dev/null | head -40")} + +Commit log with dates: ${p.bash("git log --format='%ae|%ad' --date=short 2>/dev/null | head -200")} + +For each author email, compute commitCount, firstCommit date, and lastCommit date. Identify the topAuthor with the most commits. Compute totalCommits across all authors.`, + output: s.object({ + authors: s.record(s.object({ + commitCount: s.int, + firstCommit: s.string, + lastCommit: s.string, + })), + topAuthor: s.string, + totalCommits: s.int, + }), +}); + +export default gitAuthorStats; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts new file mode 100644 index 0000000..ac1f7bd --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts @@ -0,0 +1,37 @@ +import { agent, p, s, defineTool } from "rig"; +import { existsSync } from "node:fs"; + +const checkAlias = defineTool("checkAlias", { + description: "Check whether a TypeScript path alias target directory exists", + parameters: s.object({ alias: s.string, target: s.string }), + handler: ({ alias, target }) => { + const resolved = target.replace(/\/\*$/, ""); + const exists = existsSync(resolved); + return JSON.stringify({ alias, target, exists }); + }, +}); + +// Agent role: validate TypeScript path aliases from tsconfig against actual filesystem paths. +const tsPathAliasValidator = agent({ + model: "typecheck", + instructions: p`Validate TypeScript path alias configuration. + +tsconfig.json: ${p.read("tsconfig.json")} + +Files with aliased imports: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | xargs grep -l 'from [\"\\x27]' 2>/dev/null | head -20")} + +Import alias usage: ${p.bash("grep -r --include='*.ts' -h 'from [\"\\x27]' . 2>/dev/null | grep -v node_modules | grep -v '\\.' | head -40")} + +For each alias in compilerOptions.paths, use checkAlias to verify the target exists. Classify as valid (exists and used), broken (target missing), or unused (exists but no imports found). Report totalAliases and brokenCount.`, + output: s.object({ + aliases: s.record(s.object({ + target: s.string, + status: s.enum("valid", "broken", "unused"), + })), + totalAliases: s.int, + brokenCount: s.int, + }), + tools: [checkAlias], +}); + +export default tsPathAliasValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts new file mode 100644 index 0000000..44453de --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts @@ -0,0 +1,40 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFileSync, existsSync } from "node:fs"; + +const parseFrontmatter = defineTool("parseFrontmatter", { + description: "Parse YAML frontmatter from a markdown file and check for required fields", + parameters: s.object({ filePath: s.string }), + handler: ({ filePath }) => { + if (!existsSync(filePath)) return JSON.stringify({ error: "file not found" }); + const content = readFileSync(filePath, "utf8"); + if (!content.startsWith("---")) return JSON.stringify({ presentFields: [], missingFields: ["title", "description", "date"], status: "missing" }); + const end = content.indexOf("---", 3); + if (end === -1) return JSON.stringify({ presentFields: [], missingFields: ["title", "description", "date"], status: "missing" }); + const fm = content.slice(3, end); + const required = ["title", "description", "date"]; + const present = required.filter((f) => new RegExp(`^${f}\\s*:`, "m").test(fm)); + const missing = required.filter((f) => !present.includes(f)); + const status = missing.length === 0 ? "complete" : present.length === 0 ? "missing" : "partial"; + return JSON.stringify({ presentFields: present, missingFields: missing, status }); + }, +}); + +// Agent role: check markdown files for required YAML frontmatter fields (title, description, date). +const markdownFrontmatterChecker = agent({ + model: "typecheck", + maxTurns: 4, + addons: [repair()], + instructions: p`Check markdown files for required YAML frontmatter fields. + +Markdown files: ${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -50")} + +For each markdown file, use parseFrontmatter to detect which required fields (title, description, date) are present or missing. Return a record keyed by filename.`, + output: s.record(s.object({ + presentFields: s.array(s.string), + missingFields: s.array(s.string), + status: s.enum("complete", "partial", "missing"), + })), + tools: [parseFrontmatter], +}); + +export default markdownFrontmatterChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts new file mode 100644 index 0000000..7287628 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: create a focused validation plan for the current changes. +const planner = agent({ + model: "typecheck", + output: s.object({ + commands: s.array(s.string), + manualChecks: s.array(s.string), + rationale: s.string + }), + instructions: `Create a focused validation plan for the current changes.`, +}); +export default planner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts new file mode 100644 index 0000000..4d547ee --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts @@ -0,0 +1,36 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const scoreFile = defineTool("scoreFile", { + description: "Compute a churn score from commit count for a file.", + parameters: s.object({ filename: s.string, commitCount: s.int }), + handler({ commitCount }) { + const score = Math.log1p(commitCount) * 10; + return { churnScore: Math.round(score * 100) / 100 }; + }, +}); + +// Agent role: Analyze git history to identify hot-spot files by churn frequency. +const gitHotspotAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze the git log to find frequently-changed files. + +Use the git history: +${p.bash("git log --name-only --format= | sort | uniq -c | sort -rn | head -30")} + +For each file in the top results, get contributor info: +${p.bash("git shortlog -sn --no-merges -- . | head -10")} + +Use the scoreFile tool to compute a churnScore for each file. +Return s.record output keyed by file path with churnScore, commitCount, and topContributors.`, + tools: [scoreFile], + addons: steering({ message: "Ensure all top files appear in the output keyed by their path." }), + output: s.record( + s.object({ + churnScore: s.number, + commitCount: s.int, + topContributors: s.array(s.string), + }), + ), +}); + +export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts new file mode 100644 index 0000000..876e587 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool } from "rig"; + +const aggregateByExtension = defineTool("aggregateByExtension", { + description: "Aggregate line counts and file counts by extension from wc -l output.", + parameters: s.object({ wcOutput: s.string }), + handler({ wcOutput }) { + const lines = wcOutput.trim().split("\n"); + const result: Record = {}; + for (const line of lines) { + const match = line.trim().match(/^(\d+)\s+(.+)$/); + if (!match) continue; + const count = parseInt(match[1], 10); + const file = match[2]; + const ext = file.includes(".") ? "." + file.split(".").pop()! : "(no-ext)"; + if (!result[ext]) result[ext] = { lineCount: 0, fileCount: 0 }; + result[ext].lineCount += count; + result[ext].fileCount += 1; + } + return result; + }, +}); + +// Agent role: Gather lines-of-code statistics grouped by file extension. +const locStatisticsGatherer = agent({ + model: "typecheck", + instructions: p`Count lines of code across the workspace grouped by file extension. + +Find source files and count lines: +${p.bash("find . -maxdepth 4 -type f \\( -name '*.ts' -o -name '*.js' -o -name '*.py' -o -name '*.go' -o -name '*.md' \\) ! -path '*/node_modules/*' ! -path '*/.git/*' | xargs wc -l 2>/dev/null | tail -n +1")} + +Use the aggregateByExtension tool to group by extension. +Classify each extension's complexity based on total lineCount: +- small: < 500, medium: 500-2000, large: 2000-10000, xlarge: > 10000 +Return s.record output keyed by extension with lineCount, fileCount, and complexity.`, + tools: [aggregateByExtension], + output: s.record( + s.object({ + lineCount: s.int, + fileCount: s.int, + complexity: s.enum("small", "medium", "large", "xlarge"), + }), + ), +}); + +export default locStatisticsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts new file mode 100644 index 0000000..88be4f8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts @@ -0,0 +1,34 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: Detect import cycles in TypeScript source using madge and classify severity. +const importCycleDetector = agent({ + model: "typecheck", + maxTurns: 3, + instructions: p`Detect circular import cycles in this TypeScript project. + +Run madge to find circular dependencies: +${p.bash("npx madge --circular --json . 2>/dev/null || echo '[]'")} + +Also read the TypeScript config: +${p.readOptional("tsconfig.json", "{}")} + +For each cycle found, classify severity: +- high: cycle involves more than 3 files or includes entry points +- medium: cycle involves 2-3 files +- low: short cycle between utility files + +Return the structured output with hasCycles, cycles array, and totalCycles count.`, + addons: repair(), + output: s.object({ + hasCycles: s.boolean, + cycles: s.array( + s.object({ + path: s.array(s.string), + severity: s.enum("high", "medium", "low"), + }), + ), + totalCycles: s.int, + }), +}); + +export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts new file mode 100644 index 0000000..ff5f447 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts @@ -0,0 +1,29 @@ +import { agent, p, s } from "rig"; + +// Agent role: Update README.md with shields.io coverage badges from coverage summary JSON. +const coverageBadgeUpdater = agent({ + model: "typecheck", + instructions: p`Read the coverage summary and generate shields.io badge markdown. + +Coverage summary: +${p.readOptional("coverage/coverage-summary.json", "{}")} + +Compute coverage percentages per category (lines, statements, functions, branches) and overall. +Generate shields.io badge markdown URL for each category. +Classify overall coverage rating: +- green: >= 80%, yellow: 50-79%, red: < 50% + +Write the badge summary markdown to README.md using the p.writeOutput intent below. +${p.writeOutput("badgeSummary", "README.md")} + +Return coverageByCategory (record of percentages), overallPct, rating, badgesWritten, and badgeSummary.`, + output: s.object({ + coverageByCategory: s.record(s.number), + overallPct: s.number, + rating: s.enum("green", "yellow", "red"), + badgesWritten: s.boolean, + badgeSummary: s.string, + }), +}); + +export default coverageBadgeUpdater; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts new file mode 100644 index 0000000..e2087b4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool } from "rig"; + +const extractLicense = defineTool("extractLicense", { + description: "Read license field from a package in node_modules.", + parameters: s.object({ packageName: s.string }), + async handler({ packageName }) { + const { readFileSync } = await import("node:fs"); + try { + const pkgPath = `node_modules/${packageName}/package.json`; + const pkg = JSON.parse(readFileSync(pkgPath, "utf8")); + const license: string = pkg.license ?? pkg.licenses?.[0]?.type ?? "UNKNOWN"; + let category: "permissive" | "copyleft" | "unknown" = "unknown"; + const upper = license.toUpperCase(); + if (["MIT", "ISC", "BSD", "APACHE", "0BSD", "WTFPL"].some((l: string) => upper.includes(l))) { + category = "permissive"; + } else if (["GPL", "LGPL", "AGPL", "MPL", "EUPL"].some((l: string) => upper.includes(l))) { + category = "copyleft"; + } + return { license, category }; + } catch { + return { license: "UNKNOWN", category: "unknown" as const }; + } + }, +}); + +// Agent role: Audit dependency licenses and flag copyleft packages. +const depLicenseAuditor = agent({ + model: "typecheck", + instructions: p`Audit dependency licenses for this project. + +List installed packages: +${p.bash("npm ls --json --depth=0 2>/dev/null | node -e \"const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));console.log(Object.keys(d.dependencies||{}).join('\\n'))\" 2>/dev/null || ls node_modules | head -50")} + +For each package, use the extractLicense tool to get its license and category. +Return packages array, hasCopyleft flag, and totalPackages count.`, + tools: [extractLicense], + output: s.object({ + packages: s.array( + s.object({ + name: s.string, + license: s.string, + category: s.enum("permissive", "copyleft", "unknown"), + }), + ), + hasCopyleft: s.boolean, + totalPackages: s.int, + }), +}); + +export default depLicenseAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts new file mode 100644 index 0000000..aac78db --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts @@ -0,0 +1,51 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const matchTestFile = defineTool("matchTestFile", { + description: "Heuristically find test files matching a source file by name.", + parameters: s.object({ sourcePath: s.string, testFiles: s.array(s.string) }), + handler({ sourcePath, testFiles }) { + const baseName = sourcePath.split("/").pop()!.replace(/\.ts$/, ""); + const patterns = [ + `${baseName}.test.ts`, + `${baseName}.spec.ts`, + `${baseName}.test.js`, + `${baseName}.spec.js`, + ]; + const matched = testFiles.filter((f: string) => + patterns.some((p: string) => f.endsWith(p)) + ); + return { matched }; + }, +}); + +// Agent role: Map source files to their test counterparts and classify coverage. +const testCoverageMapper = agent({ + model: "typecheck", + maxTurns: 2, + instructions: p`Map source files to test files using filename heuristics. + +Source files: +${p.bash("find . -type f -name '*.ts' ! -name '*.test.ts' ! -name '*.spec.ts' ! -path '*/node_modules/*' ! -path '*/.git/*' | head -40")} + +Test files: +${p.bash("find . -type f \\( -name '*.test.ts' -o -name '*.spec.ts' \\) ! -path '*/node_modules/*' | head -40")} + +For each source file, use matchTestFile to find matching test files. +Classify coverage: +- covered: at least one test file matched +- uncovered: no test files matched +- partial: test file exists but may not cover all exports (use heuristics) + +Return s.record output keyed by source file path.`, + tools: [matchTestFile], + addons: repair(), + output: s.record( + s.object({ + coverage: s.enum("covered", "uncovered", "partial"), + testFiles: s.array(s.string), + reason: s.string, + }), + ), +}); + +export default testCoverageMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts new file mode 100644 index 0000000..5c29107 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool } from "rig"; + +const parsePermissions = defineTool("parsePermissions", { + description: "Parse a unix permission string and classify risk level.", + parameters: s.object({ permissions: s.string, filename: s.string }), + handler({ permissions }) { + const isExecutable = permissions[3] === "x" || permissions[6] === "x" || permissions[9] === "x"; + const isWorldWritable = permissions[8] === "w"; + let riskLevel: "safe" | "warn" | "danger" = "safe"; + if (isWorldWritable) riskLevel = "danger"; + else if (isExecutable) riskLevel = "warn"; + return { isExecutable, isWorldWritable, riskLevel }; + }, +}); + +// Agent role: Scan workspace file permissions and flag dangerous or unusual access modes. +const filePermissionScanner = agent({ + model: "typecheck", + instructions: p`Scan file permissions in the workspace and classify risk. + +List files with permissions: +${p.bash("find . -maxdepth 3 -type f ! -path '*/node_modules/*' ! -path '*/.git/*' | head -50 | xargs ls -la 2>/dev/null")} + +For each file, use parsePermissions to determine isExecutable, isWorldWritable, and riskLevel. +Return s.object with files record (keyed by filename), dangerCount, and allSafe.`, + tools: [parsePermissions], + output: s.object({ + files: s.record( + s.object({ + mode: s.string, + isExecutable: s.boolean, + isWorldWritable: s.boolean, + riskLevel: s.enum("safe", "warn", "danger"), + }), + ), + dangerCount: s.int, + allSafe: s.boolean, + }), +}); + +export default filePermissionScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts new file mode 100644 index 0000000..ef58fb6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts @@ -0,0 +1,49 @@ +import { agent, p, s, defineTool } from "rig"; + +const parseSubmoduleStatus = defineTool("parseSubmoduleStatus", { + description: "Parse a git submodule status line into structured fields.", + parameters: s.object({ line: s.string }), + handler({ line }) { + const trimmed = line.trimStart(); + if (!trimmed) return null; + const statusChar = line[0]; + const rest = trimmed.replace(/^[\+\- U]/, "").trim(); + const parts = rest.split(/\s+/); + const sha = parts[0] ?? ""; + const path = parts[1] ?? ""; + let status: "clean" | "modified" | "uninitialized" | "missing" = "clean"; + if (statusChar === "+") status = "modified"; + else if (statusChar === "-") status = "uninitialized"; + else if (statusChar === "U") status = "missing"; + return { path, sha, status }; + }, +}); + +// Agent role: Inventory git submodules and report their health status. +const gitSubmoduleHealth = agent({ + model: "typecheck", + instructions: p`Check the health of all git submodules in this repository. + +Submodule status: +${p.bash("git submodule status 2>/dev/null || echo '(no submodules)'")} + +Submodule config: +${p.readOptional(".gitmodules", "(no .gitmodules file)")} + +For each status line, use parseSubmoduleStatus to extract path, sha, and status. +Return submodules array, allClean flag, and totalCount.`, + tools: [parseSubmoduleStatus], + output: s.object({ + submodules: s.array( + s.object({ + path: s.string, + sha: s.string, + status: s.enum("clean", "modified", "uninitialized", "missing"), + }), + ), + allClean: s.boolean, + totalCount: s.int, + }), +}); + +export default gitSubmoduleHealth; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts new file mode 100644 index 0000000..dc25285 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyDecorator = defineTool("classifyDecorator", { + description: "Classify a decorator as class, method, property, or parameter based on context.", + parameters: s.object({ name: s.string, context: s.string }), + handler({ context }) { + const trimmed = context.trim(); + if (/^@\w+\s*\n?\s*(export\s+)?(abstract\s+)?class\s+/.test(trimmed) || + /class\s+\w+/.test(trimmed)) { + return { type: "class" }; + } + if (/\(.*:/.test(trimmed) && trimmed.includes("constructor")) { + return { type: "parameter" }; + } + if (/^\s*(public|private|protected|readonly)/.test(trimmed) || + /\w+\s*[=:!]/.test(trimmed)) { + return { type: "property" }; + } + return { type: "method" }; + }, +}); + +// Agent role: Scan TypeScript files for decorator usage and classify each by decorator type. +const tsDecoratorScanner = agent({ + model: "typecheck", + instructions: p`Find and classify TypeScript decorators across the codebase. + +Scan for decorators: +${p.bash("grep -rn '@[A-Z][a-zA-Z]*' --include='*.ts' . 2>/dev/null | grep -v node_modules | grep -v '.git' | head -60")} + +For each unique decorator found, use classifyDecorator with one representative context line. +Determine if any experimental decorators are used (e.g., @Inject, @Component, @NgModule). +Return decorators record (keyed by decorator name with count and type), totalCount, and hasExperimental.`, + tools: [classifyDecorator], + output: s.object({ + decorators: s.record( + s.object({ + count: s.int, + type: s.enum("class", "method", "property", "parameter"), + }), + ), + totalCount: s.int, + hasExperimental: s.boolean, + }), +}); + +export default tsDecoratorScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts new file mode 100644 index 0000000..8dd9ad1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts @@ -0,0 +1,36 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: Discover and categorize dotfiles in the workspace root and nearby directories. +const dotfileInventory = agent({ + model: "typecheck", + instructions: p`Inventory all dotfiles in the workspace and categorize them. + +Find dotfiles: +${p.bash("find . -maxdepth 2 -name '.*' -type f ! -path '*/.git/*' 2>/dev/null")} + +Read common dotfiles for context: +${p.bash("find . -maxdepth 2 -name '.*' -type f ! -path '*/.git/*' 2>/dev/null | head -10 | xargs head -c 200 2>/dev/null")} + +For each dotfile, determine its purpose and category: +- editor: .editorconfig, .vscode/*, .nvmrc +- git: .gitignore, .gitattributes, .gitmodules +- shell: .bashrc, .zshrc, .profile, .env +- package: .npmrc, .yarnrc, .nvmrc, .node-version +- ci: .travis.yml, .circleci, .github, .eslintrc +- other: anything else + +Return dotfiles record (keyed by filename) with purpose and category, totalFound, and categorySummary (record of counts per category).`, + addons: repair(), + output: s.object({ + dotfiles: s.record( + s.object({ + purpose: s.string, + category: s.enum("editor", "git", "shell", "package", "ci", "other"), + }), + ), + totalFound: s.int, + categorySummary: s.record(s.int), + }), +}); + +export default dotfileInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts new file mode 100644 index 0000000..a50c0b9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: convert the change description to Keep a Changelog style. +const categorize = agent({ + model: "typecheck", + output: s.object({ + category: s.enum("added", "changed", "deprecated", "removed", "fixed", "security"), + entry: s.string + }), + instructions: `Convert the change description to Keep a Changelog style.`, +}); + +export default categorize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts new file mode 100644 index 0000000..8fd37de --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts @@ -0,0 +1,38 @@ +import { agent, defineTool, p, s, steering } from "rig"; + +// Agent role: identify hot-spot files by git churn and classify risk level. +const gitHotspotAnalyzerV3 = agent({ + model: "typecheck", + addons: steering({ message: "Focus on files that appear most frequently. Assign riskLevel based on churnScore: >20=critical, >10=high, >5=medium, else low." }), + instructions: p`Analyze git history to find frequently changed files and classify their risk. + +Recently changed files (with churn counts): +${p.bash("git log --name-only --format='' HEAD~50..HEAD | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} + +Top contributors overall: +${p.bash("git shortlog -sn HEAD~50..HEAD 2>/dev/null | head -10")} + +Use the countChurn tool to parse the churn output for each file. For each file, determine +the churnScore, assign topContributors from the shortlog output, and classify riskLevel. +Return a record keyed by file path with the declared output shape.`, + tools: [ + defineTool("countChurn", { + description: "Parse a line of uniq -c output to extract count and filename", + parameters: s.object({ line: s.string }), + handler({ line }) { + const m = line.trim().match(/^(\d+)\s+(.+)$/); + if (!m) return { count: 0, file: "" }; + return { count: parseInt(m[1], 10), file: m[2].trim() }; + }, + }), + ], + output: s.record( + s.object({ + churnScore: s.int, + topContributors: s.array(s.string), + riskLevel: s.enum("low", "medium", "high", "critical"), + }) + ), +}); + +export default gitHotspotAnalyzerV3; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts new file mode 100644 index 0000000..7f230b8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts @@ -0,0 +1,52 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: gather lines-of-code statistics per file extension. +const locStatisticsV2 = agent({ + model: "typecheck", + instructions: p`Count lines of code per file extension in this workspace. + +TypeScript files found: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | head -50")} + +Line counts for TypeScript files: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | head -20 | xargs wc -l 2>/dev/null | tail -1")} + +JavaScript files found: +${p.bash("find . -name '*.js' -not -path '*/node_modules/*' | head -20")} + +Use the aggregateExtension tool to compute totals. Then classify complexity for each +extension: xlarge > 10000 lines, large > 5000, medium > 1000, small otherwise. +Return a record keyed by extension (e.g. ".ts", ".js") with lineCount, fileCount, +and complexity.`, + tools: [ + defineTool("aggregateExtension", { + description: "Count lines in files matching a given extension", + parameters: s.object({ extension: s.string, sampleFile: s.string }), + async handler({ extension, sampleFile }) { + const { execSync } = await import("node:child_process"); + try { + const count = execSync( + `find . -name '*${extension}' -not -path '*/node_modules/*' | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}'`, + { encoding: "utf-8" } + ).trim(); + const files = execSync( + `find . -name '*${extension}' -not -path '*/node_modules/*' | wc -l`, + { encoding: "utf-8" } + ).trim(); + return { extension, lineCount: parseInt(count) || 0, fileCount: parseInt(files) || 0, sampleFile }; + } catch { + return { extension, lineCount: 0, fileCount: 0, sampleFile }; + } + }, + }), + ], + output: s.record( + s.object({ + lineCount: s.int, + fileCount: s.int, + complexity: s.enum("small", "medium", "large", "xlarge"), + }) + ), +}); + +export default locStatisticsV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts new file mode 100644 index 0000000..a3d6e92 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts @@ -0,0 +1,34 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: detect circular import cycles in TypeScript source and classify severity. +const importCycleDetectorV3 = agent({ + model: "typecheck", + maxTurns: 3, + addons: repair(), + instructions: p`Detect circular import cycles in this TypeScript project. + +Circular dependency analysis: +${p.bash("npx madge --circular --extensions ts src 2>/dev/null || echo 'No cycles found or madge not available'")} + +TypeScript configuration: +${p.readOptional("tsconfig.json", "{}")} + +Analyze the output above. Each cycle is a group of files that import each other in a +circle. Classify severity: high if the cycle involves more than 3 files or core modules, +medium for 2-3 files, low for simple two-file cycles. + +Return hasCycles (true if any cycles found), the cycles array with path (array of file +strings in the cycle) and severity, and totalCycles count.`, + output: s.object({ + hasCycles: s.boolean, + cycles: s.array( + s.object({ + path: s.array(s.string), + severity: s.enum("high", "medium", "low"), + }) + ), + totalCycles: s.int, + }), +}); + +export default importCycleDetectorV3; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts new file mode 100644 index 0000000..a65f803 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts @@ -0,0 +1,35 @@ +import { agent, p, s } from "rig"; + +// Agent role: read coverage summary and update README with shields.io badge links. +const coverageBadgeUpdaterV2 = agent({ + model: "typecheck", + instructions: p`Read coverage data and update the README with shields.io coverage badges. + +Coverage summary (JSON): +${p.readOptional("coverage/coverage-summary.json", "{}")} + +Current README: +${p.readOptional("README.md", "# Project\n")} + +Compute the coverage percentage for each category (statements, branches, functions, lines) +from the total section. Compute overallPct as the average. Classify rating: green >= 80%, +yellow >= 60%, red < 60%. + +Generate shields.io badge markdown for each category using URL format: +https://img.shields.io/badge/coverage-XX%25-green + +Write the updated README with badges added at the top using p.write. + +${p.write("README.md", "")} + +Return coverageByCategory (record of category to percentage), overallPct, rating, and +badgesWritten (true if README was updated).`, + output: s.object({ + coverageByCategory: s.record(s.number), + overallPct: s.number, + rating: s.enum("green", "yellow", "red"), + badgesWritten: s.boolean, + }), +}); + +export default coverageBadgeUpdaterV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts new file mode 100644 index 0000000..31f71d6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts @@ -0,0 +1,37 @@ +import { agent, p, s } from "rig"; + +// Agent role: audit npm dependency licenses and flag copyleft packages. +const depLicenseAuditorV2 = agent({ + model: "typecheck", + instructions: p`Audit the licenses of npm dependencies and classify each one. + +Installed dependencies (JSON tree): +${p.bash("npm ls --json --depth=0 2>/dev/null || echo '{}'")} + +Package dependency names: +${p.bash("node -e \"try{const p=require('./package.json');console.log(JSON.stringify(Object.keys(p.dependencies||{})))}catch(e){console.log('[]')}\"")} + +Package license fields from node_modules: +${p.bash("node -e \"const fs=require('fs');const d='./node_modules';if(fs.existsSync(d)){const pkgs=fs.readdirSync(d).filter(x=>!x.startsWith('.'));pkgs.slice(0,30).forEach(p=>{try{const m=JSON.parse(fs.readFileSync(d+'/'+p+'/package.json','utf8'));console.log(p+':'+m.license)}catch(e){}});}\" 2>/dev/null || echo 'unavailable'")} + +For each dependency, determine its license. Classify as: +- permissive: MIT, ISC, BSD, Apache, CC0, Unlicense, 0BSD +- copyleft: GPL, LGPL, AGPL, MPL, EUPL, CC-BY-SA +- unknown: anything else or unspecified + +Return the packages array with name, license, and classification, hasCopyleft (true if any +copyleft found), and totalCount.`, + output: s.object({ + packages: s.array( + s.object({ + name: s.string, + license: s.string, + classification: s.enum("permissive", "copyleft", "unknown"), + }) + ), + hasCopyleft: s.boolean, + totalCount: s.int, + }), +}); + +export default depLicenseAuditorV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts new file mode 100644 index 0000000..7d65660 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts @@ -0,0 +1,51 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +// Agent role: map source files to their test files using filename heuristics. +const testCoverageMapperV2 = agent({ + model: "typecheck", + maxTurns: 2, + addons: repair(), + instructions: p`Map TypeScript source files to their corresponding test files. + +Source files (non-test TypeScript): +${p.bash("find . -name '*.ts' -not -name '*.test.ts' -not -name '*.spec.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -30")} + +Test files: +${p.bash("find . -name '*.test.ts' -o -name '*.spec.ts' | grep -v node_modules | head -30")} + +Use the matchTestFile tool for each source file to find its corresponding test file using +filename heuristics (e.g., src/foo.ts -> src/foo.test.ts or tests/foo.test.ts). + +Return a record keyed by source file path with coverage ("covered" if test found, +"uncovered" if none, "partial" if indirect match), testFiles (array of matched test paths), +and reason explaining the determination.`, + tools: [ + defineTool("matchTestFile", { + description: "Find test files that match a source file using naming heuristics", + parameters: s.object({ sourceFile: s.string, testFiles: s.array(s.string) }), + handler({ sourceFile, testFiles }) { + const base = sourceFile.replace(/\.tsx?$/, "").replace(/^.*\//, ""); + const direct = testFiles.filter((t) => + t.includes(`${base}.test`) || t.includes(`${base}.spec`) + ); + const partial = direct.length === 0 + ? testFiles.filter((t) => t.toLowerCase().includes(base.toLowerCase())) + : []; + return { + matched: direct, + partial, + coverage: direct.length > 0 ? "covered" : partial.length > 0 ? "partial" : "uncovered", + }; + }, + }), + ], + output: s.record( + s.object({ + coverage: s.enum("covered", "uncovered", "partial"), + testFiles: s.array(s.string), + reason: s.string, + }) + ), +}); + +export default testCoverageMapperV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts new file mode 100644 index 0000000..595ebe6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts @@ -0,0 +1,59 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +// Agent role: run regex patterns against test cases and report pass/fail results. +const regexPatternTester = agent({ + model: "typecheck", + addons: repair(), + input: s.object({ + patterns: s.array( + s.object({ + name: s.string, + regex: s.string, + testCases: s.array( + s.object({ + input: s.string, + expected: s.boolean, + }) + ), + }) + ), + }), + instructions: p`Run each regex pattern against its test cases and report results. + +Input patterns and test cases: +${p.json("input")} + +Use the runRegexTest tool for each (pattern, input) pair. Then build the results array +with patternName, input, expected, actual (from tool), and passed (expected === actual). +Count passCount and failCount. Set allPassed to true only if failCount is 0.`, + tools: [ + defineTool("runRegexTest", { + description: "Test a regex pattern against an input string", + parameters: s.object({ pattern: s.string, input: s.string }), + handler({ pattern, input }) { + try { + const matched = new RegExp(pattern).test(input); + return { matched }; + } catch { + return { matched: false }; + } + }, + }), + ], + output: s.object({ + results: s.array( + s.object({ + patternName: s.string, + input: s.string, + expected: s.boolean, + actual: s.boolean, + passed: s.boolean, + }) + ), + passCount: s.int, + failCount: s.int, + allPassed: s.boolean, + }), +}); + +export default regexPatternTester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts new file mode 100644 index 0000000..aca03e5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts @@ -0,0 +1,27 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: classify files by commit churn frequency and assign a risk level. +const commitChurnClassifier = agent({ + model: "typecheck", + addons: steering({ message: "Be precise: assign riskLevel based on churnCount: >20=critical, >10=volatile, >5=active, else stable." }), + instructions: p`Classify repository files by how frequently they are committed (churn). + +File churn counts from last 100 commits (count file): +${p.bash("git log --name-only --format='' HEAD~100..HEAD 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} + +For each file in the output above, parse the churn count and assign a riskLevel: +- critical: churnCount > 20 +- volatile: churnCount > 10 +- active: churnCount > 5 +- stable: churnCount <= 5 + +Return a record keyed by file path with churnCount (integer) and riskLevel.`, + output: s.record( + s.object({ + churnCount: s.int, + riskLevel: s.enum("stable", "active", "volatile", "critical"), + }) + ), +}); + +export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts new file mode 100644 index 0000000..1540dea --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts @@ -0,0 +1,44 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: estimate npm package publish size and rate it with a recommendation. +const npmPackageSize = agent({ + model: "typecheck", + instructions: p`Estimate the npm package publish size and provide a recommendation. + +Files that would be included in npm publish (dry run): +${p.bash("npm pack --dry-run 2>&1 | head -40")} + +Overall workspace size: +${p.bash("du -sh . 2>/dev/null | cut -f1")} + +Package metadata: +${p.readOptional("package.json", "{}")} + +Parse the npm pack output to extract file sizes. Use the classifySize tool to rate the +total estimated size. Provide a recommendation based on the rating (e.g., suggest adding +files to .npmignore if large/xlarge). + +Return estimatedSizeKb (total in KB), topFiles (up to 5 largest files with file and +sizeKb), sizeRating, and a recommendation string.`, + tools: [ + defineTool("classifySize", { + description: "Classify a package size in KB into a rating tier", + parameters: s.object({ sizeKb: s.number }), + handler({ sizeKb }) { + if (sizeKb < 10) return { rating: "tiny" }; + if (sizeKb < 50) return { rating: "small" }; + if (sizeKb < 200) return { rating: "medium" }; + if (sizeKb < 1000) return { rating: "large" }; + return { rating: "xlarge" }; + }, + }), + ], + output: s.object({ + estimatedSizeKb: s.number, + topFiles: s.array(s.object({ file: s.string, sizeKb: s.number })), + sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), + recommendation: s.string, + }), +}); + +export default npmPackageSize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts new file mode 100644 index 0000000..d041006 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts @@ -0,0 +1,58 @@ +import { agent, p, s } from "rig"; + +// Agent role: identify branch statements in a TypeScript file and estimate coverage. +const branchAnalyzer = agent({ + name: "branchAnalyzer", + model: "typecheck", + input: s.string, + instructions: p`Analyze the TypeScript source code provided and identify all branch points. + +For each branch (if statements, ternaries, switch cases, nullish coalescing), determine: +- functionName: the enclosing function name (or "module" if top-level) +- line: approximate line number +- branchType: "if", "ternary", "switch", or "nullish" +- covered: false (assume uncovered unless the code contains obvious test guards) + +Return only the declared output array.`, + output: s.array( + s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "nullish"), + covered: s.boolean, + }) + ), +}); + +// Agent role: coordinate branch coverage analysis by delegating to branchAnalyzer subagent. +const tsBranchCoverage = agent({ + model: "typecheck", + input: s.object({ filePath: s.path }), + instructions: p`Analyze TypeScript branch coverage for the file at the provided path. + +File content: +${p.readInput("filePath")} + +Delegate the analysis to the branchAnalyzer subagent. Then aggregate results into: +- branches: the full array returned by branchAnalyzer +- summary: totalBranches (length of array), coveredBranches (count where covered=true), + uncoveredBranches (count where covered=false)`, + agents: { branchAnalyzer }, + output: s.object({ + branches: s.array( + s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "nullish"), + covered: s.boolean, + }) + ), + summary: s.object({ + totalBranches: s.int, + coveredBranches: s.int, + uncoveredBranches: s.int, + }), + }), +}); + +export default tsBranchCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts new file mode 100644 index 0000000..ebdc9c9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: compare public API declarations and identify breaking changes. +const apiDiff = agent({ + model: "typecheck", + output: s.object({ + breaking: s.boolean, + summary: s.string, + changes: s.array(s.string) + }), + instructions: `Compare public API declarations and identify breaking changes.`, +}); +export default apiDiff; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts new file mode 100644 index 0000000..1d42806 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts @@ -0,0 +1,44 @@ +import { agent, defineTool, p, repair, s } from "rig"; + +// Agent role: detect dead TypeScript exports by scanning for exported symbols and estimating usage counts. +const deadCodeDetector = agent({ + model: "typecheck", + instructions: p`Detect dead code in this TypeScript project. + +Files in project: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -40")} + +Exported symbols found: +${p.bash("grep -rn '^export ' --include='*.ts' . 2>/dev/null | grep -v node_modules | head -60")} + +Use the estimateUsage tool for each exported symbol name to count how many times it appears across the codebase. Classify each as: "used" (>1 reference), "possibly-dead" (exactly 1, the declaration itself), or "dead" (0 references outside declaration). Return only the declared output.`, + tools: [ + defineTool("estimateUsage", { + description: "Count non-declaration usages of an exported symbol across the codebase", + parameters: s.object({ symbol: s.string }), + async handler({ symbol }) { + const { execSync } = await import("node:child_process"); + try { + const out = execSync( + `grep -rn "\\b${symbol}\\b" --include="*.ts" . 2>/dev/null | grep -v "^export " | grep -v node_modules | wc -l`, + { encoding: "utf-8" } + ); + return { symbol, usageCount: parseInt(out.trim(), 10) }; + } catch { + return { symbol, usageCount: 0 }; + } + }, + }), + ], + addons: [repair()], + output: s.object({ + symbols: s.record(s.object({ + usageCount: s.int, + status: s.enum("used", "possibly-dead", "dead"), + })), + totalExported: s.int, + deadCount: s.int, + }), +}); + +export default deadCodeDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts new file mode 100644 index 0000000..4165b0c --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts @@ -0,0 +1,48 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: validate an OpenAPI spec file for structural correctness and report issues. +const openapiSpecValidator = agent({ + model: "typecheck", + instructions: p`Validate the OpenAPI specification in this workspace. + +openapi.json content: +${p.readOptional("openapi.json")} + +openapi.yaml content: +${p.readOptional("openapi.yaml")} + +Use the checkStructure tool to validate the spec content. Check for: required fields (openapi version, info.title, info.version, paths), valid HTTP methods, proper response codes, and schema references. Return only the declared output.`, + tools: [ + defineTool("checkStructure", { + description: "Check structural validity of OpenAPI spec content", + parameters: s.object({ content: s.string }), + handler({ content }) { + const issues: Array<{ type: "error" | "warning" | "info"; message: string; path?: string }> = []; + try { + const spec = JSON.parse(content); + if (!spec.openapi) issues.push({ type: "error", message: "Missing required field 'openapi'", path: "openapi" }); + if (!spec.info) issues.push({ type: "error", message: "Missing required field 'info'", path: "info" }); + else { + if (!spec.info.title) issues.push({ type: "error", message: "Missing info.title", path: "info.title" }); + if (!spec.info.version) issues.push({ type: "error", message: "Missing info.version", path: "info.version" }); + } + if (!spec.paths) issues.push({ type: "error", message: "Missing required field 'paths'", path: "paths" }); + } catch { + issues.push({ type: "warning", message: "Content is not valid JSON — may be YAML or empty" }); + } + return { issues }; + }, + }), + ], + output: s.object({ + valid: s.boolean, + issues: s.array(s.object({ + type: s.enum("error", "warning", "info"), + message: s.string, + path: s.optional(s.string), + })), + issueCount: s.int, + }), +}); + +export default openapiSpecValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts new file mode 100644 index 0000000..5a66a8f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts @@ -0,0 +1,36 @@ +import { agent, p, s } from "rig"; + +// Agent role: classify purpose of each API endpoint found in route files. +const endpointClassifier = agent({ + name: "endpointClassifier", + model: "typecheck", + input: s.object({ route: s.string }), + instructions: p`Classify this API route: return purpose and description.`, + output: s.object({ + purpose: s.enum("read", "write", "delete", "auth", "health", "other"), + description: s.string, + }), +}); + +// Agent role: extract API endpoints from route/controller files and classify each by purpose. +const apiEndpointExtractor = agent({ + model: "typecheck", + agents: { endpointClassifier }, + instructions: p`Extract and classify all API endpoints in this workspace. + +Route patterns found: +${p.bash("grep -rn '\\.(get|post|put|delete|patch)(' --include='*.ts' --include='*.js' . 2>/dev/null | grep -v node_modules | head -40")} + +For each unique route pattern found, delegate to the endpointClassifier subagent to determine its purpose. Return all discovered endpoints with method, path, and purpose. Return only the declared output.`, + output: s.object({ + endpoints: s.array(s.object({ + method: s.enum("GET", "POST", "PUT", "DELETE", "PATCH"), + path: s.string, + purpose: s.enum("read", "write", "delete", "auth", "health", "other"), + })), + totalCount: s.int, + hasCrud: s.boolean, + }), +}); + +export default apiEndpointExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts new file mode 100644 index 0000000..d3f755b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts @@ -0,0 +1,37 @@ +import { agent, p, s } from "rig"; + +// Agent role: generate JSDoc annotations for TypeScript source files and write annotated output. +const jsDocAnnotator = agent({ + name: "jsDocAnnotator", + model: "typecheck", + input: s.object({ filePath: s.path, content: s.string }), + instructions: p`Add JSDoc comments to every exported function, class, and interface in the TypeScript source. Return only the declared output.`, + output: s.object({ + annotatedContent: s.string, + annotationsAdded: s.int, + }), +}); + +// Agent role: annotate TypeScript source files with JSDoc comments using a subagent and write results. +const sourceFileAnnotator = agent({ + model: "typecheck", + agents: { jsDocAnnotator }, + instructions: p`Annotate TypeScript source files with JSDoc comments. + +TypeScript files in workspace: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.test.ts' -not -name '*.d.ts' | head -20")} + +For each file, read its content, delegate to the jsDocAnnotator subagent, then write the annotated version back using p.write. Track which files were processed successfully and which were skipped. + +${p.write("annotated-summary.md", "# Annotation Summary\n")} + +Return only the declared output.`, + output: s.object({ + filesProcessed: s.int, + filesSkipped: s.int, + totalAnnotations: s.int, + processedPaths: s.array(s.path), + }), +}); + +export default sourceFileAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts new file mode 100644 index 0000000..b39346d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts @@ -0,0 +1,42 @@ +import { agent, defineTool, p, repair, s } from "rig"; + +// Agent role: detect stale npm dependencies by comparing installed versions with latest published versions. +const staleDependencyDetector = agent({ + model: "typecheck", + instructions: p`Identify stale npm dependencies that need updating. + +package.json contents: +${p.read("package.json")} + +npm outdated results: +${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} + +Use the classifyDrift tool for each outdated package to classify the version drift level. Determine the overall risk for the project. Return only the declared output.`, + tools: [ + defineTool("classifyDrift", { + description: "Classify version drift between current and latest version", + parameters: s.object({ current: s.string, latest: s.string }), + handler({ current, latest }) { + const parse = (v: string) => v.replace(/^[^0-9]*/, "").split(".").map(Number); + const [cMaj, cMin] = parse(current); + const [lMaj, lMin] = parse(latest); + if (lMaj > cMaj) return { driftLevel: "major" as const }; + if (lMin > cMin) return { driftLevel: "minor" as const }; + return { driftLevel: "patch" as const }; + }, + }), + ], + addons: [repair()], + output: s.object({ + packages: s.array(s.object({ + name: s.string, + current: s.string, + latest: s.string, + driftLevel: s.enum("major", "minor", "patch", "ok"), + })), + overallRisk: s.enum("safe", "moderate", "critical"), + staleCount: s.int, + }), +}); + +export default staleDependencyDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts new file mode 100644 index 0000000..ac4577f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts @@ -0,0 +1,46 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize commits and authors between two git tags. +const timelineSummarizer = agent({ + name: "timelineSummarizer", + model: "typecheck", + input: s.object({ + tag: s.string, + prevTag: s.string, + commits: s.string, + }), + instructions: p`Summarize the git log between two tags and return structured timeline entry.`, + output: s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + }), +}); + +// Agent role: build a release timeline from git tags showing commit counts and top authors per tag. +const gitTagTimeline = agent({ + model: "typecheck", + agents: { timelineSummarizer }, + instructions: p`Build a git tag release timeline. + +Git tags (sorted by date): +${p.bash("git tag --sort=version:refname 2>/dev/null | tail -20 || echo 'No tags found'")} + +Recent commit log: +${p.bash("git log --oneline --format='%h %an %ad %s' --date=short -40 2>/dev/null || echo 'No commits'")} + +For each tag pair, delegate to the timelineSummarizer subagent with the relevant commit log section. Also check for unreleased commits after the latest tag. Return only the declared output.`, + output: s.object({ + timeline: s.array(s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + })), + hasUnreleasedCommits: s.boolean, + totalTags: s.int, + }), +}); + +export default gitTagTimeline; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts new file mode 100644 index 0000000..beeed21 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s } from "rig"; + +// Agent role: infer the type and purpose of each variable defined in a .env.example file. +const envVariableTypeInferrer = agent({ + model: "typecheck", + instructions: p`Infer the type and purpose of each environment variable in the project. + +.env.example contents: +${p.readOptional(".env.example")} + +.env.sample contents: +${p.readOptional(".env.sample")} + +For each KEY=value pair found, use the inferType tool to classify the value type. Produce a description of each variable's likely purpose based on its name. Determine whether all variables appear to be documented (have a non-empty value or comment). Return only the declared output.`, + tools: [ + defineTool("inferType", { + description: "Infer the type of an environment variable value", + parameters: s.object({ key: s.string, value: s.string }), + handler({ value }) { + const v = value.trim(); + if (/^https?:\/\//i.test(v)) return { type: "url" as const }; + if (/^\/|^\.\.?\//.test(v)) return { type: "path" as const }; + if (/^(true|false)$/i.test(v)) return { type: "boolean" as const }; + if (/^\d+(\.\d+)?$/.test(v)) return { type: "number" as const }; + if (v === "") return { type: "unknown" as const }; + return { type: "string" as const }; + }, + }), + ], + output: s.object({ + variables: s.record(s.object({ + type: s.enum("string", "number", "boolean", "url", "path", "unknown"), + description: s.string, + })), + totalCount: s.int, + allDocumented: s.boolean, + }), +}); + +export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts new file mode 100644 index 0000000..76b0664 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts @@ -0,0 +1,43 @@ +import { agent, defineTool, p, repair, s } from "rig"; + +// Agent role: extract and classify Makefile targets into phony vs real file targets with descriptions. +const makefileTargetExtractor = agent({ + model: "typecheck", + instructions: p`Extract and classify all targets from the Makefile in this workspace. + +Makefile contents: +${p.readOptional("Makefile")} + +Use the parseTargets tool to extract target names, then classify each. Phony targets are declared with .PHONY or have no corresponding file. Check if each target has an adjacent comment (##) for help text. Return only the declared output.`, + tools: [ + defineTool("parseTargets", { + description: "Parse Makefile content and extract target names with their type", + parameters: s.object({ content: s.string }), + handler({ content }) { + const phonyTargets = new Set(); + const phonyMatch = content.match(/^\.PHONY\s*:(.*)/gm) || []; + for (const line of phonyMatch) { + line.replace(/^\.PHONY\s*:/, "").trim().split(/\s+/).forEach((t: string) => phonyTargets.add(t)); + } + const targetLines = content.match(/^([a-zA-Z0-9_-]+)\s*:/gm) || []; + const targets = targetLines + .map((l: string) => l.replace(/:.*/, "").trim()) + .filter((t: string) => t && t !== ".PHONY"); + return { targets, phonyTargets: [...phonyTargets] }; + }, + }), + ], + addons: [repair()], + output: s.object({ + targets: s.array(s.object({ + name: s.string, + isPhony: s.boolean, + hasHelp: s.boolean, + description: s.optional(s.string), + })), + totalCount: s.int, + phonyCount: s.int, + }), +}); + +export default makefileTargetExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts new file mode 100644 index 0000000..3701159 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts @@ -0,0 +1,41 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze a TypeScript function's signature and generate a test fixture file. +const signatureAnalyzer = agent({ + name: "signatureAnalyzer", + model: "typecheck", + input: s.object({ content: s.string, functionName: s.string }), + instructions: p`Analyze the TypeScript source and identify the signature for the requested function. Return parameter types, return type, and any needed imports.`, + output: s.object({ + params: s.array(s.object({ name: s.string, type: s.string })), + returnType: s.string, + requiredImports: s.array(s.string), + }), +}); + +// Agent role: generate a test fixture file for a specific TypeScript function. +const testFixtureGenerator = agent({ + model: "typecheck", + agents: { signatureAnalyzer }, + input: s.object({ + sourceFile: s.path, + functionName: s.string, + }), + instructions: p`Generate a test fixture file for a TypeScript function. + +Source file contents: +${p.readInput("sourceFile")} + +Delegate to the signatureAnalyzer subagent to extract the function signature for the requested functionName. Then generate complete test fixture code including sample inputs, expected outputs, and a describe/it test scaffold. Write the fixture file. + +${p.writeOutput("suggestedFileName", "fixture-output.ts")} + +Return only the declared output.`, + output: s.object({ + fixtureCode: s.string, + imports: s.array(s.string), + suggestedFileName: s.path, + }), +}); + +export default testFixtureGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts new file mode 100644 index 0000000..d5dfc08 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts @@ -0,0 +1,41 @@ +import { agent, defineTool, p, s, steering } from "rig"; + +// Agent role: parse server uptime logs to extract start/stop/crash events and compute uptime statistics. +const serverUptimeLogParser = agent({ + model: "typecheck", + instructions: p`Parse server uptime events from system logs. + +System journal / log output: +${p.bash("journalctl -u '*' --no-pager -n 100 2>/dev/null || cat /var/log/syslog 2>/dev/null | tail -100 || echo 'No system logs available'")} + +Use the parseLogLine tool to classify each log entry as a start, stop, crash, or restart event. For each event, extract the timestamp and compute duration from the previous stop/start. Flag anomalies (multiple crashes in quick succession) for steering. Return only the declared output.`, + tools: [ + defineTool("parseLogLine", { + description: "Classify a log line as a server lifecycle event", + parameters: s.object({ line: s.string }), + handler({ line }) { + const lower = line.toLowerCase(); + if (/start(?:ed|ing)|boot(?:ed|ing)|up\b/.test(lower)) return { event: "start" as const }; + if (/crash(?:ed)?|segfault|oom|killed/.test(lower)) return { event: "crash" as const }; + if (/restart(?:ed|ing)/.test(lower)) return { event: "restart" as const }; + if (/stop(?:ped|ping)|shut(?:down)?|halt(?:ed)?/.test(lower)) return { event: "stop" as const }; + return { event: null }; + }, + }), + ], + addons: [ + steering({ message: "If you detect multiple crashes within an hour, flag this as a crash loop anomaly in the output." }), + ], + output: s.object({ + uptimeEvents: s.array(s.object({ + event: s.enum("start", "stop", "crash", "restart"), + timestamp: s.string, + durationSeconds: s.optional(s.number), + })), + crashCount: s.int, + totalUptimeHours: s.number, + hasCrashLoop: s.boolean, + }), +}); + +export default serverUptimeLogParser; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts new file mode 100644 index 0000000..80aac26 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: find documentation gaps against the source API. +const docsGap = agent({ + model: "typecheck", + output: s.object({ + missing: s.array(s.string), + stale: s.array(s.string), + quickFixes: s.array(s.string) + }), + instructions: `Find documentation gaps against the source API.`, +}); +export default docsGap; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts new file mode 100644 index 0000000..1cfe623 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts @@ -0,0 +1,36 @@ +import { agent, p, s, repair } from "rig"; +import { defineTool } from "rig"; + +const classifyDrift = defineTool("classifyDrift", { + description: "Classify version drift between current and latest semver strings", + parameters: s.object({ current: s.string, latest: s.string }), + handler({ current, latest }) { + const parse = (v: string) => v.replace(/^[^0-9]*/, "").split(".").map(Number); + const [cMaj, cMin] = parse(current); + const [lMaj, lMin] = parse(latest); + if (lMaj > cMaj) return "major"; + if (lMin > cMin) return "minor"; + if (latest !== current) return "patch"; + return "ok"; + }, +}); + +// Agent role: detect stale npm dependencies and classify version drift. +const staleDependencyDetector = agent({ + model: "typecheck", + maxTurns: 3, + addons: repair(), + tools: [classifyDrift], + instructions: p`Analyze outdated npm packages using ${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} and the manifest ${p.read("package.json")}. For each outdated package, use the classifyDrift tool to determine drift level. Compute overallRisk: "critical" if any major drift, "moderate" if any minor drift, else "safe".`, + output: s.object({ + packages: s.array(s.object({ + name: s.string, + current: s.string, + latest: s.string, + driftLevel: s.enum("major", "minor", "patch", "ok"), + })), + overallRisk: s.enum("safe", "moderate", "critical"), + }), +}); + +export default staleDependencyDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts new file mode 100644 index 0000000..c3f3024 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts @@ -0,0 +1,36 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize a release timeline from git tag/commit data (nano). +const timelineSummarizer = agent({ + name: "timelineSummarizer", + model: "typecheck", + instructions: p`Given raw git tag data in the input, produce a structured timeline. For each tag entry extract tag name, date, commit count, and top authors.`, + input: s.object({ rawData: s.string }), + output: s.object({ + timeline: s.array(s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + })), + hasUnreleasedCommits: s.boolean, + }), +}); + +// Agent role: gather git tag and commit metadata then delegate timeline summarization. +const gitTagTimeline = agent({ + model: "typecheck", + agents: { timelineSummarizer }, + instructions: p`List tags with ${p.bash("git tag --sort=-version:refname 2>/dev/null || true")} and recent commits with ${p.bash("git log --oneline -30 --format='%H %ad %an %s' --date=short 2>/dev/null || true")}. Also check for unreleased commits with ${p.bash("git log $(git describe --tags --abbrev=0 2>/dev/null || echo '')..HEAD --oneline 2>/dev/null || true")}. Pass all raw data to the timelineSummarizer subagent and return its output directly.`, + output: s.object({ + timeline: s.array(s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + })), + hasUnreleasedCommits: s.boolean, + }), +}); + +export default gitTagTimeline; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts new file mode 100644 index 0000000..cf7115e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts @@ -0,0 +1,19 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: probe service health endpoints and classify status for each URL. +const serviceHealthProbe = agent({ + model: "typecheck", + addons: steering({ message: "For unexpected or missing HTTP codes, classify status as 'unknown' rather than failing." }), + instructions: p`Probe the comma-separated URLs in ${p.env("HEALTH_CHECK_URLS", "https://example.com,https://example.org")}. Use ${p.bash("echo 'probe each URL with: curl -o /dev/null -s -w \\'%{http_code}\\' --max-time 5'")} as a reference. For each URL, probe it and classify its status: "up" (2xx), "down" (4xx/5xx/connection refused), "slow" (timeout), "unknown" (other). Compute healthyCount and overallStatus.`, + output: s.object({ + endpoints: s.array(s.object({ + url: s.url, + status: s.enum("up", "down", "slow", "unknown"), + httpCode: s.int, + })), + healthyCount: s.int, + overallStatus: s.enum("all-healthy", "degraded", "critical"), + }), +}); + +export default serviceHealthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts new file mode 100644 index 0000000..ecd80fc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts @@ -0,0 +1,31 @@ +import { agent, p, s } from "rig"; +import { defineTool } from "rig"; + +const parseGitLog = defineTool("parseGitLog", { + description: "Parse a git log line in format 'HASH|AUTHOR|DATE|SUBJECT' into fields", + parameters: s.object({ logLine: s.string }), + handler({ logLine }) { + const parts = logLine.split("|"); + return { + commit: parts[0]?.trim() ?? "", + author: parts[1]?.trim() ?? "", + date: parts[2]?.trim() ?? "", + message: parts[3]?.trim() ?? "", + }; + }, +}); + +// Agent role: render a git-metadata template by filling placeholders from git log output. +const gitTemplateRenderer = agent({ + model: "typecheck", + tools: [parseGitLog], + input: s.string, + instructions: p`Read the template string from input. Gather git metadata: ${p.bash("git log -1 --format='%H|%an|%ad|%s' --date=short 2>/dev/null || echo '|||(no commits)'")} and branch: ${p.bash("git branch --show-current 2>/dev/null || echo 'main'")}. Use the parseGitLog tool to extract fields. Replace {{commit}}, {{author}}, {{branch}}, {{date}}, {{message}} placeholders in the template. Write rendered output via ${p.write("rendered-output.txt", "{{rendered}}")}. Return the rendered text and which placeholders were replaced.`, + output: s.object({ + rendered: s.string, + placeholdersReplaced: s.array(s.string), + outputFile: s.path, + }), +}); + +export default gitTemplateRenderer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts new file mode 100644 index 0000000..20592e2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts @@ -0,0 +1,29 @@ +import { agent, defineTool, p, s } from "rig"; + +const validateSemverBump = defineTool("validateSemverBump", { + description: "Validate that a semver bump type string is one of major/minor/patch", + parameters: s.object({ bumpType: s.string }), + handler({ bumpType }) { + const valid = /^(major|minor|patch)$/.test(bumpType); + return { valid, normalized: valid ? bumpType : "patch" }; + }, +}); + +// Agent role: generate a changelog entry from recent git changes and write it to CHANGELOG.md. +const changelogEntryGen = agent({ + model: "typecheck", + tools: [validateSemverBump], + instructions: p`Analyze recent changes: ${p.bash("git diff HEAD~1 HEAD --stat 2>/dev/null || true")} and ${p.bash("git log HEAD~1..HEAD --oneline 2>/dev/null || true")}. Determine the appropriate semver bump type and validate it with the validateSemverBump tool. Categorize commits into breaking changes, features, and fixes. Propose a next version and write a changelog entry to ${p.write("CHANGELOG.md", "## Unreleased\n")}. Return structured output.`, + output: s.object({ + version: s.string, + bumpType: s.enum("major", "minor", "patch"), + changes: s.object({ + breaking: s.array(s.string), + features: s.array(s.string), + fixes: s.array(s.string), + }), + written: s.boolean, + }), +}); + +export default changelogEntryGen; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts new file mode 100644 index 0000000..5b2acfa --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts @@ -0,0 +1,19 @@ +import { agent, p, s } from "rig"; + +// Agent role: scan source files for TODO/FIXME/HACK comments and write a markdown report. +const todoCommentTracker = agent({ + model: "typecheck", + instructions: p`Scan source files: ${p.bash("grep -rn 'TODO\\|FIXME\\|HACK' --include='*.ts' --include='*.js' --include='*.tsx' . 2>/dev/null || true")}. Parse each matching line to extract file path, line number, comment type (TODO/FIXME/HACK), and comment text. Write a grouped markdown report via ${p.write("todo-report.md", "# TODO Report\n")}. Return all found comments and the total count.`, + output: s.object({ + comments: s.array(s.object({ + file: s.path, + line: s.int, + type: s.enum("TODO", "FIXME", "HACK"), + text: s.string, + })), + totalCount: s.int, + reportWritten: s.boolean, + }), +}); + +export default todoCommentTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts new file mode 100644 index 0000000..2441183 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts @@ -0,0 +1,28 @@ +import { agent, defineTool, p, s } from "rig"; + +const parseCssVar = defineTool("parseCssVar", { + description: "Parse a CSS custom property declaration line and extract name and value", + parameters: s.object({ line: s.string }), + handler({ line }) { + const match = line.match(/(--[\w-]+)\s*:\s*(.+?)\s*;?$/); + if (!match) return null; + return { name: match[1], value: match[2].trim() }; + }, +}); + +// Agent role: extract CSS custom properties and identify unused variables. +const cssVariableExtractor = agent({ + model: "typecheck", + tools: [parseCssVar], + instructions: p`Find CSS/SCSS files: ${p.bash("find . -name '*.css' -o -name '*.scss' 2>/dev/null | grep -v node_modules | head -20")}. Extract declarations: ${p.bash("grep -rh --include='*.css' --include='*.scss' -- '--[a-z]' . 2>/dev/null | grep -v node_modules | head -100")}. Also scan for usages: ${p.bash("grep -roh --include='*.css' --include='*.scss' --include='*.ts' --include='*.tsx' -- 'var(--[^)]+)' . 2>/dev/null | grep -o -- '--[^)]*' | sort | uniq -c | sort -rn | head -50")}. Use parseCssVar to parse each declaration line. For each variable track value and usage count. Identify unused variables (declared but never used).`, + output: s.object({ + variables: s.record(s.object({ + value: s.string, + usageCount: s.int, + })), + totalVars: s.int, + unusedVars: s.array(s.string), + }), +}); + +export default cssVariableExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts new file mode 100644 index 0000000..94a5fd3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts @@ -0,0 +1,32 @@ +import { agent, p, s } from "rig"; +import { defineTool } from "rig"; + +const extractRoutes = defineTool("extractRoutes", { + description: "Parse grep output lines to extract route method and path from Express-style code", + parameters: s.object({ grepLine: s.string }), + handler({ grepLine }) { + const match = grepLine.match(/app\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)/i) + ?? grepLine.match(/router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)/i); + if (!match) return null; + return { method: match[1].toUpperCase(), path: match[2] }; + }, +}); + +// Agent role: compare OpenAPI spec routes with Express route handler implementations. +const openapiRouteCoverage = agent({ + model: "typecheck", + tools: [extractRoutes], + instructions: p`Read the OpenAPI spec: ${p.readOptional("openapi.json", "{}")}. Also check ${p.readOptional("openapi.yaml", "")}. Scan source for route handlers: ${p.bash("grep -rn 'app\\.get\\|app\\.post\\|app\\.put\\|app\\.delete\\|router\\.' --include='*.ts' --include='*.js' . 2>/dev/null | grep -v node_modules | head -50")}. Use the extractRoutes tool to parse each grep line. Compare defined routes (from spec) vs implemented routes (from grep). Mark each as "implemented", "missing", or "extra". Compute coveragePercent.`, + output: s.object({ + routes: s.array(s.object({ + path: s.string, + method: s.enum("GET", "POST", "PUT", "DELETE", "PATCH"), + status: s.enum("implemented", "missing", "extra"), + })), + coveragePercent: s.number, + totalDefined: s.int, + totalImplemented: s.int, + }), +}); + +export default openapiRouteCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts new file mode 100644 index 0000000..9b9b072 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts @@ -0,0 +1,37 @@ +import { agent, p, s, repair } from "rig"; +import { defineTool } from "rig"; + +const classifyStyle = defineTool("classifyStyle", { + description: "Classify a JS file's module style based on require and import counts", + parameters: s.object({ requireCount: s.int, importCount: s.int }), + handler({ requireCount, importCount }) { + if (requireCount > 0 && importCount > 0) return "mixed"; + if (requireCount > 0) return "cjs"; + if (importCount > 0) return "esm"; + return "unknown"; + }, +}); + +// Agent role: classify each JavaScript file as ESM, CJS, mixed, or unknown module style. +const importStyleChecker = agent({ + model: "typecheck", + maxTurns: 3, + addons: repair(), + tools: [classifyStyle], + instructions: p`Find JS files: ${p.bash("find . -name '*.js' -not -path '*/node_modules/*' 2>/dev/null | head -30")}. For each file run both grep counts in one call: ${p.bash("find . -name '*.js' -not -path '*/node_modules/*' 2>/dev/null | head -30 | xargs -I{} sh -c 'echo {}:$(grep -c \"require(\" {} 2>/dev/null || echo 0):$(grep -c \"^import \" {} 2>/dev/null || echo 0)'")}. Use classifyStyle tool with the counts for each file. Aggregate summary counts by style.`, + output: s.object({ + files: s.record(s.object({ + style: s.enum("esm", "cjs", "mixed", "unknown"), + requireCount: s.int, + importCount: s.int, + })), + summary: s.object({ + esmCount: s.int, + cjsCount: s.int, + mixedCount: s.int, + }), + totalFiles: s.int, + }), +}); + +export default importStyleChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts new file mode 100644 index 0000000..12f8871 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts @@ -0,0 +1,40 @@ +import { agent, p, s, steering } from "rig"; +import { defineTool } from "rig"; + +const parseSemver = defineTool("parseSemver", { + description: "Parse a git tag string and determine if it is valid semver", + parameters: s.object({ tag: s.string }), + handler({ tag }) { + const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/); + if (!match) return { valid: false }; + return { + valid: true, + major: parseInt(match[1], 10), + minor: parseInt(match[2], 10), + patch: parseInt(match[3], 10), + }; + }, +}); + +// Agent role: validate all git tags against semver format and identify the latest valid tag. +const gitTagSemverValidator = agent({ + model: "typecheck", + addons: steering({ message: "For tags with date-based or non-semver formats, mark valid as false and omit the parsed field." }), + tools: [parseSemver], + instructions: p`List all git tags: ${p.bash("git tag --list 2>/dev/null || true")}. For each tag, call the parseSemver tool to check if it conforms to semver (e.g. v1.2.3 or 1.2.3). Count invalid tags. Identify the latest valid semver tag by finding the highest version number.`, + output: s.object({ + tags: s.array(s.object({ + tag: s.string, + valid: s.boolean, + parsed: s.optional(s.object({ + major: s.int, + minor: s.int, + patch: s.int, + })), + })), + invalidCount: s.int, + latestValid: s.optional(s.string), + }), +}); + +export default gitTagSemverValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts new file mode 100644 index 0000000..e72cc6a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: plan a minimal, low-risk refactor. Do not edit files. +const refactorPlan = agent({ + model: "typecheck", + output: s.object({ + steps: s.array(s.string), + files: s.array(s.string), + risks: s.array(s.string) + }), + instructions: `Plan a minimal, low-risk refactor. Do not edit files.`, +}); +export default refactorPlan; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts new file mode 100644 index 0000000..c5a7233 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts @@ -0,0 +1,31 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize release details for a single git tag range. +const timelineSummarizer = agent({ + name: "timelineSummarizer", + model: "typecheck", + input: s.object({ fromTag: s.string, toTag: s.string, logOutput: s.string }), + instructions: p`Given the git log output between two tags, extract the commit count and top 3 authors.`, + output: s.object({ + commitCount: s.int, + topAuthors: s.array(s.string), + }), +}); + +// Agent role: build a release timeline from git tags and report whether unreleased commits exist. +const gitTagTimelineReporter = agent({ + model: "typecheck", + instructions: p`List all git tags sorted by date: ${p.bash("git tag --sort=creatordate 2>/dev/null || echo ''")}. For each consecutive pair of tags, examine the log: ${p.bash("git log --oneline --format='%an' $(git tag --sort=creatordate | head -2 | tail -1)..HEAD 2>/dev/null | head -20 || echo ''")}. Delegate each tag range to the timelineSummarizer subagent. Also check for unreleased commits since the latest tag using ${p.bash("git log $(git describe --tags --abbrev=0 2>/dev/null || echo '')..HEAD --oneline 2>/dev/null | wc -l || echo 0")}. Build the full timeline and return structured results.`, + output: s.object({ + timeline: s.array(s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + })), + hasUnreleasedCommits: s.boolean, + }), + agents: { timelineSummarizer }, +}); + +export default gitTagTimelineReporter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts new file mode 100644 index 0000000..a197304 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts @@ -0,0 +1,20 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: probe each URL endpoint and classify its health status. +const serviceHealthProbe = agent({ + model: "typecheck", + addons: [steering({ message: "For any URL that times out or returns a non-standard code, classify as 'unknown' rather than failing." })], + instructions: p`Probe the comma-separated URLs in ${p.env("HEALTH_CHECK_URLS", "https://example.com,https://example.org")} using curl: ${p.bash("echo 'example: curl -o /dev/null -s -w \\'%{http_code}\\' --max-time 5 '")}. Run a separate curl command for each URL. Classify each: 'up' (2xx), 'down' (4xx/5xx/refused), 'slow' (timeout after 5s), 'unknown' (other). Count healthyCount and determine overallStatus: 'all-healthy' if all up, 'critical' if more than half are down, otherwise 'degraded'.`, + output: s.object({ + endpoints: s.array(s.object({ + url: s.url, + status: s.enum("up", "down", "slow", "unknown"), + httpCode: s.optional(s.int), + responseTimeMs: s.optional(s.int), + })), + healthyCount: s.int, + overallStatus: s.enum("all-healthy", "degraded", "critical"), + }), +}); + +export default serviceHealthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts new file mode 100644 index 0000000..791cf46 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts @@ -0,0 +1,27 @@ +import { agent, defineTool, p, s } from "rig"; + +const parseGitLogLine = defineTool("parseGitLogLine", { + description: "Parse a git log line in format 'HASH|AUTHOR|EMAIL|DATE|SUBJECT' into structured fields", + parameters: s.object({ line: s.string }), + handler({ line }) { + const parts = line.split("|"); + if (parts.length < 5) return null; + const [hash, author, email, date, ...subjectParts] = parts; + return { hash, author, email, date, subject: subjectParts.join("|") }; + }, +}); + +// Agent role: read a template file, fill git metadata placeholders, and write the rendered output. +const gitMetadataTemplateRenderer = agent({ + model: "typecheck", + tools: [parseGitLogLine], + instructions: p`Read the template using ${p.read("docs/commit-template.md")}. Gather recent commit metadata: ${p.bash("git log --format='%H|%an|%ae|%ai|%s' -10 2>/dev/null || echo ''")} and current branch: ${p.bash("git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown'")}. Use parseGitLogLine to parse each log line. Replace {{commit}}, {{author}}, {{branch}}, {{date}}, {{message}} placeholders in the template with actual values. Write the rendered content using ${p.writeOutput("renderedContent", "docs/commit-rendered.md")}. Return which placeholders were replaced.`, + output: s.object({ + rendered: s.boolean, + placeholdersReplaced: s.array(s.string), + outputPath: s.path, + renderedContent: s.string, + }), +}); + +export default gitMetadataTemplateRenderer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts new file mode 100644 index 0000000..8b460bc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts @@ -0,0 +1,32 @@ +import { agent, defineTool, p, s } from "rig"; + +const validateSemverBump = defineTool("validateSemverBump", { + description: "Validate and classify a semver bump type based on commit message keywords", + parameters: s.object({ commitMessages: s.string }), + handler({ commitMessages }) { + const lower = commitMessages.toLowerCase(); + if (/breaking.change|BREAKING CHANGE/i.test(commitMessages)) return "major"; + if (/^feat[:(]/m.test(lower) || /feature/i.test(lower)) return "minor"; + return "patch"; + }, +}); + +// Agent role: analyze recent git changes, determine semver bump type, and write a changelog entry. +const changelogEntryGenerator = agent({ + model: "typecheck", + tools: [validateSemverBump], + instructions: p`Analyze recent git diff: ${p.bash("git diff HEAD~1 HEAD --stat 2>/dev/null || true")} and commit log: ${p.bash("git log HEAD~1..HEAD --oneline 2>/dev/null || echo 'no commits'")}. Use validateSemverBump to determine the bump type. Categorize commits into breaking changes, features, fixes, and chores. Propose a next version string (e.g. 1.2.3). Write the changelog entry using ${p.write("CHANGELOG.md", "## [Unreleased]\n")}. Return structured results.`, + output: s.object({ + bumpType: s.enum("patch", "minor", "major"), + categories: s.object({ + breaking: s.array(s.string), + features: s.array(s.string), + fixes: s.array(s.string), + chores: s.array(s.string), + }), + entryWritten: s.boolean, + version: s.string, + }), +}); + +export default changelogEntryGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts new file mode 100644 index 0000000..1fdc29b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts @@ -0,0 +1,20 @@ +import { agent, p, s } from "rig"; + +// Agent role: scan source files for TODO/FIXME/HACK comments and write a grouped markdown report. +const todoFixmeTracker = agent({ + model: "typecheck", + instructions: p`Scan source files for comment markers: ${p.bash("grep -rn 'TODO\\|FIXME\\|HACK' --include='*.ts' --include='*.js' --include='*.tsx' --include='*.py' . 2>/dev/null | grep -v node_modules | head -100 || echo ''")}. Parse each matching line to extract file path, line number, comment type (TODO, FIXME, or HACK), and the message text. Count occurrences by type. Write a grouped markdown report using ${p.write("todo-report.md", "# TODO/FIXME/HACK Report\n")}. Return all found items and summary counts.`, + output: s.object({ + todos: s.array(s.object({ + file: s.path, + line: s.int, + type: s.enum("TODO", "FIXME", "HACK"), + message: s.string, + })), + totalCount: s.int, + byType: s.record(s.int), + reportWritten: s.boolean, + }), +}); + +export default todoFixmeTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts new file mode 100644 index 0000000..c120b34 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts @@ -0,0 +1,20 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize a single TypeScript source file in one sentence. +const fileSummarizer = agent({ + name: "fileSummarizer", + model: "typecheck", + input: s.object({ filePath: s.path }), + instructions: p`Read and summarize the file: ${p.readInput("filePath")}. Return a one-sentence summary of what the file does.`, + output: s.string, +}); + +// Agent role: find TypeScript source files and delegate summarization to fileSummarizer, then aggregate results keyed by path. +const multiFileGlobSummarizer = agent({ + model: "typecheck", + instructions: p`Find TypeScript source files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -15 || echo ''")}. For each file path found, delegate to the fileSummarizer subagent passing the file path. Collect all summaries into a record keyed by file path. If no files are found, return an empty record.`, + output: s.record(s.string), + agents: { fileSummarizer }, +}); + +export default multiFileGlobSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts new file mode 100644 index 0000000..520b234 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts @@ -0,0 +1,39 @@ +import { agent, defineTool, p, s } from "rig"; + +const analyzeShellScript = defineTool("analyzeShellScript", { + description: "Read a shell script file and analyze its safety flags and shebang", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf8"); + const lines = content.split("\n"); + const shebang = lines[0]?.startsWith("#!") ? lines[0] : null; + const hasSetE = /\bset\s+-[a-z]*e/.test(content) || /\bset\s+-e\b/.test(content); + const hasSetU = /\bset\s+-[a-z]*u/.test(content) || /\bset\s+-u\b/.test(content); + const hasPipefail = /set\s+-o\s+pipefail/.test(content); + const safetyLevel = hasSetE && hasSetU && hasPipefail ? "strict" + : hasSetE || hasSetU ? "partial" + : "unsafe"; + return { shebang, hasSetE, hasSetU, hasPipefail, safetyLevel }; + } catch { + return { shebang: null, hasSetE: false, hasSetU: false, hasPipefail: false, safetyLevel: "unsafe" }; + } + }, +}); + +// Agent role: find shell scripts and analyze each for safety flag usage. +const shellScriptAnalyzer = agent({ + model: "typecheck", + tools: [analyzeShellScript], + instructions: p`Find shell scripts: ${p.bash("find . -name '*.sh' -not -path '*/node_modules/*' 2>/dev/null | head -20 || echo ''")}. For each .sh file found, call analyzeShellScript to inspect its shebang and safety flags (set -e, set -u, set -o pipefail). Return a record keyed by file path.`, + output: s.record(s.object({ + shebang: s.optional(s.string), + hasSetE: s.boolean, + hasSetU: s.boolean, + hasPipefail: s.boolean, + safetyLevel: s.enum("strict", "partial", "unsafe"), + })), +}); + +export default shellScriptAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts new file mode 100644 index 0000000..d6a33df --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts @@ -0,0 +1,53 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const crossCheckVersions = defineTool("crossCheckVersions", { + description: "Cross-check declared package.json versions against package-lock.json resolved versions", + parameters: s.object({ packageJson: s.string, lockJson: s.string }), + handler({ packageJson, lockJson }) { + try { + const pkg = JSON.parse(packageJson); + const lock = JSON.parse(lockJson); + const declared: Record = { + ...pkg.dependencies, + ...pkg.devDependencies, + }; + const lockPackages = lock.packages || {}; + const drifted: Array<{ name: string; declared: string; locked: string; severity: string }> = []; + for (const [name, declaredVersion] of Object.entries(declared)) { + const lockEntry = lockPackages[`node_modules/${name}`]; + if (!lockEntry) continue; + const locked = lockEntry.version as string; + const declStr = String(declaredVersion).replace(/^[\^~]/, ""); + if (locked !== declStr) { + const [dMaj, dMin] = declStr.split(".").map(Number); + const [lMaj, lMin] = locked.split(".").map(Number); + const severity = lMaj !== dMaj ? "major" : lMin !== dMin ? "minor" : "patch"; + drifted.push({ name, declared: String(declaredVersion), locked, severity }); + } + } + return drifted; + } catch (e) { + return { error: String(e) }; + } + }, +}); + +// Agent role: detect version drift between package.json declarations and package-lock.json resolved versions. +const lockFileDriftDetector = agent({ + model: "typecheck", + addons: [repair()], + tools: [crossCheckVersions], + instructions: p`Read package.json: ${p.bash("cat package.json 2>/dev/null || echo '{}'")} and package-lock.json: ${p.bash("cat package-lock.json 2>/dev/null || echo '{}'")}. Call crossCheckVersions with both file contents to find drifted packages. Return driftedPackages list, total driftCount, and whether all packages are in sync.`, + output: s.object({ + driftedPackages: s.array(s.object({ + name: s.string, + declared: s.string, + locked: s.string, + severity: s.enum("patch", "minor", "major", "unknown"), + })), + driftCount: s.int, + allInSync: s.boolean, + }), +}); + +export default lockFileDriftDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts new file mode 100644 index 0000000..c2cf93c --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts @@ -0,0 +1,20 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: scan the repository for git conflict markers and report affected files. +const gitConflictMarkerScanner = agent({ + model: "typecheck", + addons: [steering({ message: "Check all text file types including .ts, .js, .json, .md, .yaml. Report every line where a conflict marker appears." })], + instructions: p`Scan for git conflict markers in tracked files: ${p.bash("grep -rn '<<<<<<< \\|=======$\\|>>>>>>> ' --include='*.ts' --include='*.js' --include='*.json' --include='*.md' --include='*.yaml' --include='*.yml' . 2>/dev/null | grep -v node_modules | head -100 || echo ''")}. Also check all text files: ${p.bash("grep -rn '^<<<<<<< ' . 2>/dev/null | grep -v node_modules | grep -v '.git' | head -50 || echo ''")}. For each match, extract the file path, line number, and which marker it is. Deduplicate affected file paths. Return all conflict locations, the unique affected files list, total count, and whether the repo is clean.`, + output: s.object({ + conflicts: s.array(s.object({ + file: s.path, + line: s.int, + marker: s.enum("<<<<<<<", "=======", ">>>>>>>"), + })), + affectedFiles: s.array(s.path), + conflictCount: s.int, + isClean: s.boolean, + }), +}); + +export default gitConflictMarkerScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts new file mode 100644 index 0000000..84c7975 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts @@ -0,0 +1,50 @@ +import { agent, defineTool, p, s } from "rig"; + +const extractProtoMessages = defineTool("extractProtoMessages", { + description: "Read a .proto file and extract message names with their field definitions", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf8"); + const result: Record> = {}; + const messageRegex = /message\s+(\w+)\s*\{([^}]*)\}/gs; + const fieldRegex = /^\s*(repeated\s+)?(\w+)\s+(\w+)\s*=\s*(\d+)/gm; + let msgMatch; + while ((msgMatch = messageRegex.exec(content)) !== null) { + const [, messageName, body] = msgMatch; + const fields: Array<{ fieldName: string; fieldType: string; fieldNumber: number; isRepeated: boolean }> = []; + let fieldMatch; + fieldRegex.lastIndex = 0; + while ((fieldMatch = fieldRegex.exec(body)) !== null) { + const [, repeated, fieldType, fieldName, fieldNumberStr] = fieldMatch; + fields.push({ + fieldName, + fieldType, + fieldNumber: parseInt(fieldNumberStr, 10), + isRepeated: !!repeated, + }); + } + result[messageName] = fields; + } + return result; + } catch (e) { + return { error: String(e) }; + } + }, +}); + +// Agent role: find .proto files and extract message field definitions from each. +const protoFieldExtractor = agent({ + model: "typecheck", + tools: [extractProtoMessages], + instructions: p`Find .proto files: ${p.bash("find . -name '*.proto' -not -path '*/node_modules/*' 2>/dev/null | head -20 || echo ''")}. For each .proto file found, call extractProtoMessages to parse message definitions and field lists. Merge all results into a record keyed by message name. If no .proto files exist, return an empty record.`, + output: s.record(s.array(s.object({ + fieldName: s.string, + fieldType: s.string, + fieldNumber: s.int, + isRepeated: s.boolean, + }))), +}); + +export default protoFieldExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts new file mode 100644 index 0000000..3cd7cef --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: return a complete replacement for the target file. +const patcher = agent({ + model: "typecheck", + output: s.object({ + path: s.string, + contents: s.string, + summary: s.string + }), + instructions: `Return a complete replacement for the target file.`, +}); +export default patcher; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts new file mode 100644 index 0000000..e67cf12 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts @@ -0,0 +1,17 @@ +import { agent, p, s, steering, repair } from "rig"; + +// Agent role: rewrite recent git commit messages into conventional commit format with imperative mood. +const commitMsgRewriter = agent({ + model: "typecheck", + instructions: p`Review recent commits from ${p.bash("git log --oneline -20 2>/dev/null || echo 'no commits'")} and rewrite each message in conventional commit format with imperative mood (e.g. "Add feature" not "Added feature"). Classify each by category.`, + output: s.array(s.object({ + hash: s.string, + original: s.string, + revised: s.string, + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + })), + maxTurns: 6, + addons: [steering({ message: "Use imperative mood and conventional commit prefixes." }), repair()], +}); + +export default commitMsgRewriter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts new file mode 100644 index 0000000..17d643f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts @@ -0,0 +1,50 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize a git tag release interval into structured timeline data. +const timelineSummarizer = agent({ + model: "typecheck", + name: "timelineSummarizer", + input: s.object({ + tag: s.string, + date: s.string, + commitLog: s.string, + }), + instructions: p`Summarize the commit log for release ${p.inputField("tag")} on ${p.inputField("date")}. +Commit log: +${p.inputField("commitLog")} +Return the top authors (up to 3) and the commit count.`, + output: s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + }), +}); + +// Agent role: report git tag release timeline with commit stats between consecutive tags. +const gitTagTimelineReporter = agent({ + model: "typecheck", + instructions: p`You are a git release timeline reporter. + +List all git tags sorted by version: +${p.bash("git tag --sort=version:refname")} + +For each consecutive pair of tags, run: git log --oneline TAG1..TAG2 --format="%h %an %s" +to find commits between them. Also check for unreleased commits after the latest tag with: +${p.bash("git log --oneline $(git describe --tags --abbrev=0 2>/dev/null || echo '')..HEAD 2>/dev/null | wc -l")} + +For each tag interval, delegate to the timelineSummarizer subagent with the tag name, date, and commit log. +Aggregate all results into the output array.`, + agents: { timelineSummarizer }, + output: s.object({ + timeline: s.array(s.object({ + tag: s.string, + date: s.string, + commitCount: s.int, + topAuthors: s.array(s.string), + })), + hasUnreleasedCommits: s.boolean, + }), +}); + +export default gitTagTimelineReporter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts new file mode 100644 index 0000000..c184a3c --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts @@ -0,0 +1,24 @@ +import { agent, p, s, defineTool } from "rig"; + +const extractKeys = defineTool("extractKeys", { + description: "Extract KEY names from dotenv-style file content", + parameters: s.object({ content: s.string }), + handler({ content }) { + const keys = (content.match(/^([A-Z_][A-Z0-9_]*)=/gm) ?? []).map((l: string) => l.replace("=", "")); + return { keys }; + }, +}); + +// Agent role: compare .env.example required keys against .env actual keys to find missing and extra entries. +const envKeyChecker = agent({ + model: "typecheck", + instructions: p`Read required keys from ${p.readOptional(".env.example")} and present keys from ${p.readOptional(".env")}. Use extractKeys on each content. Compare to find missing (in example, not in env) and extra (in env, not in example) keys.`, + output: s.object({ + missing: s.array(s.string), + extra: s.array(s.string), + status: s.enum("complete", "partial", "empty"), + }), + tools: [extractKeys], +}); + +export default envKeyChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts new file mode 100644 index 0000000..1a952ba --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts @@ -0,0 +1,37 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: probe HTTP endpoints and classify their health status. +const serviceHealthProbe = agent({ + model: "typecheck", + input: s.object({ + urls: s.array(s.string), + }), + instructions: p`You are a service health probe. + +For each URL in the input list, run: curl -o /dev/null -s -w '%{http_code}' +using the command once per element. +${p.bashEach("curl -o /dev/null -s -w '%{http_code}' --max-time 5 {}", "urls")} + +Classify each endpoint: +- "up": HTTP 2xx +- "down": HTTP 5xx or connection refused +- "slow": HTTP 408 or timeout +- "unknown": anything else + +Count healthy endpoints (status "up") and set overallStatus: +- "all-healthy": all up +- "degraded": some up +- "critical": none up`, + addons: [steering({ message: "Re-check any endpoint that returned an ambiguous or unexpected status code before finalizing." })], + output: s.object({ + endpoints: s.array(s.object({ + url: s.url, + status: s.enum("up", "down", "slow", "unknown"), + httpCode: s.optional(s.int), + })), + healthyCount: s.int, + overallStatus: s.enum("all-healthy", "degraded", "critical"), + }), +}); + +export default serviceHealthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts new file mode 100644 index 0000000..780aa6f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts @@ -0,0 +1,41 @@ +import { agent, defineTool, p, s } from "rig"; + +const parseCommit = defineTool("parseCommit", { + description: "Parse a pipe-delimited git log line into structured commit fields", + parameters: s.object({ line: s.string }), + handler({ line }) { + const [hash, author, email, date, ...rest] = line.split("|"); + return { hash, author, email, date, message: rest.join("|") }; + }, +}); + +// Agent role: render a file template using git commit metadata as placeholder values. +const gitMetadataTemplateRenderer = agent({ + model: "typecheck", + input: s.object({ + templatePath: s.path, + outputPath: s.path, + }), + instructions: p`You are a git metadata template renderer. + +Template content: +${p.readInput("templatePath")} + +Current commit metadata (hash|author|email|date|message): +${p.bash("git log -1 --format=%H|%an|%ae|%aI|%s")} + +Current branch: +${p.bash("git rev-parse --abbrev-ref HEAD")} + +Use the parseCommit tool to parse the commit metadata line. +Replace all occurrences of {{commit}}, {{author}}, {{branch}}, {{date}}, {{message}} in the template with their actual values. +Count how many distinct placeholder types were replaced. +${p.writeInput("outputPath", "rendered")}`, + tools: [parseCommit], + output: s.object({ + rendered: s.string, + placeholdersFilled: s.int, + }), +}); + +export default gitMetadataTemplateRenderer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts new file mode 100644 index 0000000..29bbae1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts @@ -0,0 +1,31 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze structural differences between two JSON schemas and list each change. +const diffAnalyzer = agent({ + name: "diffAnalyzer", + model: "typecheck", + instructions: p`Analyze the structural differences between the two JSON schemas provided in the input and list each change with its path and whether it is a breaking change.`, + input: s.object({ oldSchema: s.string, newSchema: s.string }), + output: s.array(s.object({ + changeType: s.enum("add", "remove", "modify", "rename"), + path: s.string, + description: s.string, + breakingChange: s.boolean, + })), +}); + +// Agent role: read two JSON schema files and produce a migration plan using the diffAnalyzer subagent. +const jsonSchemaMigrationPlanner = agent({ + model: "typecheck", + input: s.object({ oldSchemaPath: s.path, newSchemaPath: s.path }), + instructions: p`Read the old schema at ${p.readInput("oldSchemaPath")} and the new schema at ${p.readInput("newSchemaPath")}. Delegate the structural diff analysis to the diffAnalyzer subagent.`, + output: s.array(s.object({ + changeType: s.enum("add", "remove", "modify", "rename"), + path: s.string, + description: s.string, + breakingChange: s.boolean, + })), + agents: { diffAnalyzer }, +}); + +export default jsonSchemaMigrationPlanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts new file mode 100644 index 0000000..d9a6190 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts @@ -0,0 +1,29 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const validateBumpType = defineTool("validateBumpType", { + description: "Validate that a semver bump type is major, minor, or patch", + parameters: s.object({ bumpType: s.string }), + handler: ({ bumpType }) => { const v = /^(major|minor|patch)$/.test(bumpType); return { valid: v, reason: v ? "ok" : `expected major|minor|patch, got: ${bumpType}` }; }, +}); +// Agent role: generate a structured changelog entry from the current git diff. +const changelogEntryGenerator = agent({ + model: "typecheck", + instructions: p`Generate a changelog entry from this diff: ${p.bash("git diff HEAD")} +Categorize into added, fixed, changed, breaking. Validate bumpType with validateBumpType. +Latest tag: ${p.bash("git describe --tags --abbrev=0 2>/dev/null || echo '0.0.0'")} +Write a human-readable entry in "entry". ${p.writeOutput("entry", "CHANGELOG_ENTRY.md")}`, + tools: [validateBumpType], + addons: [repair()], + output: s.object({ + entry: s.string, + version: s.string, + changes: s.object({ + added: s.array(s.string), + fixed: s.array(s.string), + changed: s.array(s.string), + breaking: s.array(s.string), + }), + bumpType: s.enum("major", "minor", "patch"), + }), +}); +export default changelogEntryGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts new file mode 100644 index 0000000..68ae20a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts @@ -0,0 +1,28 @@ +import { agent, p, s, defineTool } from "rig"; + +const RULES = [ + { re: /^USER\s+root\s*$/im, sev: "critical", pattern: "root USER", suggestion: "Use a non-root user" }, + { re: /^ADD\s+(?!https?:\/\/)/m, sev: "medium", pattern: "ADD for local files", suggestion: "Use COPY instead of ADD" }, + { re: /:latest/, sev: "high", pattern: ":latest tag", suggestion: "Pin to a specific image version" }, + { re: /ENV\s+\w*(SECRET|PASSWORD|TOKEN|KEY)\w*\s*=/, sev: "critical", pattern: "secret in ENV", suggestion: "Use build args or secrets" }, +]; +const auditPatterns = defineTool("auditPatterns", { + description: "Check a Dockerfile line for known insecure patterns", + parameters: s.object({ line: s.string, lineNumber: s.int }), + handler: ({ line, lineNumber }) => ({ + lineNumber, + findings: RULES.filter(r => r.re.test(line)).map(({ sev: severity, pattern, suggestion }) => ({ severity, pattern, suggestion })), + }), +}); +// Agent role: audit a Dockerfile for security anti-patterns and produce a severity-ranked findings report. +const dockerfileSecurityAuditor = agent({ + model: "typecheck", + instructions: p`Read the Dockerfile: ${p.readOptional("Dockerfile", "# no Dockerfile")}. Use auditPatterns on each instruction line to detect security issues. Compute an overall score from 0–100 (100 = no issues).`, + output: s.object({ + findings: s.array(s.object({ line: s.int, pattern: s.string, severity: s.enum("low", "medium", "high", "critical"), suggestion: s.string })), + passes: s.boolean, + score: s.int, + }), + tools: [auditPatterns], +}); +export default dockerfileSecurityAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts new file mode 100644 index 0000000..d1a780a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts @@ -0,0 +1,16 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: run npm audit and produce a simplified grouped vulnerability report with remediation advice. +const npmAuditSimplifier = agent({ + model: "typecheck", + instructions: p`Run ${p.bash("npm audit --json 2>/dev/null || echo '{}'")} to get the vulnerability report. Parse the JSON, group vulnerability package names by severity level, count totals, and provide a concise remediation recommendation.`, + output: s.object({ + vulnerabilitiesByLevel: s.record(s.array(s.string)), + totalCount: s.number, + recommendation: s.string, + }), + maxTurns: 5, + addons: repair(), +}); + +export default npmAuditSimplifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts new file mode 100644 index 0000000..4277ee8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s } from "rig"; + +const classifyComment = defineTool("classifyComment", { + description: "Classify a source code comment line by marker type and whether it has an owner", + parameters: s.object({ line: s.string }), + handler({ line }) { + const match = line.match(/\b(TODO|FIXME|HACK|XXX)\b/); + const type = (match?.[1] ?? "TODO") as "TODO" | "FIXME" | "HACK" | "XXX"; + const hasOwner = /\([\w.@-]+\)/.test(line); + return { type, hasOwner }; + }, +}); + +// Agent role: scan source files for TODO/FIXME/HACK/XXX comments and produce a structured report. +const todoFixmeTracker = agent({ + model: "typecheck", + instructions: p`You are a TODO/FIXME/HACK/XXX comment tracker. + +Scan TypeScript and JavaScript source files for comment markers: +${p.bash("grep -rn 'TODO\\|FIXME\\|HACK\\|XXX' --include='*.ts' --include='*.js' . 2>/dev/null | grep -v node_modules || true")} + +For each matching line, use the classifyComment tool to determine the type and whether it names an owner. +Collect all items and compute totalCount and byType counts. +Write a markdown summary in the "report" field. +${p.writeOutput("report", "TODO_REPORT.md")}`, + tools: [classifyComment], + output: s.object({ + report: s.string, + items: s.array(s.object({ + file: s.path, + line: s.int, + type: s.enum("TODO", "FIXME", "HACK", "XXX"), + text: s.string, + })), + totalCount: s.int, + byType: s.record(s.int), + }), +}); + +export default todoFixmeTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts new file mode 100644 index 0000000..8df27cf --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts @@ -0,0 +1,15 @@ +import { agent, p, s } from "rig"; + +// Agent role: inventory all git stashes, listing changed files and classifying staleness. +const gitStashInventory = agent({ + model: "typecheck", + instructions: p`List all stashes: ${p.bash("git stash list 2>/dev/null || echo 'no stashes'")}. For each stash ref, show changed files: ${p.bash("git stash show --name-only 2>/dev/null || true")}. Classify staleness: fresh (< 1 week), aging (1–4 weeks), stale (1–3 months), ancient (> 3 months).`, + output: s.array(s.object({ + stashRef: s.string, + description: s.string, + changedFiles: s.array(s.string), + staleness: s.enum("fresh", "aging", "stale", "ancient"), + })), +}); + +export default gitStashInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts new file mode 100644 index 0000000..e7a2acf --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts @@ -0,0 +1,39 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize a single TypeScript file's purpose and exports. +const fileSummarizer = agent({ + model: "typecheck", + name: "fileSummarizer", + input: s.object({ path: s.path }), + instructions: p`Summarize the following TypeScript file. + +File contents: +${p.readInput("path")} + +Return a one-sentence summary, the number of lines, and whether the file has any exports.`, + output: s.object({ + summary: s.string, + lineCount: s.int, + hasExports: s.boolean, + }), +}); + +// Agent role: discover TypeScript files in the workspace and summarize each via a subagent. +const multiFileGlobSummarizer = agent({ + model: "typecheck", + instructions: p`You are a multi-file TypeScript summarizer. + +Discovered TypeScript files (excluding node_modules): +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*'")} + +For each file path, delegate to the fileSummarizer subagent, passing the file path as input. +Aggregate all results into a record keyed by file path.`, + agents: { fileSummarizer }, + output: s.record(s.object({ + summary: s.string, + lineCount: s.int, + hasExports: s.boolean, + })), +}); + +export default multiFileGlobSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts new file mode 100644 index 0000000..4b132f6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts @@ -0,0 +1,48 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const parseRemoteLine = defineTool("parseRemoteLine", { + description: "Parse a git remote -v output line into name, url, type, and protocol", + parameters: s.object({ line: s.string }), + handler({ line }) { + const parts = line.split(/\s+/); + const name = parts[0] ?? ""; + const url = parts[1] ?? ""; + const raw = parts[2] ?? ""; + const type: "fetch" | "push" = raw.includes("push") ? "push" : "fetch"; + let protocol: "https" | "ssh" | "git" | "unknown" = "unknown"; + if (url.startsWith("https://")) protocol = "https"; + else if (url.startsWith("git@") || url.startsWith("ssh://")) protocol = "ssh"; + else if (url.startsWith("git://")) protocol = "git"; + return { name, url, type, protocol }; + }, +}); + +// Agent role: inspect git remotes and report their URLs, protocols, and remote branch count. +const gitRemoteInspector = agent({ + model: "typecheck", + instructions: p`You are a git remote inspector. + +Git remotes: +${p.bash("git remote -v")} + +Remote branch count (origin): +${p.bash("git ls-remote --heads origin 2>/dev/null | wc -l")} + +For each non-empty line in the remote output, use the parseRemoteLine tool. +Deduplicate entries that share the same name. +Report whether a remote named "origin" exists and the total remote branch count.`, + tools: [parseRemoteLine], + addons: [repair()], + output: s.object({ + remotes: s.array(s.object({ + name: s.string, + url: s.url, + type: s.enum("fetch", "push"), + protocol: s.enum("https", "ssh", "git", "unknown"), + })), + remoteBranchCount: s.int, + hasOrigin: s.boolean, + }), +}); + +export default gitRemoteInspector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts new file mode 100644 index 0000000..4a645d2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts @@ -0,0 +1,42 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const checkEndpoint = defineTool("checkEndpoint", { + description: "Probe an HTTP endpoint and return the status code and latency", + parameters: s.object({ url: s.url }), + async handler({ url }) { + const { execSync } = await import("node:child_process"); + const start = Date.now(); + try { + const code = execSync( + `curl -o /dev/null -s -w '%{http_code}' --max-time 5 "${url}"`, + { encoding: "utf8" }, + ).trim(); + return { statusCode: parseInt(code, 10), latencyMs: Date.now() - start }; + } catch { + return { statusCode: 0, latencyMs: Date.now() - start }; + } + }, +}); + +// Agent role: probe each supplied HTTP endpoint and classify its health status. +const httpEndpointHealthChecker = agent({ + model: "typecheck", + input: s.object({ endpoints: s.array(s.url) }), + instructions: p`For each URL in ${p.inputField("endpoints")}, call checkEndpoint to get the HTTP status code. Classify: ok (2xx), redirect (3xx), client-error (4xx), server-error (5xx), timeout (0 with latency >= 5000), unreachable (0 with low latency).`, + output: s.object({ + results: s.array(s.object({ + url: s.url, + statusCode: s.int, + status: s.enum("ok", "redirect", "client-error", "server-error", "timeout", "unreachable"), + latencyMs: s.optional(s.int), + })), + healthyCount: s.int, + totalCount: s.int, + allHealthy: s.boolean, + }), + tools: [checkEndpoint], + maxTurns: 5, + addons: repair(), +}); + +export default httpEndpointHealthChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts new file mode 100644 index 0000000..d924fcd --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts @@ -0,0 +1,37 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const parseBlameOutput = defineTool("parseBlameOutput", { + description: "Parse git blame --line-porcelain output to compute per-author line counts", + parameters: s.object({ blameText: s.string }), + handler({ blameText }) { + const authorCounts: Record = {}; + let totalLines = 0; + for (const match of blameText.matchAll(/^author (.+)$/gm)) { + const author = match[1].trim(); + authorCounts[author] = (authorCounts[author] ?? 0) + 1; + totalLines++; + } + return { authorCounts, totalLines }; + }, +}); + +// Agent role: analyze git blame for a file to report per-author line ownership. +const gitBlameOwnership = agent({ + model: "typecheck", + input: s.object({ filePath: s.path }), + instructions: p`Run git blame on the file: ${p.bash("git blame --line-porcelain HEAD -- . 2>/dev/null | head -500 || echo ''")}. Use parseBlameOutput on the porcelain output. Compute per-author percentage from line counts. Identify the top author.`, + output: s.object({ + authors: s.record(s.object({ + lineCount: s.int, + percentage: s.number, + firstLine: s.optional(s.int), + lastLine: s.optional(s.int), + })), + topAuthor: s.string, + totalLines: s.int, + }), + tools: [parseBlameOutput], + addons: steering({ message: "Ensure percentages sum to 100 and totalLines matches the sum of all line counts." }), +}); + +export default gitBlameOwnership; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts new file mode 100644 index 0000000..ee0629e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s, steering } from "rig"; +import { readFile } from "node:fs/promises"; + +const extractEnumValues = defineTool("extractEnumValues", { + description: "Extract all member names and values from a TypeScript enum in a source file", + parameters: s.object({ filePath: s.string, enumName: s.string }), + async handler({ filePath, enumName }) { + const source = await readFile(filePath, "utf8"); + const constMatch = new RegExp(`(const\\s+)?enum\\s+${enumName}\\s*\\{([^}]*)\\}`, "s").exec(source); + if (!constMatch) return { members: [], isConst: false, memberCount: 0 }; + const isConst = Boolean(constMatch[1]); + const body = constMatch[2]; + const members = [...body.matchAll(/(\w+)\s*(?:=\s*([^,\n]+))?/g)].map((m) => ({ + name: m[1], + value: m[2]?.trim() ?? undefined, + })); + return { members, isConst, memberCount: members.length }; + }, +}); + +// Agent role: find all TypeScript enum declarations and extract their members and values. +const tsEnumExtractor = agent({ + model: "typecheck", + instructions: p`You are a TypeScript enum extractor. + +Find TypeScript files with enum declarations: +${p.bash("grep -rn 'enum ' --include='*.ts' . 2>/dev/null | grep -v node_modules || true")} + +For each unique (file, enumName) pair found, use the extractEnumValues tool. +Aggregate results into a record keyed by enum name (append "@filepath" if the same name appears in multiple files).`, + tools: [extractEnumValues], + addons: [steering({ message: "Ensure every file from the grep output is scanned before finalizing." })], + output: s.record(s.object({ + members: s.array(s.object({ name: s.string, value: s.optional(s.string) })), + isConst: s.boolean, + memberCount: s.int, + })), +}); + +export default tsEnumExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts new file mode 100644 index 0000000..f3c7210 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts @@ -0,0 +1,58 @@ +import { agent, defineTool, p, s, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const readJsonFile = defineTool("readJsonFile", { + description: "Read and parse a JSON file from the given path", + parameters: s.object({ path: s.string }), + async handler({ path }) { + const text = await readFile(path, "utf8"); + return JSON.parse(text); + }, +}); + +const mergeObjects = defineTool("mergeObjects", { + description: "Shallow-merge an override object into a base object", + parameters: s.object({ base: s.unknown, override: s.unknown }), + handler({ base, override }) { + const b = base as Record; + const o = override as Record; + let keysAdded = 0; + let keysOverridden = 0; + const result = { ...b }; + for (const [k, v] of Object.entries(o)) { + if (k in result) keysOverridden++; + else keysAdded++; + result[k] = v; + } + return { merged: JSON.stringify(result, null, 2), keysAdded, keysOverridden, totalKeys: Object.keys(result).length }; + }, +}); + +// Agent role: merge two JSON config files and write the combined result to an output path. +const jsonConfigMerger = agent({ + model: "typecheck", + input: s.object({ + baseConfig: s.path, + overrideConfig: s.path, + outputPath: s.path, + }), + instructions: p`You are a JSON config merger. + +Base config file contents: +${p.readInput("baseConfig")} + +Use the readJsonFile tool to read the override config at input.overrideConfig. +Use the mergeObjects tool to merge the override into the base. +The merged field from the tool result is already a JSON string — use it as the output "merged" value. +${p.writeInput("outputPath", "merged")}`, + tools: [readJsonFile, mergeObjects], + addons: [repair()], + output: s.object({ + merged: s.string, + keysAdded: s.int, + keysOverridden: s.int, + totalKeys: s.int, + }), +}); + +export default jsonConfigMerger; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts new file mode 100644 index 0000000..aba320e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts @@ -0,0 +1,28 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const extractGenerics = defineTool("extractGenerics", { + description: "Extract TypeScript generic type parameters from a source file", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + const content = await readFile(filePath, "utf8").catch(() => ""); + const matches = content.match(/<[A-Z][A-Za-z]*(?:,\s*[A-Z][A-Za-z]*)*>/g) ?? []; + return { generics: [...new Set(matches)], count: matches.length }; + }, +}); + +// Agent role: scan TypeScript files for generic type parameters and classify complexity. +const tsGenericTypeExtractor = agent({ + model: "typecheck", + instructions: p`Find all TypeScript files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' 2>/dev/null | head -50")}. For each file, use extractGenerics to find generic type parameters. Classify complexity: none (0 generics), simple (1–2), moderate (3–5), complex (6+).`, + output: s.record(s.object({ + generics: s.array(s.string), + count: s.int, + complexity: s.enum("none", "simple", "moderate", "complex"), + })), + tools: [extractGenerics], + maxTurns: 5, + addons: repair(), +}); + +export default tsGenericTypeExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts new file mode 100644 index 0000000..14aeb4d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts @@ -0,0 +1,33 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const validateScript = defineTool("validateScript", { + description: "Validate a shell script for safety flags and structure", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + const content = await readFile(filePath, "utf8").catch(() => ""); + const lines = content.split("\n"); + const hasShebang = lines[0]?.startsWith("#!"); + const hasSafeFlags = /set\s+-[^#]*e/.test(content) && /set\s+-[^#]*u/.test(content); + const hasEval = /\beval\b/.test(content); + const functionCount = (content.match(/^\s*(function\s+\w+|\w+\s*\(\s*\))/gm) ?? []).length; + return { hasShebang, hasSafeFlags, hasEval, functionCount }; + }, +}); + +// Agent role: validate shell scripts for safety flags and classify quality. +const shellScriptValidator = agent({ + model: "typecheck", + instructions: p`Find all shell scripts: ${p.bash("find . -name '*.sh' -not -path '*/node_modules/*' 2>/dev/null | head -30")}. Use validateScript on each file. Classify quality: excellent (shebang + safe flags + no eval), good (shebang + safe flags), fair (shebang only), poor (no shebang).`, + output: s.record(s.object({ + hasShebang: s.boolean, + hasSafeFlags: s.boolean, + hasEval: s.boolean, + functionCount: s.int, + quality: s.enum("excellent", "good", "fair", "poor"), + })), + tools: [validateScript], + addons: steering({ message: "Classify every found script. If no scripts are found, return an empty record." }), +}); + +export default shellScriptValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts new file mode 100644 index 0000000..2ec1ed6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s, steering } from "rig"; + +const classifyComplexity = defineTool("classifyComplexity", { + description: "Classify a file's complexity tier based on its line count", + parameters: s.object({ lineCount: s.int }), + handler({ lineCount }) { + if (lineCount < 50) return { tier: "trivial" as const }; + if (lineCount < 150) return { tier: "small" as const }; + if (lineCount < 300) return { tier: "medium" as const }; + if (lineCount < 600) return { tier: "large" as const }; + return { tier: "huge" as const }; + }, +}); + +// Agent role: analyze TypeScript source files by line count and classify their complexity. +const sourceComplexityHeatmap = agent({ + model: "typecheck", + instructions: p`You are a source complexity heatmap generator. + +TypeScript source file line counts (sorted descending): +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | xargs wc -l 2>/dev/null | sort -rn | grep -v total || true")} + +For each file (skip the "total" summary line), use the classifyComplexity tool to assign a tier. +Build a record keyed by file path with lineCount and tier. +List hotspot files (tier "large" or "huge") as an array. +Sum all line counts for totalLines and name the single largest file as largestFile.`, + tools: [classifyComplexity], + addons: [steering({ message: "Ensure every file in the wc output is represented before finalizing." })], + output: s.object({ + files: s.record(s.object({ + lineCount: s.int, + tier: s.enum("trivial", "small", "medium", "large", "huge"), + })), + hotspots: s.array(s.path), + totalLines: s.int, + largestFile: s.path, + }), +}); + +export default sourceComplexityHeatmap; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts new file mode 100644 index 0000000..0cc6746 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts @@ -0,0 +1,14 @@ +import { agent, p, s } from "rig"; +const Diagnosis = s.object({ rootCause: s.string, confidence: s.number }); +// Agent role: diagnose the failing test output. +const diagnose = agent({ model: "typecheck", output: Diagnosis, instructions: "Diagnose the failing test output." }); +// Agent role: write the smallest safe patch for the diagnosis. +const fix = agent({ model: "typecheck", input: s.object({ diagnosis: Diagnosis }), instructions: "Write the smallest safe patch." }); +// Agent role: reproduce and fix the bug using the provided specialists when helpful. +const issueReproducer = agent({ + model: "typecheck", + instructions: p`Reproduce the failing test from ${p.bash("npm test")} and use the specialists when helpful.`, + output: s.object({ diagnosis: Diagnosis, fixSummary: s.string, approved: s.boolean }), + agents: { diagnose, fix }, +}); +export default issueReproducer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts new file mode 100644 index 0000000..8458982 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts @@ -0,0 +1,16 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: run npm audit and produce a simplified grouped vulnerability report with remediation advice. +const npmAuditSimplifierV2 = agent({ + model: "typecheck", + instructions: p`Run ${p.bash("npm audit --json 2>/dev/null || echo '{}'")} to get the vulnerability report. Parse the JSON output: extract each vulnerability's package name and severity (critical, high, moderate, low, info). Group package names by severity level into the vulnerabilitiesByLevel map. Count all vulnerabilities for totalCount. Write a one-sentence recommendation.`, + output: s.object({ + vulnerabilitiesByLevel: s.record(s.array(s.string)), + totalCount: s.number, + recommendation: s.string, + }), + maxTurns: 5, + addons: repair(), +}); + +export default npmAuditSimplifierV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts new file mode 100644 index 0000000..ec415bb --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: inventory all git stashes, listing changed files and estimating staleness. +const gitStashInventoryV2 = agent({ + model: "typecheck", + instructions: p`List all stashes with timestamps: ${p.bash("git stash list --format='%gd|%ci|%s' 2>/dev/null || echo 'no stashes'")}. For the first three stashes show changed files: ${p.bash("git stash show --name-only stash@{0} 2>/dev/null || true")} ${p.bash("git stash show --name-only stash@{1} 2>/dev/null || true")} ${p.bash("git stash show --name-only stash@{2} 2>/dev/null || true")}. Classify staleness by commit date: fresh (< 1 week), aging (1–4 weeks), stale (1–3 months), ancient (> 3 months).`, + output: s.array(s.object({ + stashRef: s.string, + description: s.string, + changedFiles: s.array(s.string), + staleness: s.enum("fresh", "aging", "stale", "ancient"), + })), + maxTurns: 5, + addons: repair(), +}); + +export default gitStashInventoryV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts new file mode 100644 index 0000000..fd3fb92 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const scanInterfaces = defineTool("scanInterfaces", { + description: "Scan a TypeScript file for exported interface names using grep", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { execSync } = await import("node:child_process"); + try { + const result = execSync( + `grep -n "^export interface\\|^interface " "${filePath}" 2>/dev/null || true`, + { encoding: "utf8" } + ); + const names = result + .split("\n") + .filter(Boolean) + .map((line) => { + const m = line.match(/interface\s+(\w+)/); + return m ? m[1] : null; + }) + .filter(Boolean) as string[]; + return { filePath, names }; + } catch { + return { filePath, names: [] }; + } + }, +}); + +// Agent role: find duplicate TypeScript interface names across all source files. +const tsInterfaceConflictCheckerV2 = agent({ + model: "typecheck", + instructions: p`Discover TypeScript source files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -80")}. Use the scanInterfaces tool on each file to collect interface names. Identify interface names declared in more than one file. Classify each conflict as error when names are likely to clash at runtime, warning otherwise. Set hasConflicts to true if any conflicts exist.`, + output: s.object({ + conflicts: s.array(s.object({ + interfaceName: s.string, + files: s.array(s.string), + severity: s.enum("warning", "error"), + })), + hasConflicts: s.boolean, + }), + tools: [scanInterfaces], + maxTurns: 6, + addons: repair(), +}); + +export default tsInterfaceConflictCheckerV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts new file mode 100644 index 0000000..c214063 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool } from "rig"; + +const parseWorktreePorcelain = defineTool("parseWorktreePorcelain", { + description: "Parse the porcelain output of git worktree list into structured entries", + parameters: s.object({ output: s.string }), + handler({ output }) { + const entries: Array<{ path: string; branch?: string; state: string }> = []; + const blocks = output.trim().split("\n\n"); + for (const block of blocks) { + const lines = block.split("\n"); + const pathLine = lines.find((l) => l.startsWith("worktree ")); + const branchLine = lines.find((l) => l.startsWith("branch ")); + const isLocked = lines.some((l) => l.startsWith("locked")); + const isBare = lines.some((l) => l.startsWith("bare")); + const entry: { path: string; branch?: string; state: string } = { + path: pathLine ? pathLine.replace("worktree ", "") : "", + state: isLocked ? "locked" : isBare ? "bare" : "clean", + }; + if (branchLine) entry.branch = branchLine.replace("branch refs/heads/", ""); + if (entry.path) entries.push(entry); + } + return entries; + }, +}); + +// Agent role: map all git worktrees and summarize active vs total count. +const gitWorktreeMapperV2 = agent({ + model: "typecheck", + instructions: p`Get all git worktrees: ${p.bash("git worktree list --porcelain 2>/dev/null || echo ''")}. Use the parseWorktreePorcelain tool to parse the output into structured entries. For each worktree check if there are uncommitted changes (set state to dirty). Count all worktrees for totalCount and non-bare ones for activeCount.`, + output: s.object({ + worktrees: s.array(s.object({ + path: s.string, + branch: s.optional(s.string), + state: s.enum("locked", "bare", "clean", "dirty"), + })), + summary: s.object({ + totalCount: s.int, + activeCount: s.int, + }), + }), + tools: [parseWorktreePorcelain], +}); + +export default gitWorktreeMapperV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts new file mode 100644 index 0000000..d3d7e5b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts @@ -0,0 +1,18 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: audit test file naming conventions and report files that violate the standard pattern. +const testNamingEnforcerV2 = agent({ + model: "typecheck", + instructions: p`Find all test files: ${p.bash("find . \\( -name '*.test.ts' -o -name '*.spec.ts' -o -name '*.test.js' -o -name '*.spec.js' -o -name '*.test.tsx' -o -name '*.spec.tsx' \\) -not -path '*/node_modules/*' | head -80")}. For each file classify the naming convention: correct if the filename follows .test. or .spec., wrong-prefix if the prefix before the dot is unusual, wrong-suffix if the extension or suffix is non-standard, missing-spec if the file appears to be a test but lacks a .test. or .spec. marker. Provide suggestedName only when a correction is needed. Set allConform to true only when every file is classified as correct.`, + output: s.object({ + files: s.record(s.object({ + convention: s.enum("correct", "wrong-prefix", "wrong-suffix", "missing-spec"), + suggestedName: s.optional(s.string), + })), + allConform: s.boolean, + }), + maxTurns: 5, + addons: steering({ message: "Ensure every discovered test file has an entry and allConform reflects all entries." }), +}); + +export default testNamingEnforcerV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts new file mode 100644 index 0000000..de992a3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts @@ -0,0 +1,36 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyDependency = defineTool("classifyDependency", { + description: "Classify a dependency as runtime, dev, or peer based on presence in package.json sections", + parameters: s.object({ + name: s.string, + inDependencies: s.boolean, + inDevDependencies: s.boolean, + inPeerDependencies: s.boolean, + }), + handler({ inDependencies, inDevDependencies, inPeerDependencies }) { + if (inPeerDependencies) return "peer"; + if (inDevDependencies) return "dev"; + if (inDependencies) return "runtime"; + return "dev"; + }, +}); + +// Agent role: extract and classify direct dependencies from package.json and describe the dependency tree shape. +const pkgDependencyGraphV2 = agent({ + model: "typecheck", + instructions: p`Read the project manifest: ${p.read("package.json")}. Get the resolved dependency tree: ${p.bash("npm ls --json --depth=1 2>/dev/null || echo '{}'")}. Use the classifyDependency tool for each direct dependency. List all devDependency names. Classify treeShape as flat (< 5 total deps), shallow (5–20), or deep (> 20). Set depthScore to the total direct dependency count.`, + output: s.object({ + directDeps: s.array(s.object({ + name: s.string, + version: s.string, + type: s.enum("runtime", "dev", "peer"), + })), + devDeps: s.array(s.string), + treeShape: s.enum("flat", "shallow", "deep"), + depthScore: s.number, + }), + tools: [classifyDependency], +}); + +export default pkgDependencyGraphV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts new file mode 100644 index 0000000..634fc89 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: triage the most recent CI test failure and classify its root cause. +const ciFlakeTriager = agent({ + model: "typecheck", + instructions: p`Inspect available CI logs: ${p.bash("cat .github/test-results.log 2>/dev/null || cat test-results.log 2>/dev/null || echo 'no test log found'")}. Also read the CI workflow configuration: ${p.readOptional(".github/workflows/ci.yml", "no ci workflow found")}. Classify the failure type: infrastructure (runner issue, network, timeout on setup), assertion (test logic failed), timeout (test exceeded time limit), or unknown. Estimate confidence. List the names of affected tests if identifiable. Provide a concrete one-sentence retry advice.`, + output: s.object({ + failureClass: s.enum("infrastructure", "assertion", "timeout", "unknown"), + confidence: s.enum("high", "medium", "low"), + retryAdvice: s.string, + affectedTests: s.array(s.string), + }), + maxTurns: 4, + addons: repair(), +}); + +export default ciFlakeTriager; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts new file mode 100644 index 0000000..d7648c4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts @@ -0,0 +1,20 @@ +import { agent, p, s } from "rig"; + +// Agent role: compare two config files, identify drifted settings, and write a corrected patch. +const configDriftReconciler = agent({ + model: "typecheck", + instructions: p`Read the baseline ESLint config: ${p.readOptional(".eslintrc.json", "{}")}. Read the active config: ${p.readOptional(".eslintrc.js", "module.exports = {}")}. Also check for any local overrides: ${p.bash("find . -maxdepth 2 -name '.eslintrc*' -not -path '*/node_modules/*' 2>/dev/null || true")}. Identify keys that differ between the baseline and active configs. Write a normalized patch to ${p.write("config-patch.json", "PATCH_CONTENT")} showing the corrected settings. Report each drifted key with its baseline and actual value. Set normalized to true if you were able to resolve all differences.`, + output: s.object({ + changedKeys: s.record(s.object({ + baseline: s.unknown, + actual: s.unknown, + })), + summary: s.object({ + totalDrifted: s.int, + totalChecked: s.int, + normalized: s.boolean, + }), + }), +}); + +export default configDriftReconciler; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts new file mode 100644 index 0000000..9df61e3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts @@ -0,0 +1,33 @@ +import { agent, p, s, defineTool, repair, steering } from "rig"; + +const lookupTicketMetadata = defineTool("lookupTicketMetadata", { + description: "Extract ticket references like #123 or PROJ-456 from text", + parameters: s.object({ text: s.string }), + handler({ text }) { + const githubRefs = [...text.matchAll(/#(\d+)/g)].map((m) => `#${m[1]}`); + const jiraRefs = [...text.matchAll(/\b([A-Z]+-\d+)\b/g)].map((m) => m[1]); + return { githubRefs, jiraRefs, all: [...githubRefs, ...jiraRefs] }; + }, +}); + +// Agent role: enrich raw release notes with structured sections, a risk label, and missing reference warnings. +const releaseNoteEnricher = agent({ + model: "typecheck", + input: s.object({ + rawNotes: s.string, + }), + instructions: p`You have raw release notes in the input. Use the lookupTicketMetadata tool to extract any ticket references from the text. Group the notes into logical sections (e.g., Features, Bug Fixes, Breaking Changes, Chores). Assign a riskLabel of low, medium, high, or critical based on whether there are breaking changes or critical fixes. List any ticket references that appear in the notes but could not be resolved or verified.`, + output: s.object({ + sections: s.array(s.object({ + heading: s.string, + items: s.array(s.string), + })), + riskLabel: s.enum("low", "medium", "high", "critical"), + missingReferences: s.array(s.string), + }), + tools: [lookupTicketMetadata], + maxTurns: 5, + addons: [steering(), repair()], +}); + +export default releaseNoteEnricher; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts new file mode 100644 index 0000000..03860c0 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts @@ -0,0 +1,31 @@ +import { agent, p, s } from "rig"; + +// Agent role: extract API names mentioned in the documentation. +const apiExtractor = agent({ + name: "apiExtractor", + model: "typecheck", + instructions: p`Read the documentation: ${p.read("README.md")}. Extract every API name, function signature, and method reference mentioned in the document. Return a flat list of unique API identifiers.`, + output: s.array(s.string), +}); + +// Agent role: rewrite documentation prose for clarity and conciseness. +const proseCleanup = agent({ + name: "proseCleanup", + model: "typecheck", + instructions: p`Read the documentation: ${p.read("README.md")}. Rewrite the prose to be clearer, more concise, and better structured. Return only the improved text.`, + output: s.string, +}); + +// Agent role: coordinate docs refactoring by extracting APIs and cleaning prose, then writing the result. +const docsRefactorCoordinator = agent({ + model: "typecheck", + instructions: p`Delegate API extraction and prose cleanup to the named subagents. Merge their results: the apiExtractor returns the list of API names, and proseCleanup returns rewritten prose. Combine into a final output and write the refactored content to ${p.write("docs/refactored.md", "REFACTORED_CONTENT")}. Count the changes made to the prose.`, + output: s.object({ + extractedApis: s.array(s.string), + changesApplied: s.int, + outputPath: s.path, + }), + agents: { apiExtractor, proseCleanup }, +}); + +export default docsRefactorCoordinator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts new file mode 100644 index 0000000..b1c373f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; +// Agent role: extract a clear reproduction from the issue. +const reproducer = agent({ + model: "typecheck", + output: s.object({ + steps: s.array(s.string), + expected: s.string, + actual: s.string, + missingInfo: s.array(s.string) + }), + instructions: `Extract a clear reproduction from the issue.`, +}); + +export default reproducer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts new file mode 100644 index 0000000..f7f8f69 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts @@ -0,0 +1,39 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const classifyFile = defineTool("classifyFile", { + description: "Classify a test filename against project naming conventions", + parameters: s.object({ + filename: s.string, + }), + handler({ filename }) { + const base = filename.split("/").pop() ?? filename; + if (/\.(test|spec)\.(ts|js|tsx|jsx)$/.test(base)) { + return { convention: "correct" as const, suggestedName: null }; + } + if (/\.(ts|js|tsx|jsx)$/.test(base) && /test|spec/i.test(base)) { + return { convention: "wrong-suffix" as const, suggestedName: base.replace(/test|spec/i, "") + ".test." + base.split(".").pop() }; + } + if (/Test\.(ts|js|tsx|jsx)$/.test(base)) { + return { convention: "wrong-suffix" as const, suggestedName: base.replace(/Test\./, ".test.") }; + } + return { convention: "missing-spec" as const, suggestedName: base.replace(/\.(ts|js|tsx|jsx)$/, ".test.$1") }; + }, +}); + +// Agent role: scan test files and report which follow the .test.ts / .spec.ts naming convention. +const testFileNamingEnforcer = agent({ + model: "typecheck", + instructions: p`Find all test files: ${p.bash("find . \\( -name '*.test.ts' -o -name '*.spec.ts' -o -name '*.test.js' -o -name '*.spec.js' -o -name '*Test.ts' -o -name '*Test.js' \\) -not -path '*/node_modules/*' | head -60")}. Use the classifyFile tool for each file path. Build a record keyed by file path with the convention classification and optional suggestedName. Set allConform to true only when every entry is classified as correct.`, + output: s.object({ + files: s.record(s.object({ + convention: s.enum("correct", "wrong-prefix", "wrong-suffix", "missing-spec"), + suggestedName: s.optional(s.string), + })), + allConform: s.boolean, + }), + tools: [classifyFile], + maxTurns: 5, + addons: repair(), +}); + +export default testFileNamingEnforcer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts new file mode 100644 index 0000000..40698dc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts @@ -0,0 +1,36 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyDependency = defineTool("classifyDependency", { + description: "Classify a dependency as runtime, dev, or peer given its presence in package.json sections", + parameters: s.object({ + name: s.string, + inDependencies: s.boolean, + inDevDependencies: s.boolean, + inPeerDependencies: s.boolean, + }), + handler({ inDependencies, inDevDependencies, inPeerDependencies }) { + if (inPeerDependencies) return "peer"; + if (inDevDependencies) return "dev"; + if (inDependencies) return "runtime"; + return "dev"; + }, +}); + +// Agent role: extract and classify direct dependencies from package.json and describe the dependency tree shape. +const pkgDependencyGraphExtractor = agent({ + model: "typecheck", + instructions: p`Read the project manifest: ${p.read("package.json")}. Get the resolved dependency tree: ${p.bash("npm ls --json --depth=1 2>/dev/null || echo '{}'")}. Use the classifyDependency tool for each direct dependency found in the manifest. List all devDependency names as plain strings. Classify treeShape as flat (fewer than 5 total direct deps), shallow (5–20), or deep (more than 20). Set depthScore to the total direct dependency count across all sections.`, + output: s.object({ + directDeps: s.array(s.object({ + name: s.string, + version: s.string, + type: s.enum("runtime", "dev", "peer"), + })), + devDeps: s.array(s.string), + treeShape: s.enum("flat", "shallow", "deep"), + depthScore: s.number, + }), + tools: [classifyDependency], +}); + +export default pkgDependencyGraphExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts new file mode 100644 index 0000000..b924842 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts @@ -0,0 +1,40 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const countUsages = defineTool("countUsages", { + description: "Count how many times a symbol appears in TypeScript source files", + parameters: s.object({ symbolName: s.string }), + async handler({ symbolName }) { + const { execSync } = await import("node:child_process"); + try { + const escaped = symbolName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const out = execSync( + `grep -rn "${escaped}" --include="*.ts" . | grep -v node_modules | grep -v ".d.ts" | wc -l`, + { encoding: "utf8" } + ); + const count = parseInt(out.trim(), 10); + const lastFile = execSync( + `grep -rln "${escaped}" --include="*.ts" . | grep -v node_modules | tail -1`, + { encoding: "utf8" } + ).trim() || null; + return { count, lastFile }; + } catch { + return { count: 0, lastFile: null }; + } + }, +}); + +// Agent role: scan TypeScript exports and measure how often each exported symbol is imported or used. +const tsExportUsageCounter = agent({ + model: "typecheck", + instructions: p`Find exported TypeScript symbols: ${p.bash("grep -rn 'export ' --include='*.ts' . | grep -v node_modules | grep -v '.d.ts' | grep -E 'export (const|function|class|type|interface|enum) ' | head -60")}. For each exported symbol name, use the countUsages tool to get how many times it appears in the codebase. Assign coverageLevel: none (0 usages), low (1–2), medium (3–9), or high (≥10). Return a record keyed by symbol name.`, + output: s.record(s.object({ + usageCount: s.int, + coverageLevel: s.enum("none", "low", "medium", "high"), + lastFile: s.optional(s.string), + })), + tools: [countUsages], + maxTurns: 6, + addons: repair(), +}); + +export default tsExportUsageCounter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts new file mode 100644 index 0000000..599beb7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: track file renames in git history and produce a structured rename log. +const gitRenameTracker = agent({ + model: "typecheck", + instructions: p`Retrieve git file rename history: ${p.bash("git log --diff-filter=R --summary --pretty=format:'%H %ci' 2>/dev/null | head -80 || echo 'no renames'")}. Parse each rename entry — lines starting with "rename from/to" — and associate each pair with the commit hash and ISO date from the preceding format line. Return an array sorted newest first, with at most 20 entries.`, + output: s.array(s.object({ + hash: s.string, + date: s.string, + oldPath: s.string, + newPath: s.string, + })), + maxTurns: 2, + addons: repair(), +}); + +export default gitRenameTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts new file mode 100644 index 0000000..d13b394 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool } from "rig"; + +const validateYaml = defineTool("validateYaml", { + description: "Validate a YAML file for structural issues, especially GitHub Actions required keys", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const text = await readFile(filePath, "utf8"); + const lines = text.split("\n"); + const lineCount = lines.length; + const issues: string[] = []; + const topKeys = lines.filter((l: string) => /^[a-zA-Z]/.test(l)).map((l: string) => l.split(":")[0].trim()); + const isGhAction = topKeys.includes("on") || topKeys.includes("jobs"); + if (isGhAction) { + if (!topKeys.includes("name")) issues.push("missing top-level 'name' key"); + if (!topKeys.includes("on")) issues.push("missing top-level 'on' trigger"); + if (!topKeys.includes("jobs")) issues.push("missing top-level 'jobs' key"); + } + const status = issues.length === 0 ? "pass" : issues.length <= 1 ? "warn" : "fail"; + return { issues, lineCount, status }; + } catch (e) { + return { issues: [`read error: ${e}`], lineCount: 0, status: "fail" }; + } + }, +}); + +// Agent role: find YAML files in the workspace and validate each for structural correctness. +const yamlLintChecker = agent({ + model: "typecheck", + instructions: p`Find all YAML files in this project: ${p.bash("find . \\( -name '*.yml' -o -name '*.yaml' \\) -not -path '*/node_modules/*' | head -30")}. Use the validateYaml tool on each file path. Return a record keyed by filename with issues, lineCount, and status for each file.`, + output: s.record(s.object({ + issues: s.array(s.string), + lineCount: s.int, + status: s.enum("pass", "warn", "fail"), + })), + tools: [validateYaml], + maxTurns: 5, +}); + +export default yamlLintChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts new file mode 100644 index 0000000..7c816a9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts @@ -0,0 +1,30 @@ +import { agent, p, s } from "rig"; + +// Agent role: extract TypeScript function names and approximate line counts from source files. +const extractor = agent({ + name: "extractor", + model: "typecheck", + instructions: p`Scan TypeScript files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.d.ts' | head -20")}. For each file, find function and arrow-function definitions: ${p.bash("grep -rn --include='*.ts' -E '^(export )?(async )?function |const [a-zA-Z]+ = (async )?(\\([^)]*\\)|[a-zA-Z]+) =>' . | grep -v node_modules | head -80")}. Estimate line count per function from surrounding context. Return a record mapping functionName to approximate lineCount.`, + output: s.record(s.int), +}); + +// Agent role: rate each TypeScript function for complexity and produce an aggregate summary. +const twoPhaseComplexityReview = agent({ + name: "twoPhaseComplexityReview", + model: "typecheck", + instructions: p`Delegate to the extractor subagent to get a record of function names and line counts. Classify each function: simple (<10 lines), moderate (10–29 lines), complex (30–59 lines), or critical (≥60 lines). Count functions rated complex or critical for summary.complexCount.`, + output: s.object({ + functions: s.record(s.object({ + lineCount: s.int, + complexity: s.enum("simple", "moderate", "complex", "critical"), + })), + summary: s.object({ + totalFunctions: s.int, + complexCount: s.int, + }), + }), + agents: { extractor }, + maxTurns: 6, +}); + +export default twoPhaseComplexityReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts new file mode 100644 index 0000000..c335730 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseLayer = defineTool("parseLayer", { + description: "Classify a Dockerfile instruction for cache-friendliness and weight", + parameters: s.object({ + instruction: s.string, + args: s.string, + }), + handler({ instruction, args }) { + const inst = instruction.toUpperCase(); + const isPackageFile = /package\.json|requirements\.txt|Pipfile|go\.mod|Cargo\.toml/.test(args); + const isHeavy = (inst === "RUN") && /apt-get|npm install|pip install|yarn|apk add/.test(args); + const cacheable = (inst === "COPY" || inst === "ADD") && isPackageFile; + let tip: string | null = null; + if (inst === "RUN" && isHeavy) tip = "Combine adjacent RUN commands to reduce layers"; + if (inst === "COPY" && !cacheable) tip = "Copy only dependency manifests first to improve cache"; + return { instruction: inst, cacheable, isHeavy, tip }; + }, +}); + +// Agent role: analyze Dockerfile layers for cache efficiency and suggest optimizations. +const dockerfileLayerAnalyzer = agent({ + model: "typecheck", + instructions: p`Read the Dockerfile: ${p.readOptional("Dockerfile", "# no Dockerfile found")}. Parse each instruction line (FROM, RUN, COPY, ADD, ENV, EXPOSE, CMD, ENTRYPOINT, etc.). Use the parseLayer tool for each instruction with its arguments. Count total layers. Set optimizable to true if any layer has isHeavy or a non-null tip. Collect all non-null tips into suggestions.`, + output: s.object({ + layers: s.array(s.object({ + instruction: s.string, + args: s.string, + cacheable: s.boolean, + isHeavy: s.boolean, + tip: s.optional(s.string), + })), + totalLayers: s.int, + optimizable: s.boolean, + suggestions: s.array(s.string), + }), + tools: [parseLayer], + addons: repair(), +}); + +export default dockerfileLayerAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts new file mode 100644 index 0000000..ed3ee3c --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts @@ -0,0 +1,38 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const classifyWorktree = defineTool("classifyWorktree", { + description: "Classify a git worktree's status based on its path, branch, and state flags", + parameters: s.object({ + path: s.string, + branch: s.optional(s.string), + isBare: s.boolean, + isDetached: s.boolean, + }), + handler({ branch, isBare, isDetached }) { + if (isBare) return "bare"; + if (isDetached) return "detached"; + if (!branch) return "detached"; + return "clean"; + }, +}); + +// Agent role: inventory git worktrees and report their cleanliness status. +const gitWorktreeStatus = agent({ + model: "typecheck", + instructions: p`List all git worktrees: ${p.bash("git worktree list --porcelain 2>/dev/null || echo 'worktree .\nHEAD unknown\nbranch refs/heads/main'")}. Also check working tree status: ${p.bash("git status --short 2>/dev/null | head -20")}. Use the classifyWorktree tool for each worktree entry. If the current worktree has modified files, override its status to dirty. Set isMain: true for the first (primary) worktree. Set allClean to true only when every worktree has status clean.`, + output: s.object({ + worktrees: s.array(s.object({ + path: s.path, + branch: s.optional(s.string), + status: s.enum("clean", "dirty", "bare", "detached"), + isMain: s.boolean, + })), + totalWorktrees: s.int, + allClean: s.boolean, + }), + tools: [classifyWorktree], + maxTurns: 4, + addons: repair(), +}); + +export default gitWorktreeStatus; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts new file mode 100644 index 0000000..bd069db --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts @@ -0,0 +1,52 @@ +import { agent, p, s, defineTool, steering, repair } from "rig"; + +const extractInterface = defineTool("extractInterface", { + description: "Extract field names from a TypeScript interface declaration in a file", + parameters: s.object({ + filePath: s.string, + interfaceName: s.string, + }), + async handler({ filePath, interfaceName }) { + const { readFile } = await import("node:fs/promises"); + try { + const text = await readFile(filePath, "utf8"); + const pattern = new RegExp(`interface\\s+${interfaceName}\\s*\\{([^}]*)\\}`, "s"); + const match = text.match(pattern); + if (!match) return { fields: [] }; + const body = match[1]; + const fields = body + .split("\n") + .map((l: string) => l.trim()) + .filter((l: string) => l && !l.startsWith("//") && !l.startsWith("*")) + .map((l: string) => l.split(":")[0].replace(/[?;]/g, "").trim()) + .filter(Boolean); + return { fields }; + } catch { + return { fields: [] }; + } + }, +}); + +// Agent role: detect TypeScript interfaces with the same name across multiple source files. +const tsInterfaceConflictChecker = agent({ + model: "typecheck", + instructions: p`Find TypeScript interface declarations: ${p.bash("grep -rn 'interface ' --include='*.ts' . | grep -v node_modules | grep -v '.d.ts' | head -60")}. Use the extractInterface tool to get fields for each interface found. Detect interface names that appear in more than one file — those are conflicts. Report them with their file list and conflicting field names. Set conflictCount to the number of conflicting interface names.`, + output: s.object({ + interfaces: s.record(s.object({ + fields: s.array(s.string), + file: s.path, + hasConflict: s.boolean, + })), + conflicts: s.array(s.object({ + name: s.string, + files: s.array(s.path), + conflictingFields: s.array(s.string), + })), + conflictCount: s.int, + }), + tools: [extractInterface], + maxTurns: 6, + addons: [steering(), repair()], +}); + +export default tsInterfaceConflictChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts new file mode 100644 index 0000000..466dea2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts @@ -0,0 +1,39 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const classifyVuln = defineTool("classifyVuln", { + description: "Classify a vulnerability as direct or transitive and produce a remediation recommendation", + parameters: s.object({ + name: s.string, + severity: s.string, + isDirect: s.boolean, + }), + handler({ name, severity, isDirect }) { + const rec = isDirect + ? `Update ${name} directly in package.json` + : `Update the top-level package that depends on ${name}`; + return { recommendation: rec + (severity === "critical" || severity === "high" ? " immediately" : " when convenient") }; + }, +}); + +// Agent role: run npm audit and produce a simplified, actionable vulnerability report. +const npmAuditSimplifier = agent({ + model: "typecheck", + instructions: p`Run npm audit and capture results: ${p.bash("npm audit --json 2>/dev/null || echo '{\"vulnerabilities\":{}}'") }. Parse the JSON output. For each vulnerability entry, extract name and severity, determine if it is direct (no via chain or via is the package itself), and use the classifyVuln tool to get a recommendation. Count criticalCount and highCount separately. Write a one-sentence summary. Set action to urgent if criticalCount > 0, scheduled if highCount > 0, monitor if there are any other vulns, or none if clean.`, + output: s.object({ + vulnerabilities: s.array(s.object({ + name: s.string, + severity: s.enum("critical", "high", "moderate", "low", "info"), + isDirect: s.boolean, + recommendation: s.string, + })), + criticalCount: s.int, + highCount: s.int, + summary: s.string, + action: s.enum("urgent", "scheduled", "monitor", "none"), + }), + tools: [classifyVuln], + maxTurns: 5, + addons: repair(), +}); + +export default npmAuditSimplifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts new file mode 100644 index 0000000..8ebb4c3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: diagnose the CI log. Prefer the first real failure over cascading errors. +const ciDiagnosis = agent({ + model: "typecheck", + output: s.object({ + failure: s.string, + likelyCause: s.string, + commandsToTry: s.array(s.string) + }), + instructions: `Diagnose the CI log. Prefer the first real failure over cascading errors.`, +}); +export default ciDiagnosis; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts new file mode 100644 index 0000000..9a885d5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts @@ -0,0 +1,21 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: track file renames in git history and produce a structured rename log. +const gitRenameTrackerV2 = agent({ + model: "typecheck", + instructions: p`Retrieve git file rename history: ${p.bash("git log --diff-filter=R --summary --pretty=format:'%h %ai' | head -60 2>/dev/null || echo 'No renames found'")}. Parse each rename entry (lines matching "rename ... => ...") and associate it with the nearest commit hash and date. Return all renames sorted newest first, the total count, and the path that appears most often as either old or new.`, + output: s.object({ + renames: s.array(s.object({ + hash: s.string, + date: s.string, + oldPath: s.path, + newPath: s.path, + })), + totalRenames: s.int, + mostRenamedFile: s.optional(s.path), + }), + maxTurns: 4, + addons: repair(), +}); + +export default gitRenameTrackerV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts new file mode 100644 index 0000000..e2640c1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool } from "rig"; +import { readFileSync } from "node:fs"; + +const validateYaml = defineTool("validateYaml", { + description: "Validate a YAML file for structural issues and required top-level keys", + parameters: s.object({ filePath: s.path }), + handler({ filePath }) { + let content: string; + try { + content = readFileSync(filePath, "utf-8"); + } catch { + return { issues: ["File not readable"], lineCount: 0, status: "fail" as const }; + } + const issues: string[] = []; + const lines = content.split("\n"); + const lineCount = lines.length; + const isWorkflow = filePath.includes(".github/workflows"); + if (isWorkflow) { + if (!content.includes("name:")) issues.push("Missing 'name' key"); + if (!content.includes("on:") && !content.includes('"on":')) issues.push("Missing 'on' trigger"); + if (!content.includes("jobs:")) issues.push("Missing 'jobs' key"); + } + if (content.includes("\t")) issues.push("Contains tab characters (use spaces in YAML)"); + const status = issues.length === 0 ? "pass" : issues.some((i: string) => i.startsWith("Missing")) ? "fail" : "warn"; + return { issues, lineCount, status } as { issues: string[]; lineCount: number; status: "pass" | "warn" | "fail" }; + }, +}); + +// Agent role: lint YAML files and report structural issues per file. +const yamlWorkflowLinter = agent({ + model: "typecheck", + instructions: p`Find YAML files: ${p.bash("find . \\( -name '*.yml' -o -name '*.yaml' \\) | grep -v node_modules | grep -v .git | head -20")}. For each file path, call validateYaml and collect the result. Return a record keyed by file path.`, + output: s.record(s.object({ + issues: s.array(s.string), + lineCount: s.int, + status: s.enum("pass", "warn", "fail"), + })), + tools: [validateYaml], +}); + +export default yamlWorkflowLinter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts new file mode 100644 index 0000000..3d5e13f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts @@ -0,0 +1,33 @@ +import { agent, p, s } from "rig"; + +// Agent role: extract TypeScript function names and approximate line counts from source files. +const extractor = agent({ + name: "extractor", + model: "typecheck", + instructions: p`Scan TypeScript source files for function definitions: ${p.bash("grep -rn --include='*.ts' 'function \\|=> {\\|async ' . | grep -v node_modules | grep -v '.test.' | head -60 2>/dev/null || echo 'no ts files'")}. For each distinct function name found, estimate its line count from context. Return an array of objects with functionName, lineCount, and file.`, + output: s.array(s.object({ + functionName: s.string, + lineCount: s.int, + file: s.path, + })), +}); + +// Agent role: rate each extracted function for complexity and produce a summary. +const reviewer = agent({ + name: "reviewer", + model: "typecheck", + instructions: p`You will receive a list of functions with their line counts. Classify each as: simple (<10 lines), moderate (10-29), complex (30-59), or critical (≥60). Return one rating object per function plus a summary with total and complex+critical count.`, + output: s.object({ + analysis: s.record(s.object({ + lineCount: s.int, + complexity: s.enum("simple", "moderate", "complex", "critical"), + })), + summary: s.object({ + totalFunctions: s.int, + complexCount: s.int, + }), + }), + agents: { extractor }, +}); + +export default reviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts new file mode 100644 index 0000000..e53146d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts @@ -0,0 +1,31 @@ +import { agent, defineTool, p, s } from "rig"; + +const detectExports = defineTool("detectExports", { + description: "Detect export declarations in a TypeScript source file", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf-8"); + const exports = (content.match(/^export\s+(default\s+)?(function|class|const|let|var|type|interface|enum)\s+\w+/gm) ?? []); + return { filePath, exports, exportCount: exports.length }; + } catch { + return { filePath, exports: [], exportCount: 0 }; + } + }, +}); + +// Agent role: generate barrel index.ts content for TypeScript source directories. +const barrelFileGenerator = agent({ + model: "typecheck", + instructions: p`Find TypeScript source files: ${p.bash("find src -name '*.ts' ! -name 'index.ts' ! -name '*.test.ts' ! -name '*.spec.ts' 2>/dev/null | head -30 || find . -name '*.ts' ! -name 'index.ts' ! -name '*.test.ts' ! -path '*/node_modules/*' | head -20")}. Use detectExports for each file. Tally filesScanned, barrelFilesWritten (directories that have at least one export), exportCount (total exports found), and directories (unique directory paths). Return only the declared output.`, + tools: [detectExports], + output: s.object({ + filesScanned: s.int, + barrelFilesWritten: s.int, + exportCount: s.int, + directories: s.array(s.string), + }), +}); + +export default barrelFileGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts new file mode 100644 index 0000000..3f41ce4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts @@ -0,0 +1,30 @@ +import { agent, defineTool, p, s } from "rig"; + +const classifyHook = defineTool("classifyHook", { + description: "Classify a git hook by inspecting its content", + parameters: s.object({ name: s.string, content: s.string }), + handler({ content }) { + if (!content || content.trim() === "missing") { + return { status: "missing" as const, isAsync: false, summary: "Hook file not present" }; + } + const isSample = content.includes("sample") || content.trim() === "#!/bin/sh" || content.trim() === "#!/bin/bash"; + const isAsync = content.includes(" &") || content.includes("async "); + const status = isSample ? "stub" : "active"; + const summary = isSample ? "Sample/placeholder hook — not active" : `Active hook (${content.split("\n").length} lines)`; + return { status, isAsync, summary } as { status: "active" | "stub" | "missing"; isAsync: boolean; summary: string }; + }, +}); + +// Agent role: inventory git hooks and classify each as active, stub, or missing. +const gitHookInventory = agent({ + model: "typecheck", + instructions: p`List and inspect git hooks: ${p.bash("ls .git/hooks/ 2>/dev/null || echo 'no hooks directory'")}. ${p.bash("for f in pre-commit commit-msg pre-push post-commit prepare-commit-msg pre-rebase; do echo \"=== $f ===\"; cat \".git/hooks/$f\" 2>/dev/null || echo 'missing'; done")}. Use classifyHook for each hook name with its content. Return a record keyed by hook name.`, + tools: [classifyHook], + output: s.record(s.object({ + summary: s.string, + status: s.enum("active", "stub", "missing"), + isAsync: s.boolean, + })), +}); + +export default gitHookInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts new file mode 100644 index 0000000..4dca604 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts @@ -0,0 +1,28 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: generate a PR review checklist from the current git diff. +const prReviewChecklist = agent({ + model: "typecheck", + maxTurns: 6, + addons: repair(), + instructions: p`Generate a PR review checklist based on these changes. + +Changed files: +${p.bash("git diff --stat HEAD~1 2>/dev/null || git diff --stat HEAD 2>/dev/null || echo 'no diff available'")} + +Diff: +${p.bash("git diff HEAD~1 -- . 2>/dev/null | head -300 || git diff HEAD -- . 2>/dev/null | head -300 || echo 'no diff'")} + +For each concern, produce a checklist item with a clear description, category (security/performance/correctness/style/testing), and priority (must/should/nice-to-have). List changed files and indicate if the PR is ready for review.`, + output: s.object({ + checklist: s.array(s.object({ + item: s.string, + category: s.enum("security", "performance", "correctness", "style", "testing"), + priority: s.enum("must", "should", "nice-to-have"), + })), + changedFiles: s.array(s.path), + ready: s.boolean, + }), +}); + +export default prReviewChecklist; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts new file mode 100644 index 0000000..ae1ec1e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s } from "rig"; + +const countAstNodes = defineTool("countAstNodes", { + description: "Count syntax node patterns in a JavaScript/TypeScript file using regex heuristics", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf-8"); + const functionCount = (content.match(/\bfunction\s+\w+\s*\(/g) ?? []).length; + const arrowFunctionCount = (content.match(/=>\s*[{(]/g) ?? []).length; + const classCount = (content.match(/\bclass\s+\w+/g) ?? []).length; + const importCount = (content.match(/^\s*import\s+/gm) ?? []).length; + const exportCount = (content.match(/^\s*export\s+/gm) ?? []).length; + return { filePath, functionCount, arrowFunctionCount, classCount, importCount, exportCount }; + } catch { + return { filePath, functionCount: 0, arrowFunctionCount: 0, classCount: 0, importCount: 0, exportCount: 0 }; + } + }, +}); + +// Agent role: count AST-like syntax node patterns in JavaScript files. +const jsAstNodeCounter = agent({ + model: "typecheck", + instructions: p`Find JavaScript files: ${p.bash("find . -name '*.js' ! -path '*/node_modules/*' ! -path '*/.git/*' | head -10 2>/dev/null || echo 'no js files found'")}. For each file, call countAstNodes and collect results. Tally totalFunctions across all files and identify mostComplexFile (highest combined function + arrowFunction count). Return only the declared output.`, + tools: [countAstNodes], + output: s.object({ + files: s.record(s.object({ + functionCount: s.int, + arrowFunctionCount: s.int, + classCount: s.int, + importCount: s.int, + exportCount: s.int, + })), + totalFunctions: s.int, + mostComplexFile: s.optional(s.path), + }), +}); + +export default jsAstNodeCounter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts new file mode 100644 index 0000000..8d3476e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts @@ -0,0 +1,44 @@ +import { agent, defineTool, p, s, steering } from "rig"; + +const classifyTagAge = defineTool("classifyTagAge", { + description: "Classify a tag's age based on its ISO date string", + parameters: s.object({ dateStr: s.string }), + handler({ dateStr }) { + const date = new Date(dateStr); + const now = new Date(); + const daysDiff = (now.getTime() - date.getTime()) / (1000 * 60 * 60 * 24); + let ageClass: "recent" | "stable" | "old" | "ancient"; + if (daysDiff < 30) ageClass = "recent"; + else if (daysDiff < 180) ageClass = "stable"; + else if (daysDiff < 730) ageClass = "old"; + else ageClass = "ancient"; + return { ageClass }; + }, +}); + +// Agent role: map git tags to their commit dates and classify their age. +const gitTagDateMapper = agent({ + model: "typecheck", + addons: steering(), + instructions: p`Inspect git tags and their dates. + +Tags: +${p.bash("git tag -l --sort=-version:refname | head -20 2>/dev/null || echo 'no tags'")} + +Tag log: +${p.bash("git log --tags --simplify-by-decoration --pretty='%D|%ai|%s' | head -30 2>/dev/null || echo 'no tag log'")} + +For each tag, extract its ISO date and call classifyTagAge. Return a record keyed by tag name with date, subject, and ageClass. Include totalTags and latestTag.`, + tools: [classifyTagAge], + output: s.object({ + tags: s.record(s.object({ + date: s.string, + subject: s.string, + ageClass: s.enum("recent", "stable", "old", "ancient"), + })), + totalTags: s.int, + latestTag: s.optional(s.string), + }), +}); + +export default gitTagDateMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts new file mode 100644 index 0000000..7fdf086 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts @@ -0,0 +1,49 @@ +import { agent, defineTool, p, s, steering } from "rig"; + +const buildImportGraph = defineTool("buildImportGraph", { + description: "Build an import graph from TypeScript files in a directory by parsing relative import statements", + parameters: s.object({ directory: s.path }), + async handler({ directory }) { + const { readdir, readFile } = await import("node:fs/promises"); + const { join } = await import("node:path"); + const graph: Record = {}; + try { + const entries = await readdir(directory, { recursive: true, encoding: "utf-8" }); + const tsFiles = entries.filter((f: string) => f.endsWith(".ts") && !f.endsWith(".test.ts") && !f.endsWith(".d.ts")); + for (const file of tsFiles.slice(0, 20)) { + const fullPath = join(directory, file); + try { + const content = await readFile(fullPath, "utf-8"); + const imports = [...content.matchAll(/from\s+['"](\.[^'"]+)['"]/g)].map((m: RegExpMatchArray) => m[1]); + graph[file] = imports; + } catch { + graph[file] = []; + } + } + } catch { + // directory not found + } + return { graph }; + }, +}); + +// Agent role: detect circular imports in TypeScript source files. +const circularImportDetector = agent({ + model: "typecheck", + addons: steering(), + instructions: p`Detect circular imports in TypeScript files. + +Import overview: +${p.bash("grep -rn \"from '\\./\\|from \\\"\\./\" src/ --include='*.ts' 2>/dev/null | head -40 || grep -rn \"from '\\./\" . --include='*.ts' | grep -v node_modules | head -40 || echo 'no relative imports found'")} + +Call buildImportGraph on the source directory (try "src" first, then "."). Analyse the graph to find cycles (A imports B imports A, etc.). Return cycles as arrays of file paths, hasCycles, totalFiles, and cycleCount.`, + tools: [buildImportGraph], + output: s.object({ + cycles: s.array(s.array(s.string)), + hasCycles: s.boolean, + totalFiles: s.int, + cycleCount: s.int, + }), +}); + +export default circularImportDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts new file mode 100644 index 0000000..4395414 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts @@ -0,0 +1,46 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const scoreField = defineTool("scoreField", { + description: "Score a package.json field for presence, completeness, and quality", + parameters: s.object({ + fieldName: s.string, + value: s.unknown, + importance: s.enum("required", "recommended", "optional"), + }), + handler({ fieldName, value, importance }) { + const present = value !== undefined && value !== null && value !== ""; + const nonEmpty = present && (typeof value !== "object" || Object.keys(value as object).length > 0); + const score = !present ? 0 : !nonEmpty ? 30 : importance === "required" ? 100 : importance === "recommended" ? 80 : 60; + const note = !present + ? `Missing ${importance} field` + : !nonEmpty + ? `Field '${fieldName}' is empty` + : `Field '${fieldName}' is present`; + return { present, score, note }; + }, +}); + +// Agent role: score a package.json manifest for completeness and produce a grade. +const packageJsonScorer = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Score this package.json for completeness: ${p.read("package.json")}. Use scoreField for each of these fields: +- required: name, version, description, main +- recommended: license, author, repository, keywords, bugs, homepage +- optional: engines, files, exports +Compute an overall score (0-100) as weighted average and assign a grade: A(90+), B(75+), C(60+), D(40+), F(<40). List missingRequired and missingRecommended fields.`, + tools: [scoreField], + output: s.object({ + score: s.int, + grade: s.enum("A", "B", "C", "D", "F"), + missingRequired: s.array(s.string), + missingRecommended: s.array(s.string), + details: s.record(s.object({ + present: s.boolean, + score: s.int, + note: s.string, + })), + }), +}); + +export default packageJsonScorer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts new file mode 100644 index 0000000..ce396d5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: normalize the config into a JSON-compatible object. +const normalize = agent({ + model: "typecheck", + output: s.object({ + normalized: s.unknown, + warnings: s.array(s.string) + }), + instructions: `Normalize the config into a JSON-compatible object.`, +}); +export default normalize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts new file mode 100644 index 0000000..83677d1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts @@ -0,0 +1,25 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: track file renames in recent git history and return a structured report. +const gitRenameTracker = agent({ + model: "typecheck", + instructions: p`Analyze the following git log output for file renames: + +${p.bash("git log --diff-filter=R --summary --oneline -50")} + +Parse each rename line (format: "rename old/path => new/path (similarity%)"). +Extract the commit hash from the preceding commit line, and the old and new paths. +Return the structured list of renames with totals.`, + output: s.object({ + renames: s.array(s.object({ + hash: s.string, + oldPath: s.path, + newPath: s.path, + })), + totalRenames: s.int, + mostRenamed: s.optional(s.path), + }), + addons: [repair()], +}); + +export default gitRenameTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts new file mode 100644 index 0000000..a3712e6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const validateWorkflow = defineTool("validateWorkflow", { + description: "Validate a GitHub Actions workflow YAML file for required top-level keys.", + parameters: { filePath: s.path }, + handler: async ({ filePath }) => { + const content = await readFile(filePath, "utf8"); + const hasName = /^name:/m.test(content); + const hasOn = /^on:/m.test(content); + const hasJobs = /^jobs:/m.test(content); + const issues: string[] = []; + if (!hasName) issues.push("Missing 'name' key"); + if (!hasOn) issues.push("Missing 'on' key"); + if (!hasJobs) issues.push("Missing 'jobs' key"); + const status = issues.length === 0 ? "pass" : issues.length < 2 ? "warn" : "fail"; + return { hasName, hasOn, hasJobs, status, issues }; + }, +}); + +// Agent role: lint GitHub Actions workflow YAML files for required top-level keys. +const yamlWorkflowLinter = agent({ + model: "typecheck", + instructions: p`Validate each GitHub Actions workflow file found in the workspace. + +Workflow files: ${p.glob(".github/workflows/**/*.yml")} + +For each file path listed above, call the validateWorkflow tool to check for required keys. +Return a record keyed by filename with validation results.`, + output: s.record(s.object({ + hasName: s.boolean, + hasOn: s.boolean, + hasJobs: s.boolean, + status: s.enum("pass", "warn", "fail"), + issues: s.array(s.string), + })), + tools: [validateWorkflow], + addons: [repair()], +}); + +export default yamlWorkflowLinter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts new file mode 100644 index 0000000..64d5490 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts @@ -0,0 +1,69 @@ +import { agent, p, s } from "rig"; + +// Agent role: extract TypeScript files with line counts from the workspace. +const extractor = agent({ + name: "extractor", + model: "typecheck", + instructions: p`List TypeScript source files and their line counts. + +Files found: ${p.glob("**/*.ts")} +Line counts: ${p.bash("wc -l $(find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -20) 2>/dev/null | tail -21")} + +Return a list of files with their line counts. Exclude totals and node_modules.`, + output: s.array(s.object({ + file: s.path, + lines: s.int, + })), +}); + +// Agent role: classify TypeScript files by complexity tier based on line counts. +const reviewer = agent({ + name: "reviewer", + model: "typecheck", + instructions: p`You will receive a JSON list of TypeScript files with line counts. +Classify each file's complexity: +- trivial: 0-20 lines +- small: 21-100 lines +- medium: 101-300 lines +- large: 301-600 lines +- huge: 600+ lines + +Return the classified list plus a summary.`, + input: s.array(s.object({ file: s.path, lines: s.int })), + output: s.object({ + files: s.array(s.object({ + file: s.path, + lines: s.int, + complexity: s.enum("trivial", "small", "medium", "large", "huge"), + })), + summary: s.object({ + totalFiles: s.int, + largestFile: s.optional(s.path), + mostComplex: s.optional(s.path), + }), + }), +}); + +// Agent role: coordinate two-phase TypeScript complexity analysis. +const coordinator = agent({ + model: "typecheck", + instructions: p`Perform a two-phase TypeScript file complexity analysis: +1. Use the extractor subagent to get a list of TypeScript files with line counts. +2. Pass the extractor's output as input to the reviewer subagent for complexity classification. +3. Return the reviewer's output as your final result.`, + output: s.object({ + files: s.array(s.object({ + file: s.path, + lines: s.int, + complexity: s.enum("trivial", "small", "medium", "large", "huge"), + })), + summary: s.object({ + totalFiles: s.int, + largestFile: s.optional(s.path), + mostComplex: s.optional(s.path), + }), + }), + agents: { extractor, reviewer }, +}); + +export default coordinator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts new file mode 100644 index 0000000..66e9d7c --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts @@ -0,0 +1,39 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const detectExports = defineTool("detectExports", { + description: "Detect exported symbols from a TypeScript source file.", + parameters: { filePath: s.path }, + handler: async ({ filePath }) => { + const content = await readFile(filePath, "utf8"); + const exportMatches = content.match(/^export\s+(?:default\s+)?(?:const|function|class|type|interface|enum)\s+(\w+)/gm) ?? []; + const symbols = exportMatches.map((m: string) => { + const match = m.match(/(\w+)\s*$/); + return match ? match[1] : ""; + }).filter(Boolean); + return { filePath, symbols, count: symbols.length }; + }, +}); + +// Agent role: scan TypeScript source files and generate a barrel index.ts with all exports. +const barrelFileGenerator = agent({ + model: "typecheck", + instructions: p`Generate a TypeScript barrel file (index.ts) that re-exports all symbols from source files. + +Source files: ${p.glob("src/**/*.ts")} + +For each file path above, call the detectExports tool to find exported symbols. +Then generate the barrel file content as a series of export statements. +Write it to ${p.writeOutput("barrelContent", "src/index.ts")}. +Return the file count, export count, barrel content, and output path.`, + output: s.object({ + filesScanned: s.int, + exportCount: s.int, + barrelContent: s.string, + outputPath: s.path, + }), + tools: [detectExports], + addons: [repair()], +}); + +export default barrelFileGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts new file mode 100644 index 0000000..5274d42 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool } from "rig"; +import { readFile, access, constants } from "node:fs/promises"; + +const classifyHook = defineTool("classifyHook", { + description: "Classify a git hook as active, stub, or missing based on its content.", + parameters: { hookName: s.string }, + handler: async ({ hookName }) => { + const hookPath = `.git/hooks/${hookName}`; + try { + await access(hookPath, constants.F_OK); + const content = await readFile(hookPath, "utf8"); + const isSample = content.includes("sample") || hookPath.endsWith(".sample"); + const isAsync = content.includes("&") || content.includes("nohup"); + const summary = isSample + ? `Sample/stub hook at ${hookPath}` + : `Active hook: ${content.split("\n")[1]?.trim() ?? ""}`; + return { status: isSample ? "stub" : "active", isAsync, summary }; + } catch { + return { status: "missing", isAsync: false, summary: `No hook at ${hookPath}` }; + } + }, +}); + +// Agent role: inventory and classify all standard git hooks in this repository. +const gitHookInventory = agent({ + model: "typecheck", + instructions: p`Inspect all standard git hooks and classify each one. + +Hook directory listing: ${p.bash("ls -la .git/hooks/ 2>/dev/null || echo 'No .git/hooks directory'")} + +Standard hooks to check: pre-commit, pre-push, commit-msg, post-commit, post-merge, +pre-rebase, post-checkout, prepare-commit-msg, pre-receive, post-receive. + +For each hook name, call the classifyHook tool to determine its status. +Return a record keyed by hook name with status, isAsync, and summary.`, + output: s.record(s.object({ + status: s.enum("active", "stub", "missing"), + isAsync: s.boolean, + summary: s.string, + })), + tools: [classifyHook], +}); + +export default gitHookInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts new file mode 100644 index 0000000..95293bf --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts @@ -0,0 +1,30 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: generate a structured PR review checklist from the current git diff. +const prReviewChecklist = agent({ + model: "typecheck", + instructions: p`Generate a structured PR review checklist based on the git diff below. + +Changed files summary: +${p.bash("git diff HEAD~1 --stat 2>/dev/null || git diff --stat 2>/dev/null || echo 'No diff available'")} + +Diff content (first 200 lines): +${p.bash("git diff HEAD~1 -- . 2>/dev/null | head -200 || git diff -- . | head -200 || echo 'No diff available'")} + +Analyze the diff and produce: +1. A checklist of specific review items, each categorized and prioritized. +2. The list of changed file paths. +3. Whether the PR appears ready to merge (ready: true if no high-priority issues).`, + output: s.object({ + checklist: s.array(s.object({ + item: s.string, + category: s.enum("security", "performance", "correctness", "style", "docs", "tests"), + priority: s.enum("high", "medium", "low"), + })), + changedFiles: s.array(s.path), + ready: s.boolean, + }), + addons: [repair()], +}); + +export default prReviewChecklist; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts new file mode 100644 index 0000000..2611cce --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts @@ -0,0 +1,61 @@ +import { agent, p, s, defineTool } from "rig"; +import { readFile } from "node:fs/promises"; + +const parseCoverageSummary = defineTool("parseCoverageSummary", { + description: "Parse a vitest coverage-summary.json file to extract per-file coverage metrics.", + parameters: { filePath: s.path }, + handler: async ({ filePath }) => { + const raw = await readFile(filePath, "utf8"); + const json = JSON.parse(raw) as Record; + const files: Record = {}; + let totalLines = 0, totalBranches = 0, totalFunctions = 0, count = 0; + for (const [file, data] of Object.entries(json)) { + if (file === "total") continue; + const lines = data.lines?.pct ?? 0; + const branches = data.branches?.pct ?? 0; + const functions = data.functions?.pct ?? 0; + const avg = (lines + branches + functions) / 3; + const status = avg >= 80 ? "covered" : avg >= 40 ? "partial" : "uncovered"; + files[file] = { lines, branches, functions, status }; + totalLines += lines; totalBranches += branches; totalFunctions += functions; count++; + } + const n = count || 1; + return { + files, + overall: { lines: totalLines / n, branches: totalBranches / n, functions: totalFunctions / n }, + totalFiles: count, + }; + }, +}); + +// Agent role: parse vitest coverage output and return a per-file coverage report. +const vitestCoverageParser = agent({ + model: "typecheck", + instructions: p`Parse the vitest coverage report for this project. + +Coverage summary file: ${p.readOptional("coverage/coverage-summary.json")} + +If the coverage summary file is available, call parseCoverageSummary with path "coverage/coverage-summary.json". +Otherwise, report all counts as 0 and status as "uncovered". + +Count files with lines coverage >= 80% as "well covered". +Return the per-file metrics, overall averages, total file count, and well-covered count.`, + output: s.object({ + files: s.record(s.object({ + lines: s.number, + branches: s.number, + functions: s.number, + status: s.enum("covered", "partial", "uncovered"), + })), + overall: s.object({ + lines: s.number, + branches: s.number, + functions: s.number, + }), + totalFiles: s.int, + wellCoveredCount: s.int, + }), + tools: [parseCoverageSummary], +}); + +export default vitestCoverageParser; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts new file mode 100644 index 0000000..6e14193 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts @@ -0,0 +1,48 @@ +import { agent, p, s, defineTool } from "rig"; + +const aggregateStats = defineTool("aggregateStats", { + description: "Aggregate git log lines into per-author and per-day-of-week commit counts.", + parameters: { logLines: s.string }, + handler: ({ logLines }) => { + const perAuthor: Record = {}; + const perDayOfWeek: Record = {}; + const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + let totalCommits = 0; + for (const line of logLines.split("\n")) { + if (!line.trim()) continue; + const parts = line.split("|"); + if (parts.length < 4) continue; + const author = parts[1].trim(); + const dateStr = parts[3].trim(); + perAuthor[author] = (perAuthor[author] ?? 0) + 1; + const day = days[new Date(dateStr).getDay()]; + if (day) perDayOfWeek[day] = (perDayOfWeek[day] ?? 0) + 1; + totalCommits++; + } + const mostActiveAuthor = Object.entries(perAuthor).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null; + const mostActiveDay = Object.entries(perDayOfWeek).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null; + return { perAuthor, perDayOfWeek, totalCommits, mostActiveAuthor, mostActiveDay }; + }, +}); + +// Agent role: aggregate git log statistics into per-author and per-day-of-week commit counts. +const gitLogStatsAggregator = agent({ + model: "typecheck", + instructions: p`Aggregate git commit statistics from the following log: + +${p.bash("git log --format='%H|%an|%ae|%ad|%s' --date=short -100 2>/dev/null || echo ''")} + +Call aggregateStats with the full log text above as logLines. +Return the result including perAuthor counts, perDayOfWeek counts, totalCommits, +mostActiveAuthor, and mostActiveDay.`, + output: s.object({ + perAuthor: s.record(s.int), + perDayOfWeek: s.record(s.int), + totalCommits: s.int, + mostActiveAuthor: s.optional(s.string), + mostActiveDay: s.optional(s.string), + }), + tools: [aggregateStats], +}); + +export default gitLogStatsAggregator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts new file mode 100644 index 0000000..66920ac --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts @@ -0,0 +1,48 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const analyzeImportDepth = defineTool("analyzeImportDepth", { + description: "Analyze relative import depth in a TypeScript file by counting '../' occurrences.", + parameters: { filePath: s.path }, + handler: async ({ filePath }) => { + const content = await readFile(filePath, "utf8"); + const importRegex = /from\s+['"]([^'"]+)['"]/g; + const imports: string[] = []; + let match: RegExpExecArray | null; + while ((match = importRegex.exec(content)) !== null) { + imports.push(match[1]); + } + const relativeImports = imports.filter((i: string) => i.startsWith(".")); + const depths = relativeImports.map((i: string) => (i.match(/\.\.\//g) ?? []).length); + const maxDepth = depths.length > 0 ? Math.max(...depths) : 0; + const deepImports = relativeImports.filter((i: string) => (i.match(/\.\.\//g) ?? []).length >= 2); + return { maxDepth, deepImports, importCount: imports.length }; + }, +}); + +// Agent role: analyze relative import depth across TypeScript files to find overly deep imports. +const tsImportDepthAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze TypeScript import depth across all source files. + +Source files to analyze: ${p.glob("**/*.ts")} + +For each .ts file (excluding node_modules), call analyzeImportDepth to get maxDepth, deepImports, and importCount. +Calculate the average depth across all files. +Identify the file with the highest maxDepth as deepestFile. +Return the full per-file record plus summary stats.`, + output: s.object({ + files: s.record(s.object({ + maxDepth: s.int, + deepImports: s.array(s.string), + importCount: s.int, + })), + deepestFile: s.optional(s.path), + averageDepth: s.number, + totalFiles: s.int, + }), + tools: [analyzeImportDepth], + addons: [repair()], +}); + +export default tsImportDepthAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts new file mode 100644 index 0000000..e718791 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseEnvKeys = defineTool("parseEnvKeys", { + description: "Parse an env file string and return the list of key names.", + parameters: { content: s.string }, + handler: ({ content }) => { + return content + .split("\n") + .map((line: string) => line.trim()) + .filter((line: string) => line && !line.startsWith("#")) + .map((line: string) => line.split("=")[0].trim()) + .filter(Boolean); + }, +}); + +// Agent role: compare .env.example with .env to check completeness of environment configuration. +const envFileCompletenessChecker = agent({ + model: "typecheck", + instructions: p`Compare .env.example with .env to check that all required keys are set. + +.env.example content: ${p.readOptional(".env.example")} + +.env content: ${p.readOptional(".env")} + +Steps: +1. Call parseEnvKeys with the .env.example content to get exampleKeys. +2. Call parseEnvKeys with the .env content to get presentKeys. +3. Compute missingKeys (in exampleKeys but not presentKeys) and extraKeys (in presentKeys but not exampleKeys). +4. Compute completeness as (exampleKeys.length - missingKeys.length) / exampleKeys.length (or 1.0 if example is empty). +5. Set status: + - "missing-example" if .env.example is empty/missing + - "missing-env" if .env is empty/missing + - "complete" if missingKeys is empty + - "partial" otherwise`, + output: s.object({ + exampleKeys: s.array(s.string), + presentKeys: s.array(s.string), + missingKeys: s.array(s.string), + extraKeys: s.array(s.string), + completeness: s.number, + status: s.enum("complete", "partial", "missing-example", "missing-env"), + }), + tools: [parseEnvKeys], + addons: [repair()], +}); + +export default envFileCompletenessChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts new file mode 100644 index 0000000..6676a2e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts @@ -0,0 +1,15 @@ +import { agent, s } from "rig"; +// Agent role: infer a practical runtime-visible schema from the samples. +const inferShape = agent({ + model: "typecheck", + output: s.object({ + fields: s.array(s.object({ + name: s.string, + type: s.string, + optional: s.boolean + })), + example: s.unknown + }), + instructions: `Infer a practical runtime-visible schema from the samples.`, +}); +export default inferShape; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts new file mode 100644 index 0000000..e9dd934 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts @@ -0,0 +1,36 @@ +import { agent, p, s } from "rig"; + +// Agent role: annotate each of the last 20 git commits with a category and impact level. +const commitSummarizer = agent({ + name: "commitSummarizer", + model: "typecheck", + instructions: p`Classify the following git commit line into a category and impact level. +Commit: ${p.readInput("commit")}`, + input: s.object({ commit: s.string }), + output: s.object({ + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + impact: s.enum("low", "medium", "high"), + }), +}); + +// Agent role: fetch the last 20 git commits and annotate each with category and impact using the commitSummarizer subagent. +const gitCommitAnnotator = agent({ + model: "typecheck", + instructions: p`You are a git commit annotator. Here are the last 20 commits: +${p.bash("git log --oneline -20")} + +For each commit line, call the commitSummarizer subagent with the full commit line. +Then assemble the annotations array and a short prose report summarizing the distribution of categories and impacts.`, + output: s.object({ + annotations: s.array(s.object({ + hash: s.string, + message: s.string, + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + impact: s.enum("low", "medium", "high"), + })), + report: s.string, + }), + agents: { commitSummarizer }, +}); + +export default gitCommitAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts new file mode 100644 index 0000000..604f33f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts @@ -0,0 +1,54 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseScriptDeps = defineTool("parseScriptDeps", { + description: "Parse npm scripts JSON and extract per-script dependency metadata.", + parameters: { scriptsJson: s.string }, + handler: ({ scriptsJson }: { scriptsJson: string }) => { + const scripts: Record = JSON.parse(scriptsJson); + const result: Record = {}; + for (const [name, command] of Object.entries(scripts)) { + const refs = [...command.matchAll(/npm run ([a-z0-9:_-]+)/gi)].map((m: RegExpMatchArray) => m[1]); + const hasPreHook = (`pre${name}`) in scripts; + const hasPostHook = (`post${name}`) in scripts; + let category = "util"; + if (/build|compile|bundle/.test(name)) category = "build"; + else if (/test|spec|coverage/.test(name)) category = "test"; + else if (/lint|format|check/.test(name)) category = "lint"; + else if (/dev|start|watch/.test(name)) category = "dev"; + else if (/deploy|publish|release/.test(name)) category = "deploy"; + else if (/^pre|^post/.test(name)) category = "hook"; + result[name] = { command, dependsOn: refs, category, hasPreHook, hasPostHook }; + } + return result; + }, +}); + +// Agent role: map npm script dependencies in the workspace package.json. +const npmScriptDepMapper = agent({ + model: "typecheck", + instructions: p`Analyze the npm scripts in the workspace package.json. +package.json content: ${p.read("package.json")} + +Steps: +1. Extract the "scripts" field from the package.json content as a JSON string. +2. Call parseScriptDeps with that JSON string. +3. Return the result directly as the output record.`, + output: s.record(s.object({ + command: s.string, + dependsOn: s.array(s.string), + category: s.enum("build", "test", "lint", "dev", "deploy", "util", "hook", "other"), + hasPreHook: s.boolean, + hasPostHook: s.boolean, + })), + tools: [parseScriptDeps], + maxTurns: 6, + addons: [repair()], +}); + +export default npmScriptDepMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts new file mode 100644 index 0000000..74d6e15 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts @@ -0,0 +1,55 @@ +import { agent, p, s, defineTool } from "rig"; +import { exec } from "node:child_process"; +import { promisify } from "node:util"; + +const execAsync = promisify(exec); + +const checkUrl = defineTool("checkUrl", { + description: "Check an HTTP URL with curl and return its status.", + parameters: { url: s.string }, + handler: async ({ url }: { url: string }) => { + try { + const { stdout } = await execAsync( + `curl -s -o /dev/null -w "%{http_code}" --max-time 5 --location "${url}"`, + ); + const code = parseInt(stdout.trim(), 10); + let status: string; + if (code >= 200 && code < 300) status = "ok"; + else if (code >= 300 && code < 400) status = "redirect"; + else if (code === 0) status = "timeout"; + else status = "broken"; + return { httpCode: code, status }; + } catch { + return { httpCode: 0, status: "timeout" }; + } + }, +}); + +// Agent role: check all HTTP/HTTPS links found in markdown files in the workspace. +const markdownLinkChecker = agent({ + model: "typecheck", + instructions: p`Check all HTTP/HTTPS links found in markdown files. + +Markdown files: ${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -30")} +Extracted URLs: ${p.bash("grep -rh 'https\\?://[^ )>\"]*' --include='*.md' --no-filename . 2>/dev/null | grep -oE 'https?://[^ )>\"]+' | sort -u | head -50")} + +Steps: +1. For each unique URL extracted, call checkUrl. +2. Build the links array with url, status, httpCode, and foundInFile (leave as null if not determinable). +3. Count brokenCount (status = "broken" or "timeout"). +4. Set allValid to true only if brokenCount is 0.`, + output: s.object({ + links: s.array(s.object({ + url: s.string, + status: s.enum("ok", "broken", "redirect", "timeout", "skipped"), + httpCode: s.optional(s.number), + foundInFile: s.optional(s.string), + })), + brokenCount: s.number, + allValid: s.boolean, + }), + tools: [checkUrl], + maxTurns: 8, +}); + +export default markdownLinkChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts new file mode 100644 index 0000000..a363ad0 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts @@ -0,0 +1,31 @@ +import { agent, p, s } from "rig"; + +// Agent role: report package version drift by comparing package.json with npm outdated results. +const packageVersionDrift = agent({ + model: "typecheck", + instructions: p`Analyze package version drift for this workspace. + +package.json: ${p.read("package.json")} +npm outdated (JSON, may be empty if all current): ${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} + +Steps: +1. Parse the npm outdated JSON — each key is a package name with current/wanted/latest fields. +2. For each outdated package determine driftLevel: + - "ok" if current === latest + - "patch" if only patch differs + - "minor" if minor version differs + - "major" if major version differs +3. Write a markdown drift report to drift-report.md summarizing the table. +4. Set reportWritten to true after writing.`, + output: s.object({ + packages: s.array(s.object({ + name: s.string, + current: s.string, + latest: s.string, + driftLevel: s.enum("ok", "patch", "minor", "major"), + })), + reportWritten: s.boolean, + }), +}); + +export default packageVersionDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts new file mode 100644 index 0000000..0642913 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts @@ -0,0 +1,28 @@ +import { agent, p, s } from "rig"; + +// Agent role: aggregate git author statistics including commit counts and first/last commit dates. +const gitAuthorStats = agent({ + model: "typecheck", + instructions: p`Aggregate git commit statistics by author. + +Commit counts per author: ${p.bash("git shortlog -sne --all 2>/dev/null || echo ''")} +Per-commit author and date: ${p.bash("git log --format='%ae|%ai' --all 2>/dev/null | head -500")} + +Steps: +1. Parse the shortlog output to extract each author email and commit count. +2. From the per-commit log, compute firstCommit (earliest date) and lastCommit (latest date) per author email. +3. Build the authors record keyed by email with commitCount, firstCommit, lastCommit. +4. Set topAuthor to the email with the highest commitCount. +5. Set totalCommits to the sum of all commitCounts.`, + output: s.object({ + authors: s.record(s.object({ + commitCount: s.number, + firstCommit: s.string, + lastCommit: s.string, + })), + topAuthor: s.string, + totalCommits: s.number, + }), +}); + +export default gitAuthorStats; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts new file mode 100644 index 0000000..32a35c0 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts @@ -0,0 +1,39 @@ +import { agent, p, s, defineTool } from "rig"; +import { existsSync } from "node:fs"; + +const checkAlias = defineTool("checkAlias", { + description: "Check whether a TypeScript path alias target directory exists on disk.", + parameters: { alias: s.string, target: s.string }, + handler: ({ target }: { alias: string; target: string }) => { + const resolved = target.replace(/\/\*$/, ""); + return existsSync(resolved) ? "valid" : "broken"; + }, +}); + +// Agent role: validate all TypeScript path aliases defined in tsconfig.json against the workspace. +const tsPathAliasValidator = agent({ + model: "typecheck", + instructions: p`Validate TypeScript path aliases defined in tsconfig.json. + +tsconfig.json: ${p.read("tsconfig.json")} +Import statements in .ts files: ${p.bash("grep -rh --include='*.ts' 'from \"' . 2>/dev/null | grep -v node_modules | sort -u | head -100")} + +Steps: +1. Parse the compilerOptions.paths from tsconfig.json — each key is an alias pattern, values are target arrays. +2. For each alias, call checkAlias with the alias key and its first target path. +3. Check whether each alias is actually used in the import statements. +4. Set status: "broken" if target doesn't exist, "unused" if never imported, "valid" otherwise. +5. Count brokenCount as the number of broken aliases.`, + output: s.object({ + aliases: s.record(s.object({ + target: s.string, + status: s.enum("valid", "broken", "unused"), + })), + totalAliases: s.number, + brokenCount: s.number, + }), + tools: [checkAlias], + maxTurns: 6, +}); + +export default tsPathAliasValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts new file mode 100644 index 0000000..2a55a3f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts @@ -0,0 +1,43 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyBranchAge = defineTool("classifyBranchAge", { + description: "Classify a branch as fresh, stale, or dead based on its last commit date.", + parameters: { branchName: s.string, lastCommitDate: s.string }, + handler: ({ lastCommitDate }: { branchName: string; lastCommitDate: string }) => { + const ageMs = Date.now() - new Date(lastCommitDate).getTime(); + const ageDays = ageMs / (1000 * 60 * 60 * 24); + if (ageDays < 30) return "fresh"; + if (ageDays < 90) return "stale"; + return "dead"; + }, +}); + +// Agent role: detect stale and dead local git branches and recommend candidates for deletion. +const staleBranchDetector = agent({ + model: "typecheck", + instructions: p`Detect stale and dead local git branches. + +Branch list with last commit dates: +${p.bash("git for-each-ref --format='%(refname:short)|%(committerdate:iso8601)' refs/heads 2>/dev/null || echo ''")} + +Steps: +1. Parse each line as branchName|lastCommitDate. +2. For each branch, call classifyBranchAge to get its age category. +3. Build the branches array with name, lastCommit, and age. +4. Count staleCount (age = "stale") and deadCount (age = "dead"). +5. Set recommendedForDeletion to branch names where age is "dead".`, + output: s.object({ + branches: s.array(s.object({ + name: s.string, + lastCommit: s.string, + age: s.enum("fresh", "stale", "dead"), + })), + staleCount: s.number, + deadCount: s.number, + recommendedForDeletion: s.array(s.string), + }), + tools: [classifyBranchAge], + maxTurns: 6, +}); + +export default staleBranchDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts new file mode 100644 index 0000000..27c4e2f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const checkLicenseHeader = defineTool("checkLicenseHeader", { + description: "Check whether a TypeScript file starts with the expected license header.", + parameters: { filePath: s.string, expectedHeader: s.string }, + handler: async ({ filePath, expectedHeader }: { filePath: string; expectedHeader: string }) => { + try { + const content = await readFile(filePath, "utf-8"); + const lines = content.split("\n"); + const headerLines = expectedHeader.split("\n"); + const fileStart = lines.slice(0, headerLines.length).join("\n"); + if (fileStart === expectedHeader) return "ok"; + if (content.includes(expectedHeader.split("\n")[0])) return "wrong"; + return "missing"; + } catch { + return "missing"; + } + }, +}); + +// Agent role: check that all TypeScript source files contain the expected license header. +const licenseHeaderChecker = agent({ + model: "typecheck", + input: s.object({ expectedHeader: s.string }), + instructions: p`Check each TypeScript file for the expected license header. + +TypeScript files in the workspace: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -60")} + +Steps: +1. Read expectedHeader from the input. +2. For each file path, call checkLicenseHeader with the filePath and expectedHeader. +3. Build a files record keyed by file path with hasHeader and status. +4. Count missingCount (status = "missing" or "wrong"). +5. Set allCompliant to true only if missingCount is 0.`, + output: s.object({ + files: s.record(s.object({ + hasHeader: s.boolean, + status: s.enum("ok", "missing", "wrong"), + })), + missingCount: s.number, + allCompliant: s.boolean, + }), + tools: [checkLicenseHeader], + maxTurns: 8, + addons: [repair()], +}); + +export default licenseHeaderChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts new file mode 100644 index 0000000..0aa8bbe --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts @@ -0,0 +1,53 @@ +import { agent, p, s, defineTool } from "rig"; + +const extractYamlKeys = defineTool("extractYamlKeys", { + description: "Extract top-level keys from a YAML string.", + parameters: { content: s.string }, + handler: ({ content }: { content: string }) => { + const keys: string[] = []; + for (const line of content.split("\n")) { + const m = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):/); + if (m) keys.push(m[1]); + } + return keys; + }, +}); + +const diffKeys = defineTool("diffKeys", { + description: "Compute added and removed keys between two key arrays.", + parameters: { baseKeys: s.array(s.string), targetKeys: s.array(s.string) }, + handler: ({ baseKeys, targetKeys }: { baseKeys: string[]; targetKeys: string[] }) => { + const addedKeys = targetKeys.filter((k: string) => !baseKeys.includes(k)); + const removedKeys = baseKeys.filter((k: string) => !targetKeys.includes(k)); + return { addedKeys, removedKeys }; + }, +}); + +// Agent role: diff top-level keys between two YAML config files and detect breaking changes. +const yamlConfigDiff = agent({ + model: "typecheck", + input: s.object({ baseFile: s.string, targetFile: s.string }), + instructions: p`Diff top-level YAML keys between two config files. + +Base file content: ${p.readInput("baseFile")} +Target file content: ${p.readInput("targetFile")} + +Steps: +1. Call extractYamlKeys on the base file content to get baseKeys. +2. Call extractYamlKeys on the target file content to get targetKeys. +3. Call diffKeys with baseKeys and targetKeys to get addedKeys and removedKeys. +4. changedKeys are keys present in both where values differ (estimate from context if possible, else leave empty). +5. totalChanges = addedKeys.length + removedKeys.length + changedKeys.length. +6. hasBreakingChanges = removedKeys.length > 0.`, + output: s.object({ + addedKeys: s.array(s.string), + removedKeys: s.array(s.string), + changedKeys: s.array(s.string), + totalChanges: s.number, + hasBreakingChanges: s.boolean, + }), + tools: [extractYamlKeys, diffKeys], + maxTurns: 6, +}); + +export default yamlConfigDiff; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts new file mode 100644 index 0000000..6acbb5e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts @@ -0,0 +1,53 @@ +import { agent, p, s, defineTool, steering } from "rig"; +import { readFile } from "node:fs/promises"; + +const extractPackageInfo = defineTool("extractPackageInfo", { + description: "Read a nested package.json and extract name, version, and dependency names.", + parameters: { filePath: s.string }, + handler: async ({ filePath }: { filePath: string }) => { + try { + const content = await readFile(filePath, "utf-8"); + const pkg = JSON.parse(content); + const deps = [ + ...Object.keys(pkg.dependencies ?? {}), + ...Object.keys(pkg.devDependencies ?? {}), + ]; + return { + name: pkg.name ?? "(unnamed)", + version: pkg.version ?? "0.0.0", + dependencies: deps, + hasPrivate: pkg.private === true, + }; + } catch { + return { name: "(error)", version: "0.0.0", dependencies: [], hasPrivate: false }; + } + }, +}); + +// Agent role: discover all workspace packages in a monorepo and list their metadata. +const monorepoWorkspaceLister = agent({ + model: "typecheck", + instructions: p`Discover all nested package.json files in this monorepo and extract package metadata. + +Nested package.json files (excluding node_modules): +${p.bash("find . -name 'package.json' -not -path '*/node_modules/*' -mindepth 2 -maxdepth 4 2>/dev/null")} + +Steps: +1. For each file path in the list above, call extractPackageInfo to get its metadata. +2. Assemble the packages array with name, version, dependencies, and hasPrivate for each. +3. Set totalPackages to the length of the packages array.`, + output: s.object({ + packages: s.array(s.object({ + name: s.string, + version: s.string, + dependencies: s.array(s.string), + hasPrivate: s.boolean, + })), + totalPackages: s.number, + }), + tools: [extractPackageInfo], + maxTurns: 8, + addons: [steering()], +}); + +export default monorepoWorkspaceLister; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts new file mode 100644 index 0000000..964d9f4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: rewrite the error to be actionable and precise. +const improve = agent({ + model: "typecheck", + output: s.object({ + message: s.string, + explanation: s.string + }), + instructions: `Rewrite the following error to be actionable and precise:\n\nTypeError: Cannot read properties of undefined (reading 'map') at Array.forEach ()\n at processItems (src/processor.ts:23:18)`, +}); + +export default improve; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts new file mode 100644 index 0000000..43cc742 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts @@ -0,0 +1,47 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize a single git commit line into a category and impact rating +const commitSummarizer = agent({ + name: "commitSummarizer", + model: "typecheck", + instructions: p`Analyze the git commit message provided in the input and classify it. + +Commit info: ${p.inputField("commitLine")} + +Classify into category (feat, fix, chore, docs, refactor, test, perf) and rate impact (low, medium, high).`, + input: s.object({ commitLine: s.string }), + output: s.object({ + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + impact: s.enum("low", "medium", "high"), + }), +}); + +// Agent role: annotate recent git commits with category and impact via subagent delegation, writing a markdown report +const gitCommitAnnotator = agent({ + name: "gitCommitAnnotator", + model: "typecheck", + agents: { commitSummarizer }, + instructions: p`Annotate recent git commits using the commitSummarizer subagent. + +Recent commits (hash + message): +${p.bash("git log --oneline -20")} + +For each commit line, delegate to commitSummarizer with the full commit line as commitLine. +Collect the category and impact for every commit. +Build a markdown report table with columns: hash, message, category, impact. +Write the report to commit-annotations.md. +${p.writeOutput("report", "commit-annotations.md")}`, + output: s.object({ + annotations: s.array( + s.object({ + hash: s.string, + message: s.string, + category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), + impact: s.enum("low", "medium", "high"), + }) + ), + report: s.string, + }), +}); + +export default gitCommitAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts new file mode 100644 index 0000000..1e4916b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseScriptDeps = defineTool("parseScriptDeps", { + description: "Extract npm run references and detect pre/post hooks for a script", + parameters: s.object({ + scriptName: s.string, + scriptBody: s.string, + allScriptNames: s.array(s.string), + }), + handler: ({ scriptName, scriptBody, allScriptNames }) => { + const deps: string[] = []; + const runRefs = scriptBody.match(/npm run ([\w:.-]+)/g) ?? []; + runRefs.forEach((ref: string) => deps.push(ref.replace("npm run ", ""))); + const hasPreHook = allScriptNames.includes("pre" + scriptName); + const hasPostHook = allScriptNames.includes("post" + scriptName); + return JSON.stringify({ deps, hasPreHook, hasPostHook }); + }, +}); + +// Agent role: map npm script dependencies and classify each script by category +const npmScriptDepMapper = agent({ + name: "npmScriptDepMapper", + model: "typecheck", + maxTurns: 2, + addons: repair(), + tools: [parseScriptDeps], + instructions: p`Analyze npm scripts from package.json and map their dependencies. + +package.json: ${p.read("package.json")} + +For each script, call parseScriptDeps with the scriptName, scriptBody, and list of all script names. +Classify each script's category: build, test, lint, dev, deploy, util, hook, or other. +A script is a hook category if its name starts with pre or post. +Set hasPreHook and hasPostHook based on tool output. +Return a record keyed by script name.`, + output: s.record( + s.object({ + command: s.string, + dependsOn: s.array(s.string), + category: s.enum("build", "test", "lint", "dev", "deploy", "util", "hook", "other"), + hasPreHook: s.boolean, + hasPostHook: s.boolean, + }) + ), +}); + +export default npmScriptDepMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts new file mode 100644 index 0000000..6cadfbb --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts @@ -0,0 +1,56 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const checkUrl = defineTool("checkUrl", { + description: "Check the HTTP status of a URL using curl", + parameters: s.object({ url: s.string }), + handler: async ({ url }) => { + const { execSync } = await import("node:child_process"); + try { + const code = execSync( + `curl --head --silent --max-time 5 -o /dev/null -w "%{http_code}" "${url}" 2>/dev/null`, + { encoding: "utf8", timeout: 8000 } + ).trim(); + return code; + } catch { + return "timeout"; + } + }, +}); + +// Agent role: locate markdown files, extract HTTP links, and check each link's HTTP status +const markdownLinkChecker = agent({ + name: "markdownLinkChecker", + model: "typecheck", + addons: repair(), + tools: [checkUrl], + instructions: p`Check HTTP links found across all markdown files in this workspace. + +Markdown files found: +${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -20")} + +Unique URLs extracted: +${p.bash("grep -roh 'https\\?://[^)\"\\s]*' . --include='*.md' 2>/dev/null | sort -u | head -50")} + +For each URL, call checkUrl and classify the result: +- ok: HTTP 200-299 +- redirect: HTTP 301, 302, 307, 308 +- broken: HTTP 400-599 +- timeout: curl timed out or failed +- skipped: malformed or non-http URL + +Set allValid to true only if brokenCount is 0.`, + output: s.object({ + links: s.array( + s.object({ + url: s.url, + status: s.enum("ok", "broken", "redirect", "timeout", "skipped"), + httpCode: s.optional(s.int), + foundInFile: s.optional(s.path), + }) + ), + brokenCount: s.int, + allValid: s.boolean, + }), +}); + +export default markdownLinkChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts new file mode 100644 index 0000000..70231b1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts @@ -0,0 +1,35 @@ +import { agent, p, s } from "rig"; + +// Agent role: compare installed npm package versions against the latest published versions and classify drift +const pkgVersionDrift = agent({ + name: "pkgVersionDrift", + model: "typecheck", + instructions: p`Report npm package version drift for this project. + +Package manifest: ${p.read("package.json")} + +Outdated packages (JSON): ${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} + +For each dependency, classify driftLevel: +- ok: current matches latest +- patch: only patch version behind +- minor: minor version behind +- major: major version behind + +Write a markdown drift summary report. +${p.writeOutput("report", "version-drift-report.md")}`, + output: s.object({ + packages: s.array( + s.object({ + name: s.string, + current: s.string, + latest: s.string, + driftLevel: s.enum("ok", "patch", "minor", "major"), + }) + ), + report: s.string, + reportWritten: s.boolean, + }), +}); + +export default pkgVersionDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts new file mode 100644 index 0000000..baad490 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts @@ -0,0 +1,33 @@ +import { agent, p, s } from "rig"; + +// Agent role: aggregate git commit statistics per author including commit counts and date ranges +const gitAuthorStats = agent({ + name: "gitAuthorStats", + model: "typecheck", + instructions: p`Aggregate git commit statistics per author. + +Author commit counts: ${p.bash("git shortlog -sne --all 2>/dev/null | head -40")} + +Commit log with author emails and dates: ${p.bash("git log --format='%ae|%ad' --date=short 2>/dev/null | head -200")} + +For each unique author email, compute: +- commitCount: total number of commits +- firstCommit: earliest commit date (YYYY-MM-DD) +- lastCommit: most recent commit date (YYYY-MM-DD) + +Identify topAuthor with the most commits. +Compute totalCommits across all authors.`, + output: s.object({ + authors: s.record( + s.object({ + commitCount: s.int, + firstCommit: s.string, + lastCommit: s.string, + }) + ), + topAuthor: s.string, + totalCommits: s.int, + }), +}); + +export default gitAuthorStats; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts new file mode 100644 index 0000000..0c9c9b0 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool } from "rig"; +import { existsSync } from "node:fs"; + +const checkAlias = defineTool("checkAlias", { + description: "Check whether a TypeScript path alias target exists on the filesystem", + parameters: s.object({ alias: s.string, target: s.string }), + handler: ({ alias, target }) => { + const resolved = target.replace(/\/\*$/, ""); + const exists = existsSync(resolved); + return JSON.stringify({ alias, target, exists }); + }, +}); + +// Agent role: validate TypeScript path alias targets from tsconfig.json against the filesystem +const tsPathAliasValidator = agent({ + name: "tsPathAliasValidator", + model: "typecheck", + tools: [checkAlias], + instructions: p`Validate TypeScript path aliases defined in tsconfig.json. + +tsconfig.json: ${p.read("tsconfig.json")} + +Import alias usage in source: ${p.bash("grep -r --include='*.ts' -h 'from [\"\\x27]' . 2>/dev/null | grep -v node_modules | grep -v '\\./' | grep -v '\\.\\./' | head -40")} + +For each entry in compilerOptions.paths, call checkAlias with the alias pattern and its first target path. +Classify each alias: +- valid: target exists on disk and alias is used in imports +- broken: target path does not exist +- unused: target exists but alias not found in any imports + +Report totalAliases and brokenCount.`, + output: s.object({ + aliases: s.record( + s.object({ + target: s.string, + status: s.enum("valid", "broken", "unused"), + }) + ), + totalAliases: s.int, + brokenCount: s.int, + }), +}); + +export default tsPathAliasValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts new file mode 100644 index 0000000..ec6d074 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts @@ -0,0 +1,52 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseWorkflowSteps = defineTool("parseWorkflowSteps", { + description: "Parse a GitHub Actions workflow YAML to extract job names, step counts, and detect optimization patterns", + parameters: s.object({ content: s.string, filename: s.string }), + handler: ({ content, filename }) => { + const jobMatches = content.match(/^\s{2}[\w-]+:/gm) ?? []; + const stepMatches = content.match(/^\s+-\s+(?:name:|uses:|run:)/gm) ?? []; + const hasCache = /uses:\s+actions\/cache/.test(content) || /cache:/.test(content); + const hasMatrix = /matrix:/.test(content); + const hasInstall = /npm (ci|install)|yarn install|pnpm install/.test(content); + const missingCache = hasInstall && !hasCache; + const suggestions: string[] = []; + if (missingCache) suggestions.push("Add actions/cache after install step to speed up builds"); + if (hasMatrix && jobMatches.length === 1) suggestions.push("Matrix found but only one job — consider parallel jobs for different test suites"); + if (stepMatches.length > 15) suggestions.push("Workflow has many steps — consider splitting into reusable workflows"); + return JSON.stringify({ filename, jobs: jobMatches.length, steps: stepMatches.length, hasCache, hasMatrix, suggestions }); + }, +}); + +// Agent role: analyze GitHub Actions workflow files for timing and performance optimization opportunities +const ghActionsTimingAnalyzer = agent({ + name: "ghActionsTimingAnalyzer", + model: "typecheck", + addons: repair(), + tools: [parseWorkflowSteps], + instructions: p`Analyze GitHub Actions workflow files for performance optimization opportunities. + +Workflow files: ${p.glob(".github/workflows/*.yml")} + +Workflow contents: ${p.bash("find .github/workflows -name '*.yml' 2>/dev/null | head -10 | xargs cat 2>/dev/null || echo 'No workflows found'")} + +For each workflow file, call parseWorkflowSteps with the file content and filename. +Collect results and determine if any workflows are optimizable (have suggestions). +Set optimizable to true if any workflow has suggestions.`, + output: s.object({ + workflows: s.array( + s.object({ + file: s.path, + jobs: s.int, + steps: s.int, + hasCache: s.boolean, + hasMatrix: s.boolean, + suggestions: s.array(s.string), + }) + ), + totalWorkflows: s.int, + optimizable: s.boolean, + }), +}); + +export default ghActionsTimingAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts new file mode 100644 index 0000000..7159b5a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts @@ -0,0 +1,53 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const detectBinary = defineTool("detectBinary", { + description: "Detect whether a file is binary by sampling its first 8KB for null bytes", + parameters: s.object({ filePath: s.string }), + handler: async ({ filePath }) => { + const { readFile, stat } = await import("node:fs/promises"); + try { + const stats = await stat(filePath); + const sizeBytes = stats.size; + const buf = await readFile(filePath); + const sample = buf.slice(0, 8192); + let nullBytes = 0; + for (let i = 0; i < sample.length; i++) { + if (sample[i] === 0) nullBytes++; + } + const nullRatio = sample.length > 0 ? nullBytes / sample.length : 0; + const type = nullRatio > 0.01 ? "binary" : "text"; + return JSON.stringify({ type, sizeBytes }); + } catch { + return JSON.stringify({ type: "unknown", sizeBytes: 0 }); + } + }, +}); + +// Agent role: detect binary files committed to the git repository by sampling file contents +const binaryFileDetector = agent({ + name: "binaryFileDetector", + model: "typecheck", + addons: steering(), + tools: [detectBinary], + instructions: p`Detect binary files in the git repository. + +All tracked files: ${p.bash("git ls-files 2>/dev/null | head -200")} + +For each tracked file, call detectBinary to classify it as text, binary, or unknown. +Count binaryCount and textCount across all files. +Set hasBinaryFiles to true if binaryCount > 0. +Return a record keyed by file path.`, + output: s.object({ + files: s.record( + s.object({ + type: s.enum("text", "binary", "unknown"), + sizeBytes: s.optional(s.int), + }) + ), + binaryCount: s.int, + textCount: s.int, + hasBinaryFiles: s.boolean, + }), +}); + +export default binaryFileDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts new file mode 100644 index 0000000..7f43790 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const extractInterfaceExtends = defineTool("extractInterfaceExtends", { + description: "Extract TypeScript interface declarations and their extends relationships from file content", + parameters: s.object({ content: s.string }), + handler: ({ content }) => { + const results: Array<{ name: string; extends: string[] }> = []; + const re = /interface\s+(\w+)(?:<[^>]+>)?\s*(?:extends\s+([\w<>, ]+))?\s*\{/g; + let m: RegExpExecArray | null; + while ((m = re.exec(content)) !== null) { + const name = m[1]; + const extendsClause = m[2] ?? ""; + const parents = extendsClause + ? extendsClause.split(",").map((p: string) => p.trim().replace(/<.*>/, "").trim()).filter(Boolean) + : []; + results.push({ name, extends: parents }); + } + return JSON.stringify(results); + }, +}); + +// Agent role: build a TypeScript interface inheritance graph from source files +const tsInterfaceInheritanceGraph = agent({ + name: "tsInterfaceInheritanceGraph", + model: "typecheck", + addons: repair(), + tools: [extractInterfaceExtends], + instructions: p`Build a TypeScript interface inheritance graph. + +TypeScript source files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.d.ts' | head -30")} + +Interface declarations from source: ${p.bash("grep -rh 'interface ' . --include='*.ts' 2>/dev/null | grep -v node_modules | head -100")} + +For each source file group, call extractInterfaceExtends with the combined content. +Build a graph where each interface node lists its parent interfaces. +Classify each interface's depth: root (no parents), derived (has parents), or leaf (no children). +Compute totalInterfaces and maxDepth (longest inheritance chain).`, + output: s.object({ + interfaces: s.record( + s.object({ + parents: s.array(s.string), + depth: s.enum("root", "derived", "leaf"), + }) + ), + totalInterfaces: s.int, + maxDepth: s.int, + }), +}); + +export default tsInterfaceInheritanceGraph; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts new file mode 100644 index 0000000..c574a99 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts @@ -0,0 +1,58 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const extractLicense = defineTool("extractLicense", { + description: "Extract the SPDX license identifier from a package's license field or LICENSE file content", + parameters: s.object({ packageName: s.string, licenseField: s.string }), + handler: ({ packageName, licenseField }) => { + const permissive = ["MIT", "ISC", "BSD-2-Clause", "BSD-3-Clause", "Apache-2.0", "Unlicense", "CC0-1.0", "0BSD"]; + const copyleft = ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0", "AGPL-3.0", "MPL-2.0"]; + const id = licenseField.trim().toUpperCase(); + let compatibility: string; + if (permissive.some((l: string) => id.includes(l.toUpperCase()))) { + compatibility = "permissive"; + } else if (copyleft.some((l: string) => id.includes(l.toUpperCase()))) { + compatibility = "copyleft"; + } else if (id === "UNLICENSED" || id === "") { + compatibility = "proprietary"; + } else { + compatibility = "unknown"; + } + return JSON.stringify({ packageName, spdxId: licenseField, compatibility }); + }, +}); + +// Agent role: audit npm dependency licenses and build a compatibility matrix +const depLicenseMatrix = agent({ + name: "depLicenseMatrix", + model: "typecheck", + addons: repair(), + tools: [extractLicense], + instructions: p`Audit npm dependency licenses and classify compatibility. + +package.json: ${p.read("package.json")} + +Installed package licenses: ${p.bash("cat node_modules/*/package.json 2>/dev/null | grep -E '\"name\"|\"license\"' | paste - - | head -60 || echo 'Run npm install first'")} + +For each direct dependency, call extractLicense with the package name and its license field value. +Classify compatibility: +- permissive: MIT, ISC, BSD, Apache-2.0, etc. +- copyleft: GPL, LGPL, AGPL, MPL, etc. +- proprietary: UNLICENSED or empty +- unknown: unrecognized SPDX identifier + +Compute copyleftCount and unknownCount. +Set hasConflicts to true if any copyleft or proprietary licenses are present.`, + output: s.object({ + packages: s.record( + s.object({ + spdxId: s.string, + compatibility: s.enum("permissive", "copyleft", "proprietary", "unknown"), + }) + ), + copyleftCount: s.int, + unknownCount: s.int, + hasConflicts: s.boolean, + }), +}); + +export default depLicenseMatrix; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts new file mode 100644 index 0000000..b00de2e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts @@ -0,0 +1,16 @@ +import { agent, s } from "rig"; +// Agent role: write a concise migration guide. +const migration = agent({ + model: "typecheck", + output: s.object({ + title: s.string, + steps: s.array(s.string), + examples: s.array(s.object({ + before: s.string, + after: s.string + })) + }), + instructions: `Write a concise migration guide.`, +}); + +export default migration; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts new file mode 100644 index 0000000..03f3eaf --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts @@ -0,0 +1,49 @@ +import { agent, p, s, defineTool } from "rig"; + +const parseSubmoduleStatus = defineTool("parseSubmoduleStatus", { + description: "Parse a git submodule status line into structured fields.", + parameters: s.object({ line: s.string }), + handler({ line }) { + const statusChar = line[0] ?? " "; + const rest = line.slice(1).trim(); + const parts = rest.split(/\s+/); + const sha = parts[0] ?? ""; + const path = parts[1] ?? ""; + let status: "clean" | "modified" | "uninitialized" | "conflict" = "clean"; + if (statusChar === "+") status = "modified"; + else if (statusChar === "-") status = "uninitialized"; + else if (statusChar === "U") status = "conflict"; + const describeMatch = rest.match(/\(([^)]+)\)$/); + return { path, sha, status, describe: describeMatch?.[1] }; + }, +}); + +// Agent role: Inventory git submodules and report their health status. +const gitSubmoduleHealth = agent({ + model: "typecheck", + instructions: p`Check the health of all git submodules. + +Submodule status: +${p.bash("git submodule status 2>/dev/null || echo '(no submodules)'")} + +Submodule config: +${p.readOptional(".gitmodules", "(no .gitmodules file)")} + +For each non-empty status line, call parseSubmoduleStatus to extract path, sha, status, and optional describe. +Return submodules array, allClean (true if every status is "clean"), and totalCount.`, + tools: [parseSubmoduleStatus], + output: s.object({ + submodules: s.array( + s.object({ + path: s.path, + sha: s.string, + status: s.enum("clean", "modified", "uninitialized", "conflict"), + describe: s.optional(s.string), + }) + ), + allClean: s.boolean, + totalCount: s.int, + }), +}); + +export default gitSubmoduleHealth; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts new file mode 100644 index 0000000..1a4a5fc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyDecorator = defineTool("classifyDecorator", { + description: "Classify a TypeScript decorator by its name into a usage type.", + parameters: s.object({ name: s.string }), + handler({ name }) { + const lower = name.toLowerCase(); + if (/^(component|module|injectable|controller|service|directive|pipe)$/.test(lower)) + return { type: "class" }; + if (/^(get|post|put|delete|patch|route|httpcode|header|body|query|param)$/.test(lower)) + return { type: "method" }; + if (/^(column|primarycolumn|primarygeneratedcolumn|onetomany|manytoone|manyto)/.test(lower)) + return { type: "property" }; + if (/^(param|body|query|request|response|headers|ip|session|uploadedfile)$/.test(lower)) + return { type: "parameter" }; + return { type: "unknown" }; + }, +}); + +// Agent role: Scan TypeScript files for decorator usage and classify each decorator. +const tsDecoratorScanner = agent({ + model: "typecheck", + instructions: p`Scan for TypeScript decorator patterns in the repository. + +Decorator occurrences: +${p.bash("grep -rn '@[A-Z][A-Za-z]*' --include='*.ts' . 2>/dev/null | head -60 || echo 'none found'")} + +For each unique decorator name found, call classifyDecorator to get its type. +Build a record keyed by decorator name (without @) with count and type. +Set hasExperimental to true if any decorators from experimental frameworks (e.g., legacy Angular, old NestJS) are found. +Return decorators record, totalCount (sum of all counts), and hasExperimental.`, + tools: [classifyDecorator], + output: s.object({ + decorators: s.record( + s.object({ + count: s.int, + type: s.enum("class", "method", "property", "parameter", "unknown"), + }) + ), + totalCount: s.int, + hasExperimental: s.boolean, + }), +}); + +export default tsDecoratorScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts new file mode 100644 index 0000000..8ec1244 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts @@ -0,0 +1,48 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const categorizeDotfile = defineTool("categorizeDotfile", { + description: "Categorize a dotfile by its filename into a purpose category.", + parameters: s.object({ filename: s.string }), + handler({ filename }) { + const name = filename.replace(/^\./, "").toLowerCase(); + if (/^(bash|zsh|fish|profile|bashrc|zshrc|bash_profile|zprofile|inputrc)/.test(name)) + return { category: "shell" }; + if (/^(vimrc|vim|nvim|emacs|nano|editorconfig|prettierrc|eslintrc)/.test(name)) + return { category: "editor" }; + if (/^(gitconfig|gitignore|gitattributes|gitmessage|git)/.test(name)) + return { category: "git" }; + if (/^(ssh|known_hosts|authorized_keys)/.test(name)) + return { category: "ssh" }; + if (/^(npmrc|yarnrc|pnpmfile|curlrc|wgetrc|tmux|screenrc|docker)/.test(name)) + return { category: "tool" }; + return { category: "other" }; + }, +}); + +// Agent role: Inventory dotfiles in the home directory and categorize each one. +const dotfileInventory = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Inventory dotfiles in the home directory and categorize each. + +Dotfiles found: +${p.bash("find ~ -maxdepth 1 -name '.*' -type f 2>/dev/null | head -40 || echo '(none found)'")} + +For each dotfile found, call categorizeDotfile with its filename (basename). +Build a record keyed by filename with category and a short purpose description. +Also compute categorySummary as a record of category → count of dotfiles in that category. +Return dotfiles record, totalFound (integer count), and categorySummary.`, + tools: [categorizeDotfile], + output: s.object({ + dotfiles: s.record( + s.object({ + category: s.enum("shell", "editor", "git", "ssh", "tool", "other"), + purpose: s.string, + }) + ), + totalFound: s.int, + categorySummary: s.record(s.int), + }), +}); + +export default dotfileInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts new file mode 100644 index 0000000..10be773 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts @@ -0,0 +1,59 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +// Agent role: Run regex patterns against test cases and report pass/fail results. +const regexPatternTester = agent({ + model: "typecheck", + addons: repair(), + input: s.object({ + patterns: s.array( + s.object({ + name: s.string, + regex: s.string, + testCases: s.array( + s.object({ + input: s.string, + shouldMatch: s.boolean, + }) + ), + }) + ), + }), + instructions: p`Run each regex pattern against its test cases and report results. + +Input patterns and test cases: +${p.json("input")} + +Use the runRegexTest tool for each pattern+testCase combination. +For each pattern, build a result with name, passed count, failed count, and allPassed. +Return results array, totalPatterns, passCount (patterns where allPassed=true), +failCount (patterns where allPassed=false), and overall allPassed.`, + tools: [ + defineTool("runRegexTest", { + description: "Test a regex pattern against an input string and return whether it matches.", + parameters: s.object({ regex: s.string, input: s.string }), + handler({ regex, input }) { + try { + return { matched: new RegExp(regex).test(input) }; + } catch (e) { + return { matched: false, error: String(e) }; + } + }, + }), + ], + output: s.object({ + results: s.array( + s.object({ + name: s.string, + passed: s.int, + failed: s.int, + allPassed: s.boolean, + }) + ), + totalPatterns: s.int, + passCount: s.int, + failCount: s.int, + allPassed: s.boolean, + }), +}); + +export default regexPatternTester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts new file mode 100644 index 0000000..f4079bb --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts @@ -0,0 +1,27 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: classify repository files by commit churn frequency and assign a risk level. +const commitChurnClassifier = agent({ + model: "typecheck", + addons: steering({ message: "Assign riskLevel based on churnCount: >20=critical, >10=volatile, >5=active, else stable. Only include files from the churn output." }), + instructions: p`Classify repository files by commit churn (how frequently they change). + +File churn counts from git history: +${p.bash("git log --name-only --format='' 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} + +For each file in the output, parse the churn count and assign a riskLevel: +- critical: churnCount > 20 +- volatile: churnCount > 10 +- active: churnCount > 5 +- stable: churnCount <= 5 + +Return a record keyed by file path with churnCount (integer) and riskLevel.`, + output: s.record( + s.object({ + churnCount: s.int, + riskLevel: s.enum("stable", "active", "volatile", "critical"), + }) + ), +}); + +export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts new file mode 100644 index 0000000..4611bf4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool } from "rig"; + +// Agent role: estimate npm package publish size and rate it with a recommendation. +const npmPackageSize = agent({ + model: "typecheck", + instructions: p`Estimate the npm package publish size and rate it. + +Files included in npm publish (dry run): +${p.bash("npm pack --dry-run 2>&1 | head -40")} + +Workspace size: +${p.bash("du -sh . 2>/dev/null | cut -f1")} + +Package metadata: +${p.readOptional("package.json", "{}")} + +Parse the npm pack output to extract individual file sizes. Use classifySize on the total. +List the top files by size. Provide a recommendation if the package is large. +Return estimatedSizeKb, topFiles (up to 5), sizeRating, and recommendation.`, + tools: [ + defineTool("classifySize", { + description: "Classify a package size in KB into a rating tier.", + parameters: s.object({ sizeKb: s.number }), + handler({ sizeKb }) { + if (sizeKb < 10) return { rating: "tiny" }; + if (sizeKb < 100) return { rating: "small" }; + if (sizeKb < 1000) return { rating: "medium" }; + if (sizeKb < 10000) return { rating: "large" }; + return { rating: "xlarge" }; + }, + }), + ], + output: s.object({ + estimatedSizeKb: s.number, + topFiles: s.array(s.object({ path: s.path, sizeKb: s.number })), + sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), + recommendation: s.string, + }), +}); + +export default npmPackageSize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts new file mode 100644 index 0000000..a775f21 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts @@ -0,0 +1,52 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseTsConfigOption = defineTool("parseTsConfigOption", { + description: "Classify a tsconfig compilerOption by name and infer if it is recommended.", + parameters: s.object({ optionName: s.string }), + handler({ optionName }) { + const strictOptions = new Set(["strict", "noImplicitAny", "strictNullChecks", "strictFunctionTypes", "strictBindCallApply", "strictPropertyInitialization", "noImplicitThis", "alwaysStrict", "useUnknownInCatchVariables", "exactOptionalPropertyTypes", "noUncheckedIndexedAccess"]); + const perfOptions = new Set(["incremental", "composite", "tsBuildInfoFile", "isolatedModules", "skipLibCheck", "skipDefaultLibCheck"]); + const outputOptions = new Set(["outDir", "outFile", "rootDir", "declarationDir", "declaration", "declarationMap", "sourceMap", "inlineSources", "inlineSourceMap", "emitDeclarationOnly", "noEmit"]); + const pathOptions = new Set(["paths", "baseUrl", "rootDirs", "typeRoots", "types"]); + if (strictOptions.has(optionName)) return { category: "strict", recommended: true }; + if (perfOptions.has(optionName)) return { category: "perf", recommended: true }; + if (outputOptions.has(optionName)) return { category: "output", recommended: false }; + if (pathOptions.has(optionName)) return { category: "paths", recommended: false }; + return { category: "misc", recommended: false }; + }, +}); + +// Agent role: analyze tsconfig.json compiler options and classify each one. +const tsconfigOptionAnalyzer = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Analyze TypeScript compiler options from tsconfig files in this project. + +Main tsconfig.json: +${p.read("tsconfig.json")} + +Additional tsconfig files found: +${p.glob("tsconfig.*.json")} + +For each compilerOption key found in the tsconfig files, call parseTsConfigOption to get +its category and recommended status. +Build an options record keyed by option name with value (from config), category, and recommended. +Count strictCount (number of strict-category options enabled). +Set hasIsolatedModules to true if isolatedModules is set to true. +List all config file paths found in configFilesFound.`, + tools: [parseTsConfigOption], + output: s.object({ + options: s.record( + s.object({ + value: s.unknown, + category: s.enum("strict", "perf", "output", "paths", "misc"), + recommended: s.boolean, + }) + ), + strictCount: s.int, + hasIsolatedModules: s.boolean, + configFilesFound: s.array(s.string), + }), +}); + +export default tsconfigOptionAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts new file mode 100644 index 0000000..dc31342 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const extractPatchMetadata = defineTool("extractPatchMetadata", { + description: "Extract metadata (author, subject, stats) from a git format-patch block.", + parameters: s.object({ patchBlock: s.string }), + handler({ patchBlock }) { + const authorMatch = patchBlock.match(/^From:\s*(.+)$/m); + const subjectMatch = patchBlock.match(/^Subject:\s*(?:\[PATCH[^\]]*\]\s*)?(.+)$/m); + const statsMatch = patchBlock.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/); + return { + author: authorMatch?.[1]?.trim() ?? "unknown", + subject: subjectMatch?.[1]?.trim() ?? "unknown", + filesChanged: statsMatch ? parseInt(statsMatch[1] ?? "0", 10) : 0, + insertions: statsMatch ? parseInt(statsMatch[2] ?? "0", 10) : 0, + deletions: statsMatch ? parseInt(statsMatch[3] ?? "0", 10) : 0, + }; + }, +}); + +// Agent role: summarize git patches from recent commits with author and diffstat info. +const gitPatchSummarizer = agent({ + model: "typecheck", + addons: steering({ message: "Split the patch output by 'From ' header lines to identify individual patch blocks before calling extractPatchMetadata." }), + instructions: p`Summarize the most recent git commits as formatted patches. + +Recent patches (last 5 commits): +${p.bash("git format-patch -5 --stdout 2>/dev/null | head -300 || echo '(no commits)'")} + +Split the output into individual patch blocks (each starts with a 'From ' line). +Call extractPatchMetadata for each block. +Return patches array with author, subject, filesChanged, insertions, deletions. +Set totalPatches to the number of patches found. +Set topContributor to the author with the most patches (omit if all are the same or none found).`, + tools: [extractPatchMetadata], + output: s.object({ + patches: s.array( + s.object({ + author: s.string, + subject: s.string, + filesChanged: s.int, + insertions: s.int, + deletions: s.int, + }) + ), + totalPatches: s.int, + topContributor: s.optional(s.string), + }), +}); + +export default gitPatchSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts new file mode 100644 index 0000000..8d018e2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyScript = defineTool("classifyScript", { + description: "Classify an npm script by name into a lifecycle category.", + parameters: s.object({ scriptName: s.string, command: s.string }), + handler({ scriptName }) { + const name = scriptName.toLowerCase(); + const isHook = /^(pre|post)/.test(name); + if (/build|compile|bundle|webpack|rollup|esbuild/.test(name)) return { category: "build", isHook }; + if (/test|jest|vitest|mocha|spec/.test(name)) return { category: "test", isHook }; + if (/lint|eslint|tslint|prettier|format/.test(name)) return { category: "lint", isHook }; + if (/release|publish|deploy|version|changelog/.test(name)) return { category: "release", isHook }; + if (isHook) return { category: "hook", isHook: true }; + return { category: "other", isHook: false }; + }, +}); + +// Agent role: analyze npm lifecycle scripts in package.json and classify each one. +const npmLifecycleAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze the npm lifecycle scripts defined in package.json. + +package.json contents: +${p.read("package.json")} + +For each entry in the "scripts" field, call classifyScript with the script name and command. +Build a scripts record keyed by script name with command, category, and isHook. +Count hookCount (scripts where isHook is true). +List missingRecommended: which of ["test", "build", "lint"] are absent from scripts. +Set hasTestScript and hasBuildScript based on whether those categories exist.`, + tools: [classifyScript], + output: s.object({ + scripts: s.record( + s.object({ + command: s.string, + category: s.enum("build", "test", "lint", "release", "hook", "other"), + isHook: s.boolean, + }) + ), + hookCount: s.int, + missingRecommended: s.array(s.string), + hasTestScript: s.boolean, + hasBuildScript: s.boolean, + }), +}); + +export default npmLifecycleAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts new file mode 100644 index 0000000..57d2703 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts @@ -0,0 +1,70 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const analyzeFunctionComments = defineTool("analyzeFunctionComments", { + description: "Count exported functions with and without JSDoc comments in a TypeScript file.", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + let content: string; + try { + content = await readFile(filePath, "utf8"); + } catch { + return { documentedCount: 0, undocumentedCount: 0, coverage: 0 }; + } + const lines = content.split("\n"); + let documentedCount = 0; + let undocumentedCount = 0; + for (let i = 0; i < lines.length; i++) { + const line = lines[i] ?? ""; + if (/^\s*export\s+(async\s+)?function\s+\w+|^\s*export\s+const\s+\w+\s*=\s*(async\s*)?\(/.test(line)) { + const prevLine = lines[i - 1] ?? ""; + const prevPrevLine = lines[i - 2] ?? ""; + if (/\*\//.test(prevLine) || /\*\//.test(prevPrevLine)) { + documentedCount++; + } else { + undocumentedCount++; + } + } + } + const total = documentedCount + undocumentedCount; + return { + documentedCount, + undocumentedCount, + coverage: total > 0 ? Math.round((documentedCount / total) * 100) / 100 : 1, + }; + }, +}); + +// Agent role: measure JSDoc comment coverage for exported functions across TypeScript files. +const tsJsdocCoverage = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Measure JSDoc coverage for exported functions in TypeScript source files. + +TypeScript files in this project: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -20")} + +For each file path listed, call analyzeFunctionComments to get documentedCount, +undocumentedCount, and coverage (0–1 ratio). +Build the files record keyed by file path. +Compute overall totals: totalFunctions, documentedFunctions, coveragePercent (0–100). +List wellDocumentedFiles: file paths where coverage >= 0.8.`, + tools: [analyzeFunctionComments], + output: s.object({ + files: s.record( + s.object({ + documentedCount: s.int, + undocumentedCount: s.int, + coverage: s.number, + }) + ), + overall: s.object({ + totalFunctions: s.int, + documentedFunctions: s.int, + coveragePercent: s.number, + }), + wellDocumentedFiles: s.array(s.path), + }), +}); + +export default tsJsdocCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts new file mode 100644 index 0000000..b9f45ea --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; +// Agent role: review the design proposal for simplicity and maintainability. +const designReview = agent({ + model: "typecheck", + output: s.object({ + decision: s.enum("approve", "revise", "reject"), + strengths: s.array(s.string), + concerns: s.array(s.string), + requiredChanges: s.array(s.string) + }), + instructions: `Review the design proposal for simplicity and maintainability.`, +}); + +export default designReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts new file mode 100644 index 0000000..3f0b595 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts @@ -0,0 +1,53 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const categorizeDotfile = defineTool("categorizeDotfile", { + description: "Categorize a dotfile by its filename into a purpose and category.", + parameters: s.object({ filename: s.string }), + handler({ filename }) { + const f = filename.toLowerCase(); + if (f.includes("bash") || f.includes("zsh") || f.includes("fish") || f.includes("profile") || f.includes("aliases")) { + return { purpose: "Shell configuration and aliases", category: "shell" as const }; + } + if (f.includes("vim") || f.includes("emacs") || f.includes("vscode") || f.includes("editorconfig") || f.includes("nvim")) { + return { purpose: "Editor settings and configuration", category: "editor" as const }; + } + if (f.includes("git") || f.includes("gitconfig") || f.includes("gitignore")) { + return { purpose: "Git version control configuration", category: "git" as const }; + } + if (f.includes("ssh") || f.includes("gnupg") || f.includes("gpg")) { + return { purpose: "SSH or GPG security configuration", category: "ssh" as const }; + } + if (f.includes("npm") || f.includes("yarn") || f.includes("pip") || f.includes("cargo") || f.includes("gem")) { + return { purpose: "Package manager settings", category: "package-manager" as const }; + } + return { purpose: "Miscellaneous dotfile configuration", category: "misc" as const }; + }, +}); + +// Agent role: inventory dotfiles in the home directory and categorize them by purpose. +const dotfileInventoryMapper = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Inventory dotfiles found in the home directory. + +Discovered dotfiles: +${p.bash("find ~ -maxdepth 2 -name '.*' -type f 2>/dev/null | head -50")} + +For each file path, call categorizeDotfile with just the filename (basename). +Build the dotfiles record keyed by filename with purpose and category. +Count totalFound (number of entries in dotfiles). +Build categorySummary as a record of category -> count of files in that category.`, + tools: [categorizeDotfile], + output: s.object({ + dotfiles: s.record( + s.object({ + purpose: s.string, + category: s.enum("shell", "editor", "git", "ssh", "package-manager", "misc"), + }) + ), + totalFound: s.int, + categorySummary: s.record(s.int), + }), +}); + +export default dotfileInventoryMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts new file mode 100644 index 0000000..7693222 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts @@ -0,0 +1,54 @@ +import { agent, s, defineTool, repair } from "rig"; + +const runRegexTest = defineTool("runRegexTest", { + description: "Test a regex pattern against an input string and return whether it matches.", + parameters: s.object({ regex: s.string, input: s.string }), + handler({ regex, input }) { + try { + const matched = new RegExp(regex).test(input); + return { matched, error: undefined }; + } catch (e) { + return { matched: false, error: String(e) }; + } + }, +}); + +// Agent role: run all test cases for each regex pattern and report pass/fail results. +const regexPatternTester = agent({ + model: "typecheck", + addons: repair(), + input: s.object({ + patterns: s.array( + s.object({ + name: s.string, + regex: s.string, + testCases: s.array( + s.object({ input: s.string, shouldMatch: s.boolean }) + ), + }) + ), + }), + instructions: `For each pattern in the input, call runRegexTest for every test case. +A test case passes when the matched result equals shouldMatch. +Collect failedCases (input, expected, got) for each pattern. +A pattern passes when all test cases pass. +Count passCount (patterns where passed=true) and failCount. +allPassed is true when failCount === 0.`, + tools: [runRegexTest], + output: s.object({ + results: s.array( + s.object({ + name: s.string, + passed: s.boolean, + failedCases: s.array( + s.object({ input: s.string, expected: s.boolean, got: s.boolean }) + ), + }) + ), + passCount: s.int, + failCount: s.int, + allPassed: s.boolean, + }), +}); + +export default regexPatternTester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts new file mode 100644 index 0000000..1a3fec5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts @@ -0,0 +1,36 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const classifyRisk = defineTool("classifyRisk", { + description: "Classify a file's churn risk level based on how many times it has changed.", + parameters: s.object({ churnCount: s.int }), + handler({ churnCount }) { + if (churnCount <= 3) return "stable" as const; + if (churnCount <= 10) return "active" as const; + if (churnCount <= 25) return "volatile" as const; + return "critical" as const; + }, +}); + +// Agent role: analyze git commit history to classify file churn risk. +const commitChurnClassifier = agent({ + model: "typecheck", + addons: steering(), + instructions: p`Analyze file churn from git commit history. + +File change frequency (count + filename): +${p.bash("git log --name-only --format='' | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} + +For each line, parse the count and file path. +Call classifyRisk with the churnCount to get the riskLevel. +Build a record keyed by file path with churnCount and riskLevel. +Include only files that appear in the output above.`, + tools: [classifyRisk], + output: s.record( + s.object({ + churnCount: s.int, + riskLevel: s.enum("stable", "active", "volatile", "critical"), + }) + ), +}); + +export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts new file mode 100644 index 0000000..4afc492 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts @@ -0,0 +1,39 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifySize = defineTool("classifySize", { + description: "Classify a package size into a tier based on kilobytes.", + parameters: s.object({ sizeKb: s.number }), + handler({ sizeKb }) { + if (sizeKb < 10) return "tiny" as const; + if (sizeKb < 100) return "small" as const; + if (sizeKb < 500) return "medium" as const; + if (sizeKb < 2000) return "large" as const; + return "xlarge" as const; + }, +}); + +// Agent role: estimate NPM package publish size and classify it. +const npmPackageSizeEstimator = agent({ + model: "typecheck", + instructions: p`Estimate the published NPM package size. + +npm pack dry-run output: +${p.bash("npm pack --dry-run 2>&1")} + +Parse the output to find: +1. The total package size in KB (look for "package size:" or "Tarball Details" lines). +2. The top individual files with their sizes. + +Call classifySize with the estimatedSizeKb to get the sizeRating. +List the top files (up to 10) as topFiles array with path and sizeKb. +Write a brief recommendation about the package size.`, + tools: [classifySize], + output: s.object({ + estimatedSizeKb: s.number, + topFiles: s.array(s.object({ path: s.string, sizeKb: s.number })), + sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), + recommendation: s.string, + }), +}); + +export default npmPackageSizeEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts new file mode 100644 index 0000000..a59b557 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts @@ -0,0 +1,52 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze TypeScript file content to identify branches and their coverage. +const branchAnalyzer = agent({ + model: "typecheck", + instructions: `Given the TypeScript file content below, identify all branch points. +For each branch, extract: functionName (surrounding function or "module-level"), line number, +branchType (if/ternary/switch/logical/nullish), and covered (true if the branch has a test or always executes). +Return the branches array.`, + input: s.object({ fileContent: s.string, filePath: s.string }), + output: s.array( + s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "logical", "nullish"), + covered: s.boolean, + }) + ), +}); + +// Agent role: coordinate branch coverage analysis for a TypeScript file. +const tsBranchCoverageAnalyzer = agent({ + model: "typecheck", + input: s.object({ filePath: s.string }), + instructions: p`Analyze TypeScript branch coverage for the file at the path provided in input. + +Read the file content: +${p.readInput("filePath")} + +Delegate analysis to the branchAnalyzer subagent passing fileContent and filePath. +Aggregate the results: count totalBranches, coveredBranches, uncoveredBranches. +Compute coveragePercent as (coveredBranches / totalBranches * 100), 0 if no branches.`, + agents: { branchAnalyzer }, + output: s.object({ + branches: s.array( + s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "logical", "nullish"), + covered: s.boolean, + }) + ), + summary: s.object({ + totalBranches: s.int, + coveredBranches: s.int, + uncoveredBranches: s.int, + coveragePercent: s.number, + }), + }), +}); + +export default tsBranchCoverageAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts new file mode 100644 index 0000000..c5848f4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool } from "rig"; + +const inferType = defineTool("inferType", { + description: "Infer the type of an environment variable value using regex patterns.", + parameters: s.object({ key: s.string, value: s.string }), + handler({ value }) { + if (/^\d+(\.\d+)?$/.test(value)) return "number" as const; + if (/^(true|false)$/i.test(value)) return "boolean" as const; + if (/^https?:\/\//.test(value)) return "url" as const; + if (/^[/~.]/.test(value)) return "path" as const; + if (value.length === 0) return "unknown" as const; + return "string" as const; + }, +}); + +// Agent role: read .env.example and infer the type of each variable. +const envVariableTypeInferrer = agent({ + model: "typecheck", + instructions: p`Infer types for environment variables from .env.example. + +File contents: +${p.readOptional(".env.example", "# no .env.example found")} + +For each non-comment, non-empty line, parse KEY=VALUE. +Call inferType with the key and value to determine the type. +Write a one-line description for each variable based on its key name and inferred type. +Build the variables record keyed by variable name. +Set allDocumented to true if all variables have non-empty descriptions.`, + tools: [inferType], + output: s.object({ + variables: s.record( + s.object({ + type: s.enum("string", "number", "boolean", "url", "path", "unknown"), + description: s.string, + }) + ), + allDocumented: s.boolean, + }), +}); + +export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts new file mode 100644 index 0000000..278d132 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const checkHooksDir = defineTool("checkHooksDir", { + description: "Check if the .git/hooks directory exists.", + parameters: s.object({}), + async handler() { + const { access } = await import("node:fs/promises"); + try { + await access(".git/hooks"); + return { exists: true }; + } catch { + return { exists: false }; + } + }, +}); + +// Agent role: install git hook scripts into .git/hooks for the current repository. +const gitHookInstaller = agent({ + model: "typecheck", + addons: repair(), + input: s.object({ + hooks: s.array( + s.object({ + name: s.string, + script: s.string, + description: s.string, + }) + ), + }), + instructions: p`Install git hook scripts into the .git/hooks directory. + +Existing hooks directory: +${p.bash("ls .git/hooks 2>/dev/null || echo 'no .git/hooks directory'")} + +First call checkHooksDir to verify the directory exists. +For each hook in input.hooks: +- If .git/hooks exists, write the script to .git/hooks/ using a write operation, then run chmod +x via bash. +- If .git/hooks does not exist, add the hook name to skippedHooks. +Track writtenHooks as array of { name, path } for each successfully written hook. +Set totalWritten and allWritten accordingly.`, + tools: [checkHooksDir], + output: s.object({ + writtenHooks: s.array(s.object({ name: s.string, path: s.string })), + skippedHooks: s.array(s.string), + totalWritten: s.int, + allWritten: s.boolean, + }), +}); + +export default gitHookInstaller; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts new file mode 100644 index 0000000..53284cd --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts @@ -0,0 +1,42 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const extractInterfaces = defineTool("extractInterfaces", { + description: "Extract interface names from a TypeScript source file.", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf8"); + const matches = [...content.matchAll(/interface\s+(\w+)/g)]; + return { interfaceNames: matches.map((m: RegExpMatchArray) => m[1] as string) }; + } catch { + return { interfaceNames: [] }; + } + }, +}); + +// Agent role: generate TypeScript type guard functions for each interface in a source file. +const tsTypeGuardGenerator = agent({ + model: "typecheck", + addons: repair(), + input: s.object({ sourceFile: s.path, outputFile: s.path }), + instructions: p`Generate TypeScript type guard functions for interfaces found in a source file. + +Source file content: +${p.readInput("sourceFile")} + +1. Call extractInterfaces with the sourceFile path to get all interface names. +2. For each interface, generate a type guard function: \`function is(val: unknown): val is \`. +3. Write the generated guard functions to the outputFile path. +4. Return generatedGuards listing interfaceName and guardFunctionName for each guard.`, + tools: [extractInterfaces], + output: s.object({ + generatedGuards: s.array( + s.object({ interfaceName: s.string, guardFunctionName: s.string }) + ), + outputFile: s.path, + totalGenerated: s.int, + }), +}); + +export default tsTypeGuardGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts new file mode 100644 index 0000000..e9cb084 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts @@ -0,0 +1,46 @@ +import { agent, p, s, defineTool } from "rig"; + +const anonymizeValue = defineTool("anonymizeValue", { + description: "Return an anonymized replacement for a field value based on its name and type.", + parameters: s.object({ fieldName: s.string, value: s.unknown, fieldType: s.string }), + handler({ fieldName, fieldType }) { + const name = fieldName.toLowerCase(); + if (name.includes("email")) return "[email@example.com]"; + if (name.includes("phone") || name.includes("tel")) return "[000-000-0000]"; + if (name.includes("name") || name.includes("user")) return "[REDACTED_NAME]"; + if (name.includes("address") || name.includes("street")) return "[REDACTED_ADDRESS]"; + if (name.includes("ip")) return "0.0.0.0"; + if (fieldType === "number") return 0; + if (fieldType === "boolean") return false; + return "[REDACTED]"; + }, +}); + +// Agent role: anonymize sensitive fields in a JSON fixture file. +const jsonFixtureAnonymizer = agent({ + model: "typecheck", + input: s.object({ + inputFile: s.path, + outputFile: s.path, + fieldsToAnonymize: s.array(s.string), + }), + instructions: p`Anonymize sensitive fields in a JSON fixture file. + +Input file content: +${p.readInput("inputFile")} + +For each field name in input.fieldsToAnonymize, call anonymizeValue with the field name, +current value, and value type to get the replacement. +Replace all matching field values throughout the JSON structure. +Write the anonymized JSON to input.outputFile. +Count fieldsAnonymized (total replacements made) and totalRecords (array length or 1 for object).`, + tools: [anonymizeValue], + output: s.object({ + fieldsAnonymized: s.int, + totalRecords: s.int, + outputPath: s.path, + anonymizedFields: s.array(s.string), + }), +}); + +export default jsonFixtureAnonymizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts new file mode 100644 index 0000000..4aaa1a0 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts @@ -0,0 +1,40 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseCSVRow = defineTool("parseCSVRow", { + description: "Split a CSV line into trimmed cell values.", + parameters: s.object({ line: s.string, delimiter: s.string }), + handler({ line, delimiter }) { + return { cells: line.split(delimiter).map((cell: string) => cell.trim()) }; + }, +}); + +// Agent role: convert a CSV file to a Markdown table and write it to an output file. +const csvToMarkdownTable = agent({ + model: "typecheck", + addons: repair(), + input: s.object({ + csvFile: s.path, + outputFile: s.path, + includeStats: s.boolean, + }), + instructions: p`Convert a CSV file to a Markdown table. + +CSV file content: +${p.readInput("csvFile")} + +1. Call parseCSVRow for the first line with delimiter "," to get the headers. +2. Call parseCSVRow for each subsequent non-empty line to get row cells. +3. Build a Markdown table: header row, separator row (---), then data rows. +4. If input.includeStats is true, append a stats section with row/column counts. +5. Write the complete Markdown output to input.outputFile. +6. Return rowCount (data rows), columnCount, outputFile path, and headers array.`, + tools: [parseCSVRow], + output: s.object({ + rowCount: s.int, + columnCount: s.int, + outputFile: s.path, + headers: s.array(s.string), + }), +}); + +export default csvToMarkdownTable; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts new file mode 100644 index 0000000..b7b73ed --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts @@ -0,0 +1,16 @@ +import { agent, s } from "rig"; +// Agent role: plan safe dependency upgrades. +const upgradePlan = agent({ + model: "typecheck", + output: s.object({ + upgrades: s.array(s.object({ + package: s.string, + from: s.string, + to: s.string, + risk: s.string + })), + order: s.array(s.string) + }), + instructions: `Plan safe dependency upgrades.`, +}); +export default upgradePlan; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts new file mode 100644 index 0000000..2652e51 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts @@ -0,0 +1,27 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: classify repository files by commit churn frequency and assign a risk level. +const commitChurnClassifier = agent({ + model: "typecheck", + addons: steering({ message: "Be precise: assign riskLevel based on churnCount: >20=critical, >10=volatile, >5=active, else stable." }), + instructions: p`Classify repository files by how frequently they are committed (churn). + +File churn counts from last 200 commits: +${p.bash("git log --name-only --format='' HEAD~200..HEAD 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -40")} + +For each file, parse the churn count and assign a riskLevel: +- critical: churnCount > 20 +- volatile: churnCount > 10 +- active: churnCount > 5 +- stable: churnCount <= 5 + +Return a record keyed by file path with churnCount (integer) and riskLevel.`, + output: s.record( + s.object({ + churnCount: s.int, + riskLevel: s.enum("stable", "active", "volatile", "critical"), + }) + ), +}); + +export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts new file mode 100644 index 0000000..f63a55e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts @@ -0,0 +1,37 @@ +import { agent, defineTool, p, s } from "rig"; + +const classifySize = defineTool("classifySize", { + description: "Classify a package size in KB into a tier rating.", + parameters: s.object({ sizeKb: s.number }), + handler({ sizeKb }: { sizeKb: number }) { + if (sizeKb < 10) return "tiny" as const; + if (sizeKb < 100) return "small" as const; + if (sizeKb < 500) return "medium" as const; + if (sizeKb < 2000) return "large" as const; + return "xlarge" as const; + }, +}); + +// Agent role: estimate the NPM package size and rate it by tier. +const npmPackageSizeEstimator = agent({ + model: "typecheck", + instructions: p`Estimate the NPM package size for this project. + +Pack dry-run output: +${p.bash("npm pack --dry-run 2>&1 | tail -20")} + +Directory size: +${p.bash("du -sh . 2>/dev/null | head -5")} + +Use classifySize tool with the estimated total size in KB to get the sizeRating. +List the top files by size and provide a brief recommendation.`, + tools: [classifySize], + output: s.object({ + estimatedSizeKb: s.number, + topFiles: s.array(s.object({ name: s.string, sizeKb: s.number })), + sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), + recommendation: s.string, + }), +}); + +export default npmPackageSizeEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts new file mode 100644 index 0000000..49e35fc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts @@ -0,0 +1,40 @@ +import { agent, p, s } from "rig"; + +const branchItem = s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "nullish"), + covered: s.boolean, +}); + +// Agent role: extract all branch points from the provided TypeScript source code. +const branchAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze the TypeScript source code provided in the input and list every branch point (if/ternary/switch/nullish coalescing). For each branch, identify the enclosing function name, line number, branch type, and whether it appears covered (has a test or usage path). Return an array of branch objects.`, + input: s.object({ filePath: s.path }), + output: s.array(branchItem), +}); + +// Agent role: coordinate branch coverage analysis for a TypeScript file. +const tsBranchCoverageAnalyzer = agent({ + model: "typecheck", + input: s.object({ filePath: s.path }), + instructions: p`Perform branch coverage analysis on a TypeScript file. + +File content: +${p.readInput("filePath")} + +Delegate the analysis to the branchAnalyzer subagent, passing the filePath. +Collect its output (an array of branch objects), then compute a summary with totalBranches, coveredBranches, and uncoveredBranches counts.`, + output: s.object({ + branches: s.array(branchItem), + summary: s.object({ + totalBranches: s.int, + coveredBranches: s.int, + uncoveredBranches: s.int, + }), + }), + agents: { branchAnalyzer }, +}); + +export default tsBranchCoverageAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts new file mode 100644 index 0000000..e0b74be --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts @@ -0,0 +1,37 @@ +import { agent, defineTool, p, s } from "rig"; + +const inferVarType = defineTool("inferVarType", { + description: "Infer the type of an environment variable value using regex heuristics.", + parameters: s.object({ value: s.string }), + handler({ value }: { value: string }) { + if (/^https?:\/\//i.test(value)) return "url" as const; + if (/^(true|false|yes|no|1|0)$/i.test(value)) return "boolean" as const; + if (/^\d+(\.\d+)?$/.test(value)) return "number" as const; + if (/^(\/|\.\/|~\/)/.test(value) || /\.(txt|json|yaml|yml|pem|key|crt)$/.test(value)) return "path" as const; + if (value === "") return "unknown" as const; + return "string" as const; + }, +}); + +// Agent role: infer types for all environment variables defined in .env.example. +const envVariableTypeInferrer = agent({ + model: "typecheck", + instructions: p`Infer the type of each environment variable defined in the .env.example file. + +.env.example contents: +${p.readOptional(".env.example", "(no .env.example found)")} + +For each KEY=VALUE line, call inferVarType with the value to get its type. Generate a short description of what each variable likely controls. Set allDocumented to true only if every variable has a non-empty value or inline comment hint.`, + tools: [inferVarType], + output: s.object({ + vars: s.record( + s.object({ + type: s.enum("string", "number", "boolean", "url", "path", "unknown"), + description: s.string, + }) + ), + allDocumented: s.boolean, + }), +}); + +export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts new file mode 100644 index 0000000..fae0e4f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts @@ -0,0 +1,58 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const parseTargets = defineTool("parseTargets", { + description: "Parse Makefile content to extract phony and real targets with descriptions.", + parameters: s.object({ content: s.string }), + handler({ content }: { content: string }) { + const lines = content.split("\n"); + const phonySet = new Set(); + const targets: Array<{ name: string; isPhony: boolean; hasHelp: boolean; description?: string }> = []; + + for (const line of lines) { + const phonyMatch = line.match(/^\.PHONY\s*:\s*(.+)/); + if (phonyMatch) { + for (const t of phonyMatch[1].split(/\s+/)) phonySet.add(t.trim()); + } + } + + const targetRe = /^([a-zA-Z0-9_\-./]+)\s*:/; + for (let i = 0; i < lines.length; i++) { + const m = lines[i].match(targetRe); + if (m && !m[1].startsWith(".")) { + const name = m[1]; + const helpLine = i > 0 ? lines[i - 1] : ""; + const hasHelp = /##/.test(helpLine) || /##/.test(lines[i]); + const description = helpLine.match(/##\s*(.+)/)?.[1]?.trim(); + targets.push({ name, isPhony: phonySet.has(name), hasHelp, ...(description ? { description } : {}) }); + } + } + return targets; + }, +}); + +// Agent role: extract and classify Makefile targets. +const makefileTargetExtractor = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Extract and classify targets from the project Makefile. + +Makefile contents: +${p.readOptional("Makefile", "(no Makefile found)")} + +Call parseTargets with the full Makefile content. Return the array of targets and include totalCount (all targets) and phonyCount (targets where isPhony is true).`, + tools: [parseTargets], + output: s.object({ + targets: s.array( + s.object({ + name: s.string, + isPhony: s.boolean, + hasHelp: s.boolean, + description: s.optional(s.string), + }) + ), + totalCount: s.int, + phonyCount: s.int, + }), +}); + +export default makefileTargetExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts new file mode 100644 index 0000000..0c59a98 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts @@ -0,0 +1,37 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze a function signature and return its parameters and return type. +const signatureAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze the TypeScript source provided in the input. Extract the signature details for the specified function: its parameters (name and type), return type, and any JSDoc description. Return structured signature details.`, + input: s.object({ sourceFile: s.path, functionName: s.string }), + output: s.object({ + functionName: s.string, + parameters: s.array(s.object({ name: s.string, type: s.string })), + returnType: s.string, + description: s.optional(s.string), + }), +}); + +// Agent role: generate a test fixture for a specific function in a TypeScript source file. +const testFixtureGenerator = agent({ + model: "typecheck", + input: s.object({ sourceFile: s.path, functionName: s.string }), + instructions: p`Generate a test fixture file for the specified function. + +Source file content: +${p.readInput("sourceFile")} + +1. Delegate to signatureAnalyzer to get the function signature for the function named in the input. +2. Using the signature, generate fixture code: example inputs, mock helpers, and a vitest describe block. +3. Write the fixture code to fixture.ts: ${p.writeOutput("fixtureCode", "fixture.ts")} +4. Return fixtureCode (the full fixture source), the required imports, and suggestedFileName.`, + output: s.object({ + fixtureCode: s.string, + imports: s.array(s.string), + suggestedFileName: s.path, + }), + agents: { signatureAnalyzer }, +}); + +export default testFixtureGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts new file mode 100644 index 0000000..d3c02e6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const analyzeTomlFile = defineTool("analyzeTomlFile", { + description: "Read a TOML file and extract its top-level section headers and key count.", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }: { filePath: string }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf8"); + const sections = [...content.matchAll(/^\[([^\]]+)\]/gm)].map((m: RegExpMatchArray) => m[1] as string); + const keyCount = (content.match(/^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*=/gm) ?? []).length; + const hasRequired = sections.includes("package") || sections.includes("tool") || keyCount > 0; + return { sections, keyCount, hasRequired }; + } catch { + return { sections: [], keyCount: 0, hasRequired: false }; + } + }, +}); + +// Agent role: analyze all TOML config files in the workspace and summarize their sections. +const tomlConfigAnalyzer = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Analyze all TOML config files found in the workspace. + +TOML files found: +${p.glob("**/*.toml")} + +For each file path listed above, call analyzeTomlFile to extract its sections, keyCount, and hasRequired flag. Return a record keyed by file path.`, + tools: [analyzeTomlFile], + output: s.record( + s.object({ + sections: s.array(s.string), + keyCount: s.int, + hasRequired: s.boolean, + }) + ), +}); + +export default tomlConfigAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts new file mode 100644 index 0000000..38b8d91 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts @@ -0,0 +1,40 @@ +import { agent, defineTool, p, s } from "rig"; + +const classifyCheckpoint = defineTool("classifyCheckpoint", { + description: "Classify a git checkpoint line as stash, commit, tag, or branch.", + parameters: s.object({ line: s.string }), + handler({ line }: { line: string }) { + if (line.startsWith("stash@{")) return "stash" as const; + if (/^refs\/tags\//.test(line)) return "tag" as const; + if (/^refs\/heads\//.test(line)) return "branch" as const; + return "commit" as const; + }, +}); + +// Agent role: summarize git checkpoints (stashes and recent commits) in the repository. +const gitCheckpointSummarizer = agent({ + model: "typecheck", + instructions: p`Summarize the git checkpoints (stashes and recent commits) for this repository. + +Stash list: +${p.bash("git stash list 2>/dev/null || echo '(no stashes)'")} + +Recent commits: +${p.bash("git log --oneline -20 2>/dev/null || echo '(no commits)'")} + +For each stash entry and each commit line, call classifyCheckpoint to determine its type. Build the checkpoints array with ref, type, and message fields. Set latestCheckpoint to the most recent commit hash or stash ref, and totalCount to the combined count.`, + tools: [classifyCheckpoint], + output: s.object({ + checkpoints: s.array( + s.object({ + ref: s.string, + type: s.enum("stash", "commit", "tag", "branch"), + message: s.string, + }) + ), + latestCheckpoint: s.optional(s.string), + totalCount: s.int, + }), +}); + +export default gitCheckpointSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts new file mode 100644 index 0000000..df463d7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts @@ -0,0 +1,44 @@ +import { agent, defineTool, p, s, steering } from "rig"; + +const extractLiteralUnions = defineTool("extractLiteralUnions", { + description: "Extract string literal union type declarations from a TypeScript file.", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }: { filePath: string }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf8"); + const re = /type\s+(\w+)\s*=\s*((?:'[^']*'|"[^"]*")(?:\s*\|\s*(?:'[^']*'|"[^"]*"))+)/g; + const results: Record = {}; + for (const m of content.matchAll(re)) { + const name = m[1] as string; + const members = (m[2] as string).split("|").map((v: string) => v.trim().replace(/^['"]|['"]$/g, "")); + results[name] = { members, memberCount: members.length, isStringLiteral: true }; + } + return results; + } catch { + return {}; + } + }, +}); + +// Agent role: extract all string literal union type declarations from TypeScript files. +const tsLiteralUnionExtractor = agent({ + model: "typecheck", + addons: steering({ message: "Call extractLiteralUnions for each file path; merge results across all files." }), + instructions: p`Extract string literal union type declarations from all TypeScript source files. + +TypeScript files: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -40")} + +For each file path above, call extractLiteralUnions to get its literal union types. Merge all results into a single record keyed by type name with members, memberCount, and isStringLiteral.`, + tools: [extractLiteralUnions], + output: s.record( + s.object({ + members: s.array(s.string), + memberCount: s.int, + isStringLiteral: s.boolean, + }) + ), +}); + +export default tsLiteralUnionExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts new file mode 100644 index 0000000..fe62e70 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts @@ -0,0 +1,52 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const validateHeadings = defineTool("validateHeadings", { + description: "Parse heading structure from markdown content and validate level ordering.", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }: { filePath: string }) { + const { readFile } = await import("node:fs/promises"); + try { + const content = await readFile(filePath, "utf8"); + const headings: Array<{ level: number; text: string }> = []; + for (const m of content.matchAll(/^(#{1,6})\s+(.+)/gm)) { + headings.push({ level: (m[1] as string).length, text: (m[2] as string).trim() }); + } + const issues: string[] = []; + const h1Count = headings.filter((h: { level: number }) => h.level === 1).length; + if (h1Count > 1) issues.push(`Multiple H1 headings found (${h1Count})`); + if (h1Count === 0 && headings.length > 0) issues.push("No H1 heading found"); + for (let i = 1; i < headings.length; i++) { + if (headings[i].level - headings[i - 1].level > 1) { + issues.push(`Skipped heading level at "${headings[i].text}" (level ${headings[i].level} after level ${headings[i - 1].level})`); + } + } + const maxDepth = headings.reduce((max: number, h: { level: number }) => Math.max(max, h.level), 0); + return { headings, maxDepth, isValid: issues.length === 0, issues }; + } catch { + return { headings: [], maxDepth: 0, isValid: false, issues: ["Could not read file"] }; + } + }, +}); + +// Agent role: validate the heading structure of all markdown files in the workspace. +const markdownHeadingValidator = agent({ + model: "typecheck", + addons: repair(), + instructions: p`Validate the heading structure of all markdown files in the workspace. + +Markdown files: +${p.glob("**/*.md")} + +For each file path above, call validateHeadings to check its heading structure. Return a record keyed by file path with headings array, maxDepth, isValid, and any issues found.`, + tools: [validateHeadings], + output: s.record( + s.object({ + headings: s.array(s.object({ level: s.int, text: s.string })), + maxDepth: s.int, + isValid: s.boolean, + issues: s.array(s.string), + }) + ), +}); + +export default markdownHeadingValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts new file mode 100644 index 0000000..1a08ef4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts @@ -0,0 +1,16 @@ +import { agent, s } from "rig"; +// Agent role: flag unknown or concerning dependency licenses. +const licenseCheck = agent({ + model: "typecheck", + output: s.object({ + compliant: s.boolean, + unknown: s.array(s.string), + concerning: s.array(s.object({ + package: s.string, + license: s.string, + reason: s.string + })) + }), + instructions: `Flag unknown or concerning dependency licenses.`, +}); +export default licenseCheck; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts new file mode 100644 index 0000000..d2ee4b1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts @@ -0,0 +1,26 @@ +import { agent, p, s, defineTool, steering, repair } from "rig"; + +const classifyRisk = defineTool("classifyRisk", { + description: "Classify churn risk level based on commit count", + parameters: s.object({ churnCount: s.int }), + handler: ({ churnCount }) => { + if (churnCount <= 2) return "stable" as const; + if (churnCount <= 5) return "active" as const; + if (churnCount <= 10) return "volatile" as const; + return "critical" as const; + }, +}); + +// Agent role: analyze git commit history to classify file churn and risk levels +const commitChurnClassifier = agent({ + model: "typecheck", + instructions: p`Analyze commit history from ${p.bash("git log --name-only --format='' | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} and classify each file's churn risk using the classifyRisk tool. Return a record keyed by file path.`, + output: s.record(s.object({ + churnCount: s.int, + riskLevel: s.enum("stable", "active", "volatile", "critical"), + })), + tools: [classifyRisk], + addons: [steering(), repair()], +}); + +export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts new file mode 100644 index 0000000..b667b7e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts @@ -0,0 +1,33 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const classifySize = defineTool("classifySize", { + description: "Classify a package size in KB into a tier rating", + parameters: s.object({ sizeKb: s.number }), + handler: ({ sizeKb }) => { + if (sizeKb < 50) return "tiny" as const; + if (sizeKb < 200) return "small" as const; + if (sizeKb < 500) return "medium" as const; + if (sizeKb < 2000) return "large" as const; + return "xlarge" as const; + }, +}); + +// Agent role: estimate the npm package size and classify it into a tier rating +const npmPackageSizeEstimator = agent({ + model: "typecheck", + instructions: p`Estimate this package's size using: +- Pack dry-run: ${p.bash("npm pack --dry-run 2>&1 | head -40")} +- Directory size: ${p.bash("du -sh . 2>/dev/null | head -5")} + +Use the classifySize tool to determine the tier rating. Return estimatedSizeKb, topFiles (up to 5 files with their sizes), sizeRating, and a recommendation.`, + output: s.object({ + estimatedSizeKb: s.number, + topFiles: s.array(s.object({ name: s.string, sizeKb: s.number })), + sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), + recommendation: s.string, + }), + tools: [classifySize], + addons: [repair()], +}); + +export default npmPackageSizeEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts new file mode 100644 index 0000000..9cfefad --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts @@ -0,0 +1,38 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze TypeScript source for branch coverage patterns +const branchAnalyzer = agent({ + name: "branchAnalyzer", + model: "typecheck", + instructions: p`Analyze the TypeScript source provided in the input and identify all branches (if/ternary/switch/logical). For each branch, determine the function name, line number, branch type, and whether it is likely covered based on test presence. Return a detailed array of branch objects.`, + input: s.object({ source: s.string }), + output: s.array(s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "logical"), + covered: s.boolean, + })), +}); + +// Agent role: coordinate branch coverage analysis for a TypeScript file +const tsBranchCoverageAnalyzer = agent({ + model: "typecheck", + instructions: p`Read the TypeScript file at the path in the input using the readInput intent and delegate branch analysis to the branchAnalyzer subagent. Compute totalBranches, coveredBranches, and uncoveredBranches from the results.`, + input: s.object({ filePath: s.path }), + output: s.object({ + branches: s.array(s.object({ + functionName: s.string, + line: s.int, + branchType: s.enum("if", "ternary", "switch", "logical"), + covered: s.boolean, + })), + summary: s.object({ + totalBranches: s.int, + coveredBranches: s.int, + uncoveredBranches: s.int, + }), + }), + agents: { branchAnalyzer }, +}); + +export default tsBranchCoverageAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts new file mode 100644 index 0000000..af18b29 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts @@ -0,0 +1,31 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const inferType = defineTool("inferType", { + description: "Infer the type of an environment variable value", + parameters: s.object({ key: s.string, value: s.string }), + handler: ({ value }) => { + if (value === "true" || value === "false") return "boolean" as const; + if (/^\d+(\.\d+)?$/.test(value)) return "number" as const; + if (/^https?:\/\//.test(value)) return "url" as const; + if (/^[./~]|^\$HOME/.test(value)) return "path" as const; + if (value.length === 0 || value.startsWith("<") || value.startsWith("#")) return "unknown" as const; + return "string" as const; + }, +}); + +// Agent role: infer types of environment variables from .env.example +const envVariableTypeInferrer = agent({ + model: "typecheck", + instructions: p`Analyze the environment variable definitions from ${p.readOptional(".env.example", "# no .env.example found")} and use the inferType tool for each variable. Produce a record of variable names to their inferred type and description, plus allDocumented indicating whether all variables have non-empty descriptions.`, + output: s.object({ + variables: s.record(s.object({ + type: s.enum("string", "number", "boolean", "url", "path", "unknown"), + description: s.string, + })), + allDocumented: s.boolean, + }), + tools: [inferType], + addons: [repair()], +}); + +export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts new file mode 100644 index 0000000..a5f7833 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts @@ -0,0 +1,37 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseTarget = defineTool("parseTarget", { + description: "Parse a Makefile target line and return its metadata", + parameters: s.object({ line: s.string, phonyTargets: s.string }), + handler: ({ line, phonyTargets }) => { + const match = line.match(/^([a-zA-Z0-9_.-]+)\s*:/); + if (!match) return null; + const name = match[1]; + const isPhony = phonyTargets.includes(name); + const hasHelp = line.includes("##"); + const descMatch = line.match(/##\s*(.+)/); + return { name, isPhony, hasHelp, description: descMatch ? descMatch[1].trim() : undefined }; + }, +}); + +// Agent role: extract and classify targets from a Makefile +const makefileTargetExtractor = agent({ + model: "typecheck", + instructions: p`Parse the Makefile content: ${p.readOptional("Makefile", "# no Makefile found")} + +Use the parseTarget tool for each target line. Collect all targets and their metadata, count phony vs real targets, and return the structured result.`, + output: s.object({ + targets: s.array(s.object({ + name: s.string, + isPhony: s.boolean, + hasHelp: s.boolean, + description: s.optional(s.string), + })), + totalCount: s.int, + phonyCount: s.int, + }), + tools: [parseTarget], + addons: [repair()], +}); + +export default makefileTargetExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts new file mode 100644 index 0000000..aba9aa2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts @@ -0,0 +1,33 @@ +import { agent, p, s } from "rig"; + +// Agent role: extract function signature from a TypeScript source file +const signatureAnalyzer = agent({ + name: "signatureAnalyzer", + model: "typecheck", + instructions: p`Given the TypeScript source in the input, extract the signature for the function named in functionName. Return the parameter types, return type, and any imports needed to use this function in a test.`, + input: s.object({ source: s.string, functionName: s.string }), + output: s.object({ + params: s.array(s.object({ name: s.string, type: s.string })), + returnType: s.string, + imports: s.array(s.string), + }), +}); + +// Agent role: generate test fixtures for a TypeScript function +const testFixtureGenerator = agent({ + model: "typecheck", + instructions: p`Generate a test fixture for the function specified in the input. + +Read the source file: ${p.readInput("sourceFile")} + +Delegate signature extraction to the signatureAnalyzer subagent for the function named in the input's functionName field. Then generate a complete test fixture file with sample inputs, expected outputs, and required imports. Write the fixture to the path in suggestedFileName.`, + input: s.object({ sourceFile: s.path, functionName: s.string }), + output: s.object({ + fixtureCode: s.string, + imports: s.array(s.string), + suggestedFileName: s.path, + }), + agents: { signatureAnalyzer }, +}); + +export default testFixtureGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts new file mode 100644 index 0000000..8f95557 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool, steering } from "rig"; +import { execSync } from "node:child_process"; + +const getFileOwner = defineTool("getFileOwner", { + description: "Get git ownership info for a file path", + parameters: s.object({ filePath: s.path }), + handler: async ({ filePath }) => { + try { + const output = execSync(`git log --format="%ae" -- "${filePath}" 2>/dev/null`, { encoding: "utf8" }); + const emails = output.trim().split("\n").filter((e: string) => e.length > 0); + const counts: Record = {}; + for (const email of emails) { + counts[email] = (counts[email] ?? 0) + 1; + } + const sorted = Object.entries(counts).sort((a: [string, number], b: [string, number]) => b[1] - a[1]); + const primaryOwner = sorted[0]?.[0] ?? "unknown"; + const commitCount = emails.length; + const contributors = sorted.map((e: [string, number]) => e[0]); + return { primaryOwner, commitCount, contributors }; + } catch { + return { primaryOwner: "unknown", commitCount: 0, contributors: [] }; + } + }, +}); + +// Agent role: map git file ownership by analyzing commit history for TypeScript files +const gitFileOwnershipMapper = agent({ + model: "typecheck", + instructions: p`Discover TypeScript source files: ${p.glob("src/**/*.ts")} + +Use the getFileOwner tool for each discovered file path to collect ownership data. Build a complete ownership record and identify the mostActiveContributor across all files.`, + output: s.object({ + ownership: s.record(s.object({ + primaryOwner: s.string, + commitCount: s.int, + contributors: s.array(s.string), + })), + mostActiveContributor: s.string, + }), + tools: [getFileOwner], + addons: [steering()], +}); + +export default gitFileOwnershipMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts new file mode 100644 index 0000000..4033d16 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts @@ -0,0 +1,48 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const validateWorkflowInputs = defineTool("validateWorkflowInputs", { + description: "Parse workflow_dispatch inputs from a GitHub Actions workflow YAML file", + parameters: s.object({ filePath: s.path }), + handler: async ({ filePath }) => { + const content = await readFile(filePath, "utf8"); + const inputSection = content.match(/workflow_dispatch:[\s\S]*?inputs:([\s\S]*?)(?=\n\S|\n\w+:|\n [a-z]+:(?!\s*\n\s+type:)|\Z)/)?.[1] ?? ""; + const inputMatches = [...inputSection.matchAll(/^\s{6}(\w[\w-]*):/gm)]; + const inputs = inputMatches.map((m: RegExpMatchArray) => { + const name = m[1]; + const block = inputSection.slice(m.index ?? 0, (m.index ?? 0) + 300); + const type = block.match(/type:\s*(\w+)/)?.[1] ?? "string"; + const required = /required:\s*true/.test(block); + const hasDefault = /default:/.test(block); + return { name, type, required, hasDefault }; + }); + return { + inputs, + inputCount: inputs.length, + hasRequiredWithoutDefault: inputs.some((i: { required: boolean; hasDefault: boolean }) => i.required && !i.hasDefault), + }; + }, +}); + +// Agent role: validate GitHub Actions workflow_dispatch inputs across all workflow files +const workflowInputValidator = agent({ + model: "typecheck", + instructions: p`Validate workflow_dispatch inputs in all workflow files discovered at ${p.glob(".github/workflows/*.yml")}. Use the validateWorkflowInputs tool for each file path. Return a record keyed by filename and the total workflow count.`, + output: s.object({ + workflows: s.record(s.object({ + inputs: s.array(s.object({ + name: s.string, + type: s.string, + required: s.boolean, + hasDefault: s.boolean, + })), + inputCount: s.int, + hasRequiredWithoutDefault: s.boolean, + })), + totalWorkflows: s.int, + }), + tools: [validateWorkflowInputs], + addons: [repair()], +}); + +export default workflowInputValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts new file mode 100644 index 0000000..d43f6d7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool, steering, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const findUnusedExports = defineTool("findUnusedExports", { + description: "Find exported symbols in a TypeScript file that are not imported elsewhere", + parameters: s.object({ filePath: s.path, allFiles: s.array(s.string) }), + handler: async ({ filePath, allFiles }) => { + const content = await readFile(filePath, "utf8"); + const exportMatches = [...content.matchAll(/export\s+(?:const|function|class|type|interface|enum)\s+(\w+)/g)]; + const exportedNames = exportMatches.map((m: RegExpMatchArray) => m[1]); + const unusedNames: string[] = []; + for (const name of exportedNames) { + let isImported = false; + for (const other of allFiles) { + if (other === filePath) continue; + try { + const otherContent = await readFile(other, "utf8"); + if (otherContent.includes(name)) { isImported = true; break; } + } catch { /* skip */ } + } + if (!isImported) unusedNames.push(name); + } + return unusedNames; + }, +}); + +// Agent role: find unused TypeScript exports across the src directory +const tsDeadExportFinder = agent({ + model: "typecheck", + instructions: p`Find potentially dead (unused) TypeScript exports. +Files with exports: ${p.bash("grep -rl 'export ' src/ --include='*.ts' 2>/dev/null | head -20 || echo 'none'")} +All TS files: ${p.glob("src/**/*.ts")} + +Use the findUnusedExports tool for each file that has exports, passing all discovered files. Build a record of unused exports keyed by file path, the total count, and whether dead code was found.`, + output: s.object({ + unusedExports: s.record(s.array(s.string)), + totalUnused: s.int, + hasDeadCode: s.boolean, + }), + tools: [findUnusedExports], + addons: [steering(), repair()], +}); + +export default tsDeadExportFinder; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts new file mode 100644 index 0000000..1898a4b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const inferScriptPurpose = defineTool("inferScriptPurpose", { + description: "Classify an npm script and suggest a one-line description of its purpose", + parameters: s.object({ name: s.string, command: s.string }), + handler: ({ name, command }: { name: string; command: string }) => { + const lname = name.toLowerCase(); + const lcmd = command.toLowerCase(); + let category: "build" | "test" | "lint" | "release" | "dev" | "other"; + if (lname.includes("build") || lcmd.includes("tsc") || lcmd.includes("webpack") || lcmd.includes("rollup") || lcmd.includes("vite build")) { + category = "build"; + } else if (lname.includes("test") || lcmd.includes("vitest") || lcmd.includes("jest") || lcmd.includes("mocha")) { + category = "test"; + } else if (lname.includes("lint") || lcmd.includes("eslint") || lcmd.includes("prettier")) { + category = "lint"; + } else if (lname.includes("release") || lname.includes("publish") || lname.includes("version")) { + category = "release"; + } else if (lname.includes("dev") || lname.includes("start") || lname.includes("watch")) { + category = "dev"; + } else { + category = "other"; + } + return { category }; + }, +}); + +// Agent role: document npm scripts from package.json and write a SCRIPTS.md file +const packageJsonScriptsDocumenter = agent({ + model: "typecheck", + instructions: p`Read the npm scripts from ${p.read("package.json")} and use the inferScriptPurpose tool for each script to classify it. Then write ${p.write("SCRIPTS.md", "scripts")} a well-structured markdown documentation file listing each script with its purpose, category, and command. Return the structured record of scripts, the count, and the output file path.`, + output: s.object({ + scripts: s.record(s.object({ + purpose: s.string, + category: s.enum("build", "test", "lint", "release", "dev", "other"), + command: s.string, + })), + documentedCount: s.int, + outputFile: s.path, + }), + tools: [inferScriptPurpose], + addons: [repair()], +}); + +export default packageJsonScriptsDocumenter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts new file mode 100644 index 0000000..53126b5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: draft a GitHub bug report from the failure details. +const bugReport = agent({ + model: "typecheck", + output: s.object({ + title: s.string, + body: s.string, + labels: s.array(s.string) + }), + instructions: `Draft a GitHub bug report from the failure details.`, +}); +export default bugReport; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts new file mode 100644 index 0000000..65b5122 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts @@ -0,0 +1,42 @@ +import { agent, p, s, defineTool, steering, repair } from "rig"; + +const parseUptimeEvent = defineTool("parseUptimeEvent", { + description: "Parse a log line to extract uptime lifecycle events", + parameters: s.object({ line: s.string }), + handler({ line }) { + const startedMatch = line.match(/(\S+\s+\S+\s+\S+).*\s(\S+(?:\[\d+\])?): .*[Ss]tarted/); + const stoppedMatch = line.match(/(\S+\s+\S+\s+\S+).*\s(\S+(?:\[\d+\])?): .*[Ss]topped/); + const crashMatch = line.match(/(\S+\s+\S+\s+\S+).*\s(\S+(?:\[\d+\])?): .*(?:[Cc]rash|[Kk]ill|exit.*code [^0])/); + if (crashMatch) return { timestamp: crashMatch[1] ?? "", service: crashMatch[2] ?? "", event: "crashed" as const }; + if (startedMatch) return { timestamp: startedMatch[1] ?? "", service: startedMatch[2] ?? "", event: "started" as const }; + if (stoppedMatch) return { timestamp: stoppedMatch[1] ?? "", service: stoppedMatch[2] ?? "", event: "stopped" as const }; + return { timestamp: "", service: "", event: "unknown" as const }; + }, +}); + +// Agent role: Parse system logs to identify service lifecycle events, crash counts, and uptime statistics. +const uptimeLogParser = agent({ + model: "typecheck", + instructions: p`Analyze the following system log lines to identify service lifecycle events. +Log lines: +${p.bash("journalctl -n 200 --no-pager 2>/dev/null || tail -n 200 /var/log/syslog 2>/dev/null || echo 'no logs'")} + +Use the parseUptimeEvent tool on relevant log lines that mention service starts, stops, or crashes. +Calculate totalUptimeHours as a rough estimate based on timestamps found. +Set hasCrashLoop to true if crashCount >= 3. +Return the structured output.`, + output: s.object({ + uptimeEvents: s.array(s.object({ + timestamp: s.string, + service: s.string, + event: s.enum("started", "stopped", "crashed", "unknown"), + })), + crashCount: s.int, + totalUptimeHours: s.number, + hasCrashLoop: s.boolean, + }), + tools: [parseUptimeEvent], + addons: [steering(), repair()], +}); + +export default uptimeLogParser; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts new file mode 100644 index 0000000..279d0dc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts @@ -0,0 +1,37 @@ +import { agent, p, s, defineTool, steering, repair } from "rig"; + +const parseCssVar = defineTool("parseCssVar", { + description: "Parse a CSS line to extract custom property (CSS variable) declarations", + parameters: s.object({ line: s.string }), + handler({ line }) { + const match = line.match(/^\s*(--[\w-]+)\s*:\s*(.+?)\s*;?\s*$/); + if (!match) return { name: "", value: "", found: false }; + return { name: match[1] ?? "", value: match[2] ?? "", found: true }; + }, +}); + +// Agent role: Scan CSS files to extract CSS custom property declarations and detect unused variables. +const cssVariableExtractor = agent({ + model: "typecheck", + instructions: p`Scan CSS files and extract all custom property (CSS variable) declarations. + +CSS file content (declarations and usages): +${p.bash("find . -name '*.css' -not -path '*/node_modules/*' | head -20 | xargs grep -h -- '--' 2>/dev/null | head -100 || echo 'no css files'")} + +Use the parseCssVar tool on each line that may contain a CSS variable declaration (--variable: value). +For each variable found, count how many times it appears as a usage (var(--name)). +A variable is unused if it is declared but never used via var(). +Return the structured output.`, + output: s.object({ + variables: s.record(s.object({ + value: s.string, + usageCount: s.int, + })), + unusedVars: s.array(s.string), + totalVars: s.int, + }), + tools: [parseCssVar], + addons: [steering(), repair()], +}); + +export default cssVariableExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts new file mode 100644 index 0000000..951dcc6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const extractRoutes = defineTool("extractRoutes", { + description: "Extract HTTP route patterns from router handler code", + parameters: s.object({ content: s.string }), + handler({ content }) { + const routes: Array<{ path: string; method: string }> = []; + const pattern = /router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/gi; + let m: RegExpExecArray | null; + while ((m = pattern.exec(content)) !== null) { + routes.push({ method: (m[1] ?? "get").toUpperCase(), path: m[2] ?? "/" }); + } + return routes; + }, +}); + +// Agent role: Compare OpenAPI spec routes against implemented router handlers to measure coverage. +const openapiRouteCoverage = agent({ + model: "typecheck", + instructions: p`Compare OpenAPI spec routes against implemented router handlers to determine coverage. + +OpenAPI spec: +${p.readOptional("openapi.json", "{}")} + +Router handler code: +${p.bash("grep -rn 'router\\.' --include='*.ts' --include='*.js' . 2>/dev/null | head -50 || echo 'no routes'")} + +Use the extractRoutes tool on the router handler code to discover implemented routes. +Cross-reference with paths defined in the OpenAPI spec. +Return routes array showing which are defined (in spec) vs implemented (in code). +Calculate coveragePercent as (totalImplemented / totalDefined * 100) or 0 if no spec.`, + output: s.object({ + routes: s.array(s.object({ + path: s.string, + method: s.string, + defined: s.boolean, + implemented: s.boolean, + })), + coveragePercent: s.number, + totalDefined: s.int, + totalImplemented: s.int, + }), + tools: [extractRoutes], + addons: [repair()], +}); + +export default openapiRouteCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts new file mode 100644 index 0000000..36b1eb9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts @@ -0,0 +1,40 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const classifyStyle = defineTool("classifyStyle", { + description: "Classify a file's module style based on require vs import counts", + parameters: s.object({ file: s.string, requireCount: s.int, importCount: s.int }), + handler({ requireCount, importCount }) { + if (requireCount === 0 && importCount === 0) return "unknown" as const; + if (requireCount > 0 && importCount > 0) return "mixed" as const; + if (requireCount > 0) return "cjs" as const; + return "esm" as const; + }, +}); + +// Agent role: Classify each JavaScript file by its module system (ESM vs CJS) based on import/require usage. +const importStyleChecker = agent({ + model: "typecheck", + instructions: p`Analyze JavaScript files to classify their module system style. + +Files with require/import patterns: +${p.bash("find . -name '*.js' -not -path '*/node_modules/*' | head -10 | xargs grep -hn '^require\\|^import ' 2>/dev/null | head -80 || echo 'no imports'")} + +For each file found, count occurrences of require(...) and import statements. +Use the classifyStyle tool to determine the module style per file. +Return counts per file and summary totals.`, + output: s.object({ + files: s.record(s.object({ + style: s.enum("esm", "cjs", "mixed", "unknown"), + requireCount: s.int, + importCount: s.int, + })), + esmCount: s.int, + cjsCount: s.int, + mixedCount: s.int, + unknownCount: s.int, + }), + tools: [classifyStyle], + addons: [repair()], +}); + +export default importStyleChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts new file mode 100644 index 0000000..a191403 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts @@ -0,0 +1,47 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const parseSemver = defineTool("parseSemver", { + description: "Parse a git tag to determine if it follows semver and extract components", + parameters: s.object({ tag: s.string }), + handler({ tag }) { + const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)/); + if (!match) return { valid: false }; + return { + valid: true, + major: parseInt(match[1] ?? "0", 10), + minor: parseInt(match[2] ?? "0", 10), + patch: parseInt(match[3] ?? "0", 10), + }; + }, +}); + +// Agent role: Validate git tags against semver format and identify the latest valid version. +const gitTagSemverValidator = agent({ + model: "typecheck", + instructions: p`Validate git tags to check semver compliance. + +Git tags: +${p.bash("git tag --list 2>/dev/null | head -30 || echo 'no tags'")} + +Use the parseSemver tool on each tag to validate format and extract major/minor/patch. +Identify invalidCount (tags that don't follow semver). +Set latestValid to the highest valid semver tag, or omit if none. +Return the structured output.`, + output: s.object({ + tags: s.array(s.object({ + name: s.string, + valid: s.boolean, + parsed: s.optional(s.object({ + major: s.int, + minor: s.int, + patch: s.int, + })), + })), + invalidCount: s.int, + latestValid: s.optional(s.string), + }), + tools: [parseSemver], + addons: [steering()], +}); + +export default gitTagSemverValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts new file mode 100644 index 0000000..122ff84 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool, steering } from "rig"; +import { readFile } from "node:fs/promises"; + +const analyzeShellScript = defineTool("analyzeShellScript", { + description: "Analyze a shell script file for safety flags (set -e, set -u, set -o pipefail) and shebang", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8").catch(() => ""); + const lines = content.split("\n"); + const shebangLine = lines[0] ?? ""; + const shebang = shebangLine.startsWith("#!") ? shebangLine.slice(2).trim() : undefined; + const hasSetE = /\bset\b.*-[a-zA-Z]*e/.test(content) || /\bset\b.*-e/.test(content); + const hasSetU = /\bset\b.*-[a-zA-Z]*u/.test(content) || /\bset\b.*-u/.test(content); + const hasPipefail = /set\s+-o\s+pipefail/.test(content); + let safetyLevel: "strict" | "partial" | "unsafe"; + if (hasSetE && hasSetU && hasPipefail) safetyLevel = "strict"; + else if (hasSetE || hasSetU || hasPipefail) safetyLevel = "partial"; + else safetyLevel = "unsafe"; + return { shebang, hasSetE, hasSetU, hasPipefail, safetyLevel }; + }, +}); + +// Agent role: Scan shell scripts for safety flags and classify each by safety level. +const shellScriptSafetyAnalyzer = agent({ + model: "typecheck", + instructions: p`Find all shell scripts and analyze each for safety flags. + +Shell script files: +${p.bash("find . -name '*.sh' -not -path '*/node_modules/*' | head -20 2>/dev/null || echo 'no shell scripts'")} + +Use the analyzeShellScript tool on each .sh file path listed above. +Return a record keyed by file path with safety analysis for each script.`, + output: s.record(s.object({ + shebang: s.optional(s.string), + hasSetE: s.boolean, + hasSetU: s.boolean, + hasPipefail: s.boolean, + safetyLevel: s.enum("strict", "partial", "unsafe"), + })), + tools: [analyzeShellScript], + addons: [steering()], +}); + +export default shellScriptSafetyAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts new file mode 100644 index 0000000..6fec012 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const classifyDiffEntry = defineTool("classifyDiffEntry", { + description: "Classify a diff entry based on addition/deletion counts", + parameters: s.object({ path: s.string, additions: s.int, deletions: s.int }), + handler({ additions, deletions }) { + if (additions > 0 && deletions === 0) return "added" as const; + if (additions === 0 && deletions > 0) return "deleted" as const; + if (additions > 0 && deletions > 0) return "modified" as const; + return "renamed" as const; + }, +}); + +// Agent role: Summarize git diff statistics between the last two commits, classifying each changed file. +const gitDiffStatsSummarizer = agent({ + model: "typecheck", + instructions: p`Analyze git diff statistics for the most recent commit. + +Diff numstat (additions deletions file): +${p.bash("git diff --numstat HEAD~1 HEAD 2>/dev/null | head -30 || echo 'no diff'")} + +Diff summary: +${p.bash("git diff --stat HEAD~1 HEAD 2>/dev/null | tail -5 || echo 'no stat'")} + +Parse the numstat output (format: additionsdeletionspath). +Use the classifyDiffEntry tool on each file entry. +Sum up totalAdditions and totalDeletions. +Set mostChangedFile to the file with the highest combined additions+deletions, or omit if empty. +Return the structured output.`, + output: s.object({ + files: s.array(s.object({ + path: s.string, + additions: s.int, + deletions: s.int, + change: s.enum("added", "modified", "deleted", "renamed"), + })), + totalAdditions: s.int, + totalDeletions: s.int, + mostChangedFile: s.optional(s.string), + }), + tools: [classifyDiffEntry], + addons: [repair()], +}); + +export default gitDiffStatsSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts new file mode 100644 index 0000000..fefeaf8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts @@ -0,0 +1,46 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +const extractEnvReferences = defineTool("extractEnvReferences", { + description: "Extract all process.env.VAR_NAME references from a TypeScript source file", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8").catch(() => ""); + const pattern = /process\.env\.([A-Z_][A-Z0-9_]*)/g; + const keys = new Set(); + let m: RegExpExecArray | null; + while ((m = pattern.exec(content)) !== null) { + if (m[1]) keys.add(m[1]); + } + return Array.from(keys); + }, +}); + +// Agent role: Generate a .env.template file by scanning source files for process.env references and comparing against existing .env keys. +const dotenvTemplateGenerator = agent({ + model: "typecheck", + instructions: p`Generate a .env.template file documenting all required environment variables. + +Existing .env file: +${p.readOptional(".env", "# no .env file found")} + +TypeScript source files to scan: +${p.glob("src/**/*.ts")} + +Use the extractEnvReferences tool on each source file to find process.env.VAR references. +Collect all unique env keys found across all files (envKeys). +Compare with keys present in .env — undocumentedKeys are those referenced in code but missing from .env. +Write a .env.template with each key as KEY=. +${p.write(".env.template", "# Generated .env.template\n# Replace with actual values\n")} +Return templatePath as ".env.template", envKeys array, undocumentedKeys array, and templateGenerated as true.`, + output: s.object({ + templatePath: s.path, + envKeys: s.array(s.string), + undocumentedKeys: s.array(s.string), + templateGenerated: s.boolean, + }), + tools: [extractEnvReferences], + addons: [repair()], +}); + +export default dotenvTemplateGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts new file mode 100644 index 0000000..7ce3ba7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts @@ -0,0 +1,52 @@ +import { agent, p, s, defineTool, steering } from "rig"; +import { readFile } from "node:fs/promises"; + +const extractClassInfo = defineTool("extractClassInfo", { + description: "Extract class declarations, inheritance, and interface implementations from a TypeScript file", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8").catch(() => ""); + const pattern = /(?:(abstract)\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?/g; + const classes: Array<{ className: string; parent?: string; interfaces: string[]; isAbstract: boolean }> = []; + let m: RegExpExecArray | null; + while ((m = pattern.exec(content)) !== null) { + const interfaces = m[4] ? m[4].split(",").map((s: string) => s.trim()).filter(Boolean) : []; + classes.push({ + className: m[2] ?? "", + parent: m[3], + interfaces, + isAbstract: !!m[1], + }); + } + return classes; + }, +}); + +// Agent role: Build a class hierarchy map from TypeScript files showing inheritance and interface relationships. +const tsClassHierarchyExtractor = agent({ + model: "typecheck", + instructions: p`Extract and map TypeScript class hierarchy from all source files. + +TypeScript files: +${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.d.ts' | head -20 2>/dev/null || echo 'no ts files'")} + +Use the extractClassInfo tool on each file to get class declarations with inheritance info. +For each class, compute depth: root classes (no parent) have depth 0; derived classes add 1 per level. +Set maxDepth to the deepest class depth found. +rootClasses are class names with no parent. +Return the structured output.`, + output: s.object({ + classes: s.record(s.object({ + parent: s.optional(s.string), + interfaces: s.array(s.string), + isAbstract: s.boolean, + depth: s.int, + })), + maxDepth: s.int, + rootClasses: s.array(s.string), + }), + tools: [extractClassInfo], + addons: [steering()], +}); + +export default tsClassHierarchyExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts new file mode 100644 index 0000000..c431a32 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +const selectMidpoint = defineTool("selectMidpoint", { + description: "Select the midpoint commit from a list for binary search bisection", + parameters: s.object({ commits: s.array(s.string), currentBad: s.string, currentGood: s.string }), + handler({ commits }) { + if (commits.length === 0) return { midpoint: null, remaining: 0 }; + const mid = Math.floor(commits.length / 2); + return { midpoint: commits[mid] ?? null, remaining: commits.length }; + }, +}); + +// Agent role: Analyze recent git commit history to identify the most likely suspect commit for a regression using binary search logic. +const gitBisectHelper = agent({ + model: "typecheck", + maxTurns: 8, + instructions: p`Analyze recent git commits to identify a suspect regression commit using binary search logic. + +Recent commits (newest first): +${p.bash("git log --oneline -20 2>/dev/null | head -20 || echo 'no commits'")} + +Commit count in range: +${p.bash("git log --oneline HEAD~10..HEAD 2>/dev/null | wc -l || echo '0'")} + +Use the selectMidpoint tool to perform binary search steps over the commit list. +Assume HEAD is the bad commit and HEAD~10 is good. +Narrow down to the most likely suspect commit. +Set confidence based on how precisely the range was narrowed: + high = 1 commit identified, medium = 2-3 candidates, low = 4+ or unknown. +Return suspectCommit (the SHA/oneline of the suspect), stepsRun, commitRange of the final narrowed set.`, + output: s.object({ + suspectCommit: s.optional(s.string), + stepsRun: s.int, + commitRange: s.array(s.string), + confidence: s.enum("high", "medium", "low"), + }), + tools: [selectMidpoint], + addons: [steering()], +}); + +export default gitBisectHelper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts new file mode 100644 index 0000000..c24f871 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: review the workflow for reliability, caching, and least privilege. +const actionReview = agent({ + model: "typecheck", + output: s.object({ + summary: s.string, + problems: s.array(s.string), + improvements: s.array(s.string) + }), + instructions: `Review the workflow for reliability, caching, and least privilege.`, +}); +export default actionReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts new file mode 100644 index 0000000..6fe9897 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts @@ -0,0 +1,66 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +// Agent role: detect version drift between package.json dependencies and package-lock.json locked versions. +const lockFileDriftDetector = agent({ + model: "typecheck", + instructions: p`You are a lock file drift detector. + +Read the package files: +${p.bash("cat package.json 2>/dev/null || echo '{}'")} +${p.bash("cat package-lock.json 2>/dev/null || echo '{}'")} + +Use the checkVersionDrift tool to cross-check declared vs locked versions for each dependency. +Return the declared output.`, + tools: [ + defineTool("checkVersionDrift", { + description: "Parse package.json and package-lock.json content and return drifted packages", + parameters: s.object({ + packageJsonContent: s.string, + lockFileContent: s.string, + }), + handler({ packageJsonContent, lockFileContent }) { + let pkg: Record; + let lock: Record; + try { + pkg = JSON.parse(packageJsonContent) as Record; + } catch { + return { error: "Failed to parse package.json" }; + } + try { + lock = JSON.parse(lockFileContent) as Record; + } catch { + return { error: "Failed to parse package-lock.json" }; + } + const deps = { + ...((pkg["dependencies"] as Record) ?? {}), + ...((pkg["devDependencies"] as Record) ?? {}), + }; + const lockPackages = (lock["packages"] as Record) ?? {}; + const drifted: Array<{ name: string; declared: string; locked: string }> = []; + for (const [name, declared] of Object.entries(deps)) { + const lockKey = `node_modules/${name}`; + const lockedEntry = lockPackages[lockKey]; + const locked = lockedEntry?.version ?? "missing"; + const declaredClean = (declared as string).replace(/^[\^~>=<]/, ""); + if (locked !== declaredClean && locked !== "missing") continue; + if (locked === "missing") { + drifted.push({ name, declared: declared as string, locked }); + } + } + return { drifted }; + }, + }), + ], + output: s.object({ + driftedPackages: s.array(s.object({ + name: s.string, + declared: s.string, + locked: s.string, + })), + driftCount: s.int, + allInSync: s.boolean, + }), + addons: [repair()], +}); + +export default lockFileDriftDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts new file mode 100644 index 0000000..d30b40f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts @@ -0,0 +1,29 @@ +import { s, workflow } from "rig"; + +const finding = s.object({ title: s.string, file: s.path }); + +// Workflow role: audit source areas in parallel, then verify each finding. +const audit = workflow({ + meta: { + name: "audit", + description: "Find and verify repository issues", + phases: [{ title: "Find" }, { title: "Verify", detail: "one verifier per finding" }], + whenToUse: "Auditing several areas that each need independent verification.", + }, + body: async ({ call, parallel, phase, pipeline }) => { + phase("Find"); + const areas = ["skills", "src", "scripts"]; + const found = await parallel(areas.map((area) => () => + call.json(`Audit ${area}/ for risky patterns.`, s.object({ findings: s.array(finding) }), { label: area }))); + + phase("Verify"); + const verdicts = await pipeline( + found.flatMap((result) => result?.findings ?? []), + (item: { title: string; file: string }) => + call.json(`Verify "${item.title}" in ${item.file}.`, s.object({ real: s.boolean }), { phase: "Verify" }), + ); + return verdicts.filter((verdict) => verdict?.real).length; + }, +}); + +export default audit; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts new file mode 100644 index 0000000..34d0ccc --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts @@ -0,0 +1,28 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: scan tracked files for unresolved git conflict markers and report affected locations. +const gitConflictMarkerScanner = agent({ + model: "typecheck", + instructions: p`You are a git conflict marker scanner. + +Check for conflict markers in tracked files: +${p.bash("git ls-files | xargs grep -lrn '<<<<<<< ' 2>/dev/null || echo 'no conflicts found'")} + +For files with conflict markers, get the details: +${p.bash("git ls-files | xargs grep -n '^<<<<<<< \\|^=======$\\|^>>>>>>> ' 2>/dev/null || echo 'none'")} + +Analyze the results and return the declared output listing all conflict markers found.`, + output: s.object({ + conflicts: s.array(s.object({ + file: s.path, + line: s.int, + markerType: s.enum("start", "middle", "end"), + })), + affectedFiles: s.array(s.path), + conflictCount: s.int, + isClean: s.boolean, + }), + addons: [steering()], +}); + +export default gitConflictMarkerScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts new file mode 100644 index 0000000..002d1d6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts @@ -0,0 +1,50 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +// Agent role: extract field definitions from protobuf message types in .proto files. +const protoFieldExtractor = agent({ + model: "typecheck", + instructions: p`You are a protobuf field extractor. + +Find .proto files in the workspace: +${p.bash("find . -name '*.proto' -not -path '*/node_modules/*' 2>/dev/null || echo 'no .proto files found'")} + +For each .proto file found, call extractProtoFields with its path to parse message definitions. +Return the declared output keyed by message name.`, + tools: [ + defineTool("extractProtoFields", { + description: "Read a .proto file and extract message field definitions", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8"); + const result: Record> = {}; + const messageRegex = /message\s+(\w+)\s*\{([^}]*)\}/gs; + const fieldRegex = /^\s*(repeated\s+)?(\w+)\s+(\w+)\s*=\s*(\d+)/gm; + for (const msgMatch of content.matchAll(messageRegex)) { + const messageName = msgMatch[1]; + const body = msgMatch[2]; + const fields: Array<{ fieldName: string; fieldType: string; fieldNumber: number; isRepeated: boolean }> = []; + for (const fldMatch of body.matchAll(fieldRegex)) { + fields.push({ + isRepeated: !!fldMatch[1], + fieldType: fldMatch[2], + fieldName: fldMatch[3], + fieldNumber: parseInt(fldMatch[4], 10), + }); + } + result[messageName] = fields; + } + return result; + }, + }), + ], + output: s.record(s.array(s.object({ + fieldName: s.string, + fieldType: s.string, + fieldNumber: s.int, + isRepeated: s.boolean, + }))), + addons: [repair()], +}); + +export default protoFieldExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts new file mode 100644 index 0000000..ae68d22 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts @@ -0,0 +1,46 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +// Agent role: inspect git remote URLs and classify their protocol and type. +const gitRemoteUrlInspector = agent({ + model: "typecheck", + instructions: p`You are a git remote URL inspector. + +List all remotes and their URLs: +${p.bash("git remote -v 2>/dev/null || echo 'no remotes'")} + +Count remote branches on origin: +${p.bash("git ls-remote --heads origin 2>/dev/null | wc -l || echo '0'")} + +Use the parseRemoteLine tool for each remote line to extract protocol and type. +Return the declared output.`, + tools: [ + defineTool("parseRemoteLine", { + description: "Parse a git remote -v output line and extract name, url, protocol, and type", + parameters: s.object({ line: s.string }), + handler({ line }) { + const match = line.match(/^(\S+)\s+(\S+)\s+\((\w+)\)$/); + if (!match) return null; + const [, name, url, type] = match; + let protocol: "https" | "ssh" | "git" | "file"; + if (url.startsWith("https://")) protocol = "https" as const; + else if (url.startsWith("git@") || url.startsWith("ssh://")) protocol = "ssh" as const; + else if (url.startsWith("git://")) protocol = "git" as const; + else protocol = "file" as const; + return { name, url, type, protocol }; + }, + }), + ], + output: s.object({ + remotes: s.array(s.object({ + name: s.string, + url: s.string, + type: s.string, + protocol: s.enum("https", "ssh", "git", "file"), + })), + remoteBranchCount: s.int, + hasOrigin: s.boolean, + }), + addons: [repair()], +}); + +export default gitRemoteUrlInspector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts new file mode 100644 index 0000000..12c1e9a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool, steering } from "rig"; +import { readFile } from "node:fs/promises"; + +// Agent role: extract TypeScript enum declarations and their members from source files. +const tsEnumValueExtractor = agent({ + model: "typecheck", + instructions: p`You are a TypeScript enum value extractor. + +Find TypeScript files with enum declarations: +${p.bash("grep -rln 'enum ' --include='*.ts' . 2>/dev/null | head -20 || echo 'no enums found'")} + +For each file found, call extractEnumValues with the file path to parse all enum declarations. +Return the declared output keyed by enum name.`, + tools: [ + defineTool("extractEnumValues", { + description: "Read a TypeScript file and extract all enum declarations with their members", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8"); + const result: Record = {}; + const enumRegex = /(const\s+)?enum\s+(\w+)\s*\{([^}]*)\}/gs; + for (const match of content.matchAll(enumRegex)) { + const isConst = !!match[1]; + const enumName = match[2]; + const body = match[3]; + const members = body + .split(",") + .map((m: string) => m.trim().split(/\s*=\s*/)[0].trim()) + .filter((m: string) => m.length > 0 && !m.startsWith("//")); + result[enumName] = { members, isConst, memberCount: members.length }; + } + return result; + }, + }), + ], + output: s.record(s.object({ + members: s.array(s.string), + isConst: s.boolean, + memberCount: s.int, + })), + addons: [steering()], +}); + +export default tsEnumValueExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts new file mode 100644 index 0000000..6c5a1e2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts @@ -0,0 +1,81 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +// Agent role: deeply merge two JSON config files and write the result to an output path. +const jsonConfigMerger = agent({ + model: "typecheck", + input: s.object({ + baseConfig: s.path, + overrideConfig: s.path, + outputPath: s.path, + }), + instructions: p`You are a JSON config merger. + +Base config contents: +${p.readInput("baseConfig")} + +Override config contents: +${p.readInput("overrideConfig")} + +Use the mergeJsonObjects tool to deeply merge the override config into the base config. +Then write the merged result to ${p.writeInput("outputPath", "mergedContent")}. +Return the declared output.`, + tools: [ + defineTool("mergeJsonObjects", { + description: "Deep merge two JSON strings, returning the merged JSON and counts of added/overridden keys", + parameters: s.object({ + baseJson: s.string, + overrideJson: s.string, + }), + handler({ baseJson, overrideJson }) { + const base = JSON.parse(baseJson) as Record; + const override = JSON.parse(overrideJson) as Record; + let keysAdded = 0; + let keysOverridden = 0; + function deepMerge( + target: Record, + source: Record + ): Record { + const result = { ...target }; + for (const [key, value] of Object.entries(source)) { + if (key in result) { + if ( + typeof result[key] === "object" && + result[key] !== null && + typeof value === "object" && + value !== null + ) { + result[key] = deepMerge( + result[key] as Record, + value as Record + ); + } else { + result[key] = value; + keysOverridden++; + } + } else { + result[key] = value; + keysAdded++; + } + } + return result; + } + const merged = deepMerge(base, override); + return { + mergedJson: JSON.stringify(merged, null, 2), + keysAdded, + keysOverridden, + totalKeys: Object.keys(merged).length, + }; + }, + }), + ], + output: s.object({ + keysAdded: s.int, + keysOverridden: s.int, + totalKeys: s.int, + outputPath: s.path, + }), + addons: [repair()], +}); + +export default jsonConfigMerger; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts new file mode 100644 index 0000000..f84c7b9 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts @@ -0,0 +1,42 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; + +// Agent role: generate a table of contents markdown file from all headings found in workspace .md files. +const markdownTocGenerator = agent({ + model: "typecheck", + instructions: p`You are a markdown table of contents generator. + +Find all markdown files in the workspace: +${p.glob("**/*.md")} + +For each file, call extractHeadings to parse its heading structure. +Then write the combined TOC to ${p.write("TOC.md", "tocContent")}. +Return the declared output.`, + tools: [ + defineTool("extractHeadings", { + description: "Read a markdown file and extract all headings with their levels and anchor text", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8"); + const headings: Array<{ level: number; text: string; anchor: string }> = []; + const headingRegex = /^(#{1,6})\s+(.+)$/gm; + for (const match of content.matchAll(headingRegex)) { + const level = match[1].length; + const text = match[2].trim(); + const anchor = text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-"); + headings.push({ level, text, anchor }); + } + return { filePath, headings }; + }, + }), + ], + output: s.object({ + processedFiles: s.array(s.path), + headingCount: s.int, + outputPath: s.path, + tocGenerated: s.boolean, + }), + addons: [repair()], +}); + +export default markdownTocGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts new file mode 100644 index 0000000..09ee46a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts @@ -0,0 +1,33 @@ +import { agent, p, s, defineTool, steering } from "rig"; + +// Agent role: aggregate git commit author email domains and count commits per domain. +const gitAuthorEmailDomains = agent({ + model: "typecheck", + instructions: p`You are a git author email domain aggregator. + +Collect all author emails from the git log: +${p.bash("git log --format=%ae 2>/dev/null | sort | uniq -c | sort -rn || echo 'no commits'")} + +For each unique email, call extractDomain to parse the domain. +Aggregate the results and return the declared output.`, + tools: [ + defineTool("extractDomain", { + description: "Extract the domain portion from an email address", + parameters: s.object({ email: s.string }), + handler({ email }) { + const atIdx = email.indexOf("@"); + if (atIdx === -1) return { domain: "unknown" }; + return { domain: email.slice(atIdx + 1).toLowerCase() }; + }, + }), + ], + output: s.object({ + domains: s.record(s.int), + totalAuthors: s.int, + uniqueEmails: s.int, + topDomain: s.string, + }), + addons: [steering()], +}); + +export default gitAuthorEmailDomains; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts new file mode 100644 index 0000000..470b9c4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts @@ -0,0 +1,19 @@ +import { agent, p, s, defineTool, repair } from "rig"; +import { readFile } from "node:fs/promises"; +// Agent role: generate a barrel file for exported symbols in skills/rig/engines. +const tsBarrelReExporter = agent({ + model: "typecheck", + instructions: p`Generate a TypeScript barrel for skills/rig/engines from ${p.bash("find skills/rig/engines -name '*.ts' -not -name 'index.ts' -not -name '*.d.ts' | head -20")}. Use extractExportedSymbols for each file, set outputFile to /tmp/rig-barrel.ts, write barrelContent to ${p.writeOutput("barrelContent", "/tmp/rig-barrel.ts")}, and return the declared output.`, + tools: [defineTool("extractExportedSymbols", { + description: "Read a TypeScript file and extract top-level exported symbol names", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8"); + const symbols = [...content.matchAll(/^export\s+(?:(?:default\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)|(\{[^}]+\}))/gm)].flatMap((match) => match[1] ? [match[1]] : match[2]!.replace(/[{}]/g, "").split(",").map((name) => name.trim().split(/\s+as\s+/)[0].trim()).filter(Boolean)); + return { filePath, symbols }; + }, + })], + output: s.object({ barrelContent: s.string, exports: s.array(s.string), outputFile: s.path, totalExports: s.int, filesScanned: s.int }), + addons: [repair()], +}); +export default tsBarrelReExporter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts new file mode 100644 index 0000000..a98673b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts @@ -0,0 +1,65 @@ +import { agent, p, s, defineTool, steering } from "rig"; +import { readFile } from "node:fs/promises"; + +// Agent role: estimate total runtime and identify bottleneck steps in GitHub Actions workflows. +const workflowStepDurationEstimator = agent({ + model: "typecheck", + instructions: p`You are a GitHub Actions workflow step duration estimator. + +Discover workflow files: +${p.glob(".github/workflows/*.yml")} + +Read each workflow file and use estimateStepDuration to classify each step's expected duration. +Return the declared output with per-workflow estimates.`, + tools: [ + defineTool("estimateStepDuration", { + description: "Classify a workflow step's expected duration based on its name and uses field", + parameters: s.object({ + stepName: s.string, + uses: s.optional(s.string), + run: s.optional(s.string), + }), + handler({ stepName, uses, run }) { + const slow = ["install", "build", "compile", "deploy", "push", "publish", "cache", "docker", "terraform"]; + const medium = ["test", "lint", "check", "validate", "setup", "configure", "upload", "download"]; + const fast = ["checkout", "echo", "env", "version", "tag", "label", "comment"]; + const text = `${stepName} ${uses ?? ""} ${run ?? ""}`.toLowerCase(); + let speed: "fast" | "medium" | "slow" | "unknown"; + let estimatedMinutes: number; + if (slow.some((k: string) => text.includes(k))) { + speed = "slow" as const; + estimatedMinutes = 5; + } else if (medium.some((k: string) => text.includes(k))) { + speed = "medium" as const; + estimatedMinutes = 2; + } else if (fast.some((k: string) => text.includes(k))) { + speed = "fast" as const; + estimatedMinutes = 0.5; + } else { + speed = "unknown" as const; + estimatedMinutes = 1; + } + return { speed, estimatedMinutes }; + }, + }), + defineTool("readWorkflowFile", { + description: "Read a workflow YAML file and return its content", + parameters: s.object({ filePath: s.path }), + async handler({ filePath }) { + const content = await readFile(filePath, "utf8"); + return { filePath, content }; + }, + }), + ], + output: s.object({ + workflows: s.record(s.object({ + estimatedMinutes: s.number, + bottleneck: s.string, + optimizable: s.boolean, + })), + totalWorkflows: s.int, + }), + addons: [steering()], +}); + +export default workflowStepDurationEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts new file mode 100644 index 0000000..f10f5f2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts @@ -0,0 +1,19 @@ +import { agent, s } from "rig"; +// Agent role: build a package map for a JavaScript monorepo. +const packageMap = agent({ + model: "typecheck", + output: s.object({ + packages: s.array(s.object({ + name: s.string, + path: s.string, + private: s.boolean + })), + relationships: s.array(s.object({ + from: s.string, + to: s.string, + kind: s.string + })) + }), + instructions: `Build a package map for a JavaScript monorepo.`, +}); +export default packageMap; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts new file mode 100644 index 0000000..b9d2735 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts @@ -0,0 +1,15 @@ +import { agent, s } from "rig"; +// Agent role: plan shell commands for the goal. Prefer readonly commands. +const commandPlanner = agent({ + model: "typecheck", + output: s.object({ + commands: s.array(s.object({ + command: s.string, + purpose: s.string, + readonly: s.boolean + })) + }), + instructions: `Plan shell commands for the goal. Prefer readonly commands.`, +}); + +export default commandPlanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts new file mode 100644 index 0000000..066fa7b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: investigate the project using only readonly evidence. +const investigator = agent({ + model: "typecheck", + output: s.object({ + observations: s.array(s.string), + likelyEntryPoints: s.array(s.string) + }), + instructions: `Investigate the project using only readonly evidence.`, +}); +export default investigator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts new file mode 100644 index 0000000..91b6a0d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: parse environment outputs. +const envReader = agent({ + model: "typecheck", + output: s.object({ + nodeMajor: s.number, + files: s.array(s.string) + }), + instructions: `Parse environment outputs.`, +}); +export default envReader; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts new file mode 100644 index 0000000..ff71fa4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts @@ -0,0 +1,15 @@ +import { agent, s } from "rig"; +// Agent role: extract the most important implementation details from the topic. +const researcher = agent({ + model: "typecheck", + output: s.object({ summary: s.string, risks: s.array(s.string) }), + instructions: "Extract the most important implementation details from the topic.", +}); +// Agent role: plan the next steps and use the researcher when helpful. +const planner = agent({ + model: "typecheck", + instructions: "Plan the next steps for explaining runtime-visible schemas in one paragraph. Use the researcher when helpful.", + output: s.object({ decision: s.string, nextSteps: s.array(s.string) }), + agents: { researcher }, +}); +export default planner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts new file mode 100644 index 0000000..cdf309f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts @@ -0,0 +1,22 @@ +import { agent, s } from "rig"; +// Agent role: summarize the diff. +const summarizeDiff = agent({ + model: "typecheck", + output: s.object({ + summary: s.string, + files: s.array(s.string) + }), + instructions: `Summarize the diff.`, +}); +// Agent role: review the diff. You may use the provided subagent conceptually. +const reviewer = agent({ + model: "typecheck", + output: s.object({ + summary: s.string, + issues: s.array(s.string) + }), + agents: { summarizeDiff }, + instructions: `Review the diff. You may use the provided subagent conceptually.`, +}); + +export default reviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts new file mode 100644 index 0000000..42513ff --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: extract event metadata. Use undefined when deletedAt is absent. +const parseEvent = agent({ + model: "typecheck", + output: s.object({ + title: s.string, + deletedAt: s.optional(s.string) + }), + instructions: `Extract event metadata. Use undefined when deletedAt is absent.`, +}); + +export default parseEvent; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts new file mode 100644 index 0000000..a359fa7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts @@ -0,0 +1,13 @@ +import { agent, s } from "rig"; +// Agent role: convert the finding into a typed review record. +const reviewRecord = agent({ + model: "typecheck", + output: s.object({ + kind: s.enum("review-finding"), + finding: s.string, + severity: s.enum("info", "warning", "error") + }), + instructions: `Convert the finding into a typed review record.`, +}); + +export default reviewRecord; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts new file mode 100644 index 0000000..6fa83c8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: extract any JSON object from input.text into raw. +const extractJson = agent({ + model: "typecheck", + output: s.object({ + raw: s.unknown, + summary: s.string + }), + instructions: `Extract any JSON object from input.text into raw.`, +}); +export default extractJson; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts new file mode 100644 index 0000000..ae4f716 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; +// Agent role: parse coverage by file path. +const coverage = agent({ + model: "typecheck", + output: s.object({ + files: s.record(s.object({ + lines: s.number, + branches: s.number, + notes: s.optional(s.string) + })) + }), + instructions: `Parse coverage by file path.`, +}); +export default coverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts new file mode 100644 index 0000000..d5640b8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts @@ -0,0 +1,14 @@ +import { agent, s } from "rig"; + +// Agent role: summarize the diff. + +const summarize = agent({ + model: "typecheck", + instructions: "Summarize the diff.", + output: s.object({ + summary: s.string, + }), + maxTurns: 2, +}); + +export default summarize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts new file mode 100644 index 0000000..56048a1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: repair input.text into a JSON-compatible value. +const repair = agent({ + model: "typecheck", + output: s.object({ + repaired: s.unknown, + changes: s.array(s.string) + }), + instructions: `Repair input.text into a JSON-compatible value.`, +}); + +export default repair; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts new file mode 100644 index 0000000..d475778 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: decide whether snapshot updates are legitimate. +const snapshotReview = agent({ + model: "typecheck", + output: s.object({ + safeToUpdate: s.boolean, + reason: s.string, + command: s.optional(s.string) + }), + instructions: `Decide whether snapshot updates are legitimate.`, +}); +export default snapshotReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts new file mode 100644 index 0000000..6b40e88 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts @@ -0,0 +1,12 @@ +import { agent, s } from "rig"; +// Agent role: analyze whether the test failure appears flaky. +const flaky = agent({ + model: "typecheck", + output: s.object({ + likelyFlaky: s.boolean, + signals: s.array(s.string), + stabilizationIdeas: s.array(s.string) + }), + instructions: `Analyze whether the test failure appears flaky.`, +}); +export default flaky; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts new file mode 100644 index 0000000..c1a67bf --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: suggest owners for changed files. +const owners = agent({ + model: "typecheck", + output: s.object({ + owners: s.array(s.string), + unmatchedFiles: s.array(s.string) + }), + instructions: `Suggest owners for changed files.`, +}); +export default owners; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts new file mode 100644 index 0000000..95d6cae --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: summarize the current git workspace changes. +const promptIntents = agent({ + model: "typecheck", + instructions: "Summarize the current git workspace changes.", + output: s.object({ + summary: s.string, + changedFiles: s.array(s.string), + }), +}); +export default promptIntents; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts new file mode 100644 index 0000000..ddffb66 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts @@ -0,0 +1,8 @@ +import { agent, s } from "rig"; +// Agent role: explain when to launch rig with --server. +const review = agent({ + model: "typecheck", + instructions: "Explain when to launch rig with --server instead of connecting to an HTTP Copilot server.", + output: s.object({ summary: s.string, recommendedMode: s.enum("http", "server") }), +}); +export default review; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts new file mode 100644 index 0000000..85e80d3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts @@ -0,0 +1,8 @@ +import { agent, timeout } from "rig"; +// Agent role: return a short response before the timeout expires. +const worker = agent({ + model: "typecheck", + instructions: "Return a short response before the timeout expires.", + addons: timeout({ timeout: 5_000 }), +}); +export default worker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts new file mode 100644 index 0000000..2385e94 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts @@ -0,0 +1,26 @@ +import { agent, p, s } from "rig"; +// Agent role: summarize the release candidate changes. +const analyzeChanges = agent({ model: "typecheck", + input: s.object({ diff: s.string, commits: s.string }), + output: s.object({ summary: s.string, highlights: s.array(s.string) }), + instructions: "Summarize the release candidate changes.", +}); +// Agent role: choose the safest semantic version bump. +const chooseVersion = agent({ model: "typecheck", + input: s.object({ summary: s.string, highlights: s.array(s.string) }), + output: s.object({ bump: s.enum("patch", "minor", "major"), rationale: s.string }), + instructions: "Choose the safest semantic version bump.", +}); +// Agent role: draft the release note from the chosen version bump. +const draftRelease = agent({ model: "typecheck", + input: s.object({ bump: s.enum("patch", "minor", "major"), rationale: s.string, summary: s.string }), + output: s.object({ title: s.string, checklist: s.array(s.string), risks: s.array(s.string) }), + instructions: "Draft the release note from the chosen version bump.", +}); +// Agent role: plan the next release using the provided specialists. +const releaseAgent = agent({ model: "typecheck", + instructions: p`Plan the next release using ${p.bash("git diff --stat -- .")} and ${p.bash("git log --oneline -20")}.`, + output: s.object({ title: s.string, bump: s.enum("patch", "minor", "major"), checklist: s.array(s.string), risks: s.array(s.string) }), + agents: { analyzeChanges, chooseVersion, draftRelease }, +}); +export default releaseAgent; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts new file mode 100644 index 0000000..1237cbd --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts @@ -0,0 +1,21 @@ +import { agent, p, s } from "rig"; +// Agent role: draft a runnable rig markdown snippet for the requested task. +const draftRigMarkdown = agent({ + model: "typecheck", + output: s.object({ markdown: s.string }), + instructions: "Return exactly one markdown response with one ```rig fenced block.", +}); +// Agent role: validate generated rig code by running TypeScript in no-emit mode. +const typecheckRigProgram = agent({ + model: "typecheck", + output: s.object({ ok: s.boolean, diagnostics: s.string }), + instructions: p`Run ${p.bash("npx tsc --noEmit --pretty false")} and summarize whether typecheck passed.`, +}); +// Agent role: solve the task by delegating to subagents and returning markdown. +const solveTask = agent({ + model: "typecheck", + output: s.object({ markdown: s.string }), + agents: { draftRigMarkdown, typecheckRigProgram }, + instructions: "Use the drafting subagent, validate with typecheck, then return one runnable rig markdown snippet.", +}); +export default solveTask; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts new file mode 100644 index 0000000..6a71165 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts @@ -0,0 +1,25 @@ +import { agent, s } from "rig"; +// Agent role: coordinate writer/critic/reviser to produce one final response. +const writer = agent({ + model: "typecheck", + output: s.object({ draft: s.string }), + instructions: "Write a helpful, clear response to the request.", +}); +const critic = agent({ + model: "typecheck", + input: s.object({ request: s.string, draft: s.string }), + output: s.object({ issues: s.array(s.string), score: s.number, acceptable: s.boolean }), + instructions: "Evaluate the draft against helpfulness, harmlessness, and honesty principles.", +}); +const reviser = agent({ + model: "typecheck", + input: s.object({ request: s.string, draft: s.string, issues: s.array(s.string) }), + output: s.object({ response: s.string }), + instructions: "Revise the draft to address all issues identified by the critic.", +}); +const root = agent({ model: "typecheck", + instructions: "Use writer, critic, and reviser to produce one final response.", + output: s.object({ response: s.string }), + agents: { writer, critic, reviser }, +}); +export default root; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts new file mode 100644 index 0000000..f49cf75 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts @@ -0,0 +1,22 @@ +import { agent, p, s } from "rig"; +// Agent role: diagnose failing tests and decide if the loop is done. +const diagnose = agent({ + model: "typecheck", + input: s.object({ ok: s.boolean, stdout: s.string, exitCode: s.number }), + output: s.object({ done: s.boolean, rootCause: s.string }), + instructions: "Diagnose test failures. Set done to true if all tests passed.", +}); +// Agent role: apply the smallest safe fix for the root cause. +const fix = agent({ + model: "typecheck", + output: s.object({ summary: s.string, changed: s.boolean }), + instructions: "Apply the smallest safe fix for the root cause.", +}); +// Agent role: run a RALF loop iterating diagnose-fix cycles until tests pass. +const ralfLoop = agent({ + model: "typecheck", + output: s.object({ iterations: s.number, fixed: s.boolean }), + agents: { diagnose, fix }, + instructions: p`Run ${p.bash("npm test")} then loop: diagnose failures, fix, repeat up to 3 times.`, +}); +export default ralfLoop; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts new file mode 100644 index 0000000..26f767d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts @@ -0,0 +1,13 @@ +import { agent, p, s } from "rig"; +// Agent role: summarize one evidence shard cheaply with a small model. +const summarizeShard = agent({ model: "typecheck", input: s.object({ scenario: s.string, shardLabel: s.string, evidence: s.string }), output: s.object({ shardLabel: s.string, summary: s.string, facts: s.array(s.string) }), instructions: "Summarize only high-signal facts." }); +// Agent role: merge shard summaries into one concise final summary. +const reduceScenario = agent({ model: "typecheck", input: s.object({ scenario: s.string, shardSummaries: s.array(s.object({ shardLabel: s.string, summary: s.string, facts: s.array(s.string) })) }), output: s.object({ scenario: s.string, summary: s.string, savings: s.string }), instructions: "Deduplicate facts and keep the final summary short." }); +// Agent role: orchestrate deterministic search + parallel shard summarization for nine large-scale scenarios. +const summarizeAtScale = agent({ + model: "typecheck", + output: s.object({ scenarios: s.array(s.object({ id: s.string, summary: s.string })), costNotes: s.array(s.string) }), + agents: { summarizeShard, reduceScenario }, + instructions: p`Cover: git diff, 24h repo changes, 24h exported/doc updates, semantic search (query->rg shards->shard summaries->final), plus 24h CI failures, auth/permission changes, dependency risk, API impact, and monorepo owner impact. Use ${p.bash("rg -n \"export|auth|permission|schema\" src docs || true")} and ${p.bash("git log --since='24 hours ago' --name-status --pretty=format:'%h %s'")} first, then parallelize shard work with Promises and use large-model reduction only once per scenario.`, +}); +export default summarizeAtScale; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts new file mode 100644 index 0000000..55dc29d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts @@ -0,0 +1,23 @@ +import { agent, s, type AgentAddon } from "rig"; +import { $ } from "zx"; + +const fingerprint = async () => { + const { exitCode, stdout } = await $`git status --porcelain`.nothrow(); + return exitCode === 0 ? stdout.trim() : ""; +}; +const lintOnFileChange = (runLint: () => Promise): AgentAddon => async (_context, next) => { + const before = await fingerprint(); + await next(); + const after = await fingerprint(); + if (before !== after) await runLint(); +}; + +// Agent role: update files and run linting after file changes. +const fileChangeMiddleware = agent({ + model: "typecheck", + instructions: "Update files when needed, then summarize the change.", + output: s.object({ changed: s.boolean, summary: s.string }), + addons: lintOnFileChange(() => $`npm run typecheck`), +}); + +export default fileChangeMiddleware; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts new file mode 100644 index 0000000..f017bf5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts @@ -0,0 +1,8 @@ +import { agent, p, s } from "rig"; +// Agent role: extract advanced rig glossary terms from docs. +const glossaryPort = agent({ + model: "typecheck", + instructions: p`Read ${p.read("README.md")} and ${p.read("skills/rig/SKILL.md")}. Return only advanced rig terms with short definitions and skip duplicates.`, + output: s.object({ terms: s.array(s.object({ term: s.string, definition: s.string })) }), +}); +export default glossaryPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts new file mode 100644 index 0000000..19135f6 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts @@ -0,0 +1,10 @@ +import { agent, p, s } from "rig"; +// Agent role: suggest metadata refactors for the first three sample files. +const refactorOne = agent({ model: "typecheck", instructions: "Suggest one minimal metadata cleanup for a rig sample.", output: s.object({ file: s.string, change: s.string }) }); +const refactorBatch = agent({ + model: "typecheck", + instructions: p`Inspect ${p.bash("find skills/rig/samples -maxdepth 1 -name '*.md' | sort | head -n 3")}. Use refactorOne when helpful and return only the smallest safe cleanup suggestions.`, + output: s.object({ suggestions: s.array(s.object({ file: s.string, change: s.string })) }), + agents: { refactorOne }, +}); +export default refactorBatch; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts new file mode 100644 index 0000000..e928f1a --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts @@ -0,0 +1,8 @@ +import { agent, s } from "rig"; +// Agent role: review a GitHub issue report and return concise feedback. +const issueReviewPort = agent({ + model: "typecheck", + instructions: "Review this issue draft: \"The CLI crashes sometimes when reading stdin programs on Windows. I expected it to work.\" Ask only for missing reproduction details and missing expected behavior.", + output: s.object({ summary: s.string, questions: s.array(s.string) }), +}); +export default issueReviewPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts new file mode 100644 index 0000000..7d81e90 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts @@ -0,0 +1,11 @@ +import { agent, s } from "rig"; +// Agent role: merge local advice and language tips into one travel plan. +const localGuide = agent({ model: "typecheck", instructions: "Suggest authentic places and activities for a 3-day trip to Egypt.", output: s.object({ ideas: s.array(s.string) }) }); +const languageTips = agent({ model: "typecheck", instructions: "Suggest communication tips for a 3-day trip to Egypt.", output: s.object({ tips: s.array(s.string) }) }); +const travelPlanPort = agent({ + model: "typecheck", + instructions: "Plan a 3-day trip to Egypt. Use localGuide and languageTips when helpful, then return one integrated itinerary.", + output: s.object({ itinerary: s.array(s.string), tips: s.array(s.string) }), + agents: { localGuide, languageTips }, +}); +export default travelPlanPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts new file mode 100644 index 0000000..8152153 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts @@ -0,0 +1,8 @@ +import { agent, s } from "rig"; +// Agent role: extract structured city facts from a short dataset. +const cityInfoPort = agent({ + model: "typecheck", + instructions: "From this dataset, return a JSON array of city facts only: Cairo | population 10.1M | https://en.wikipedia.org/wiki/Cairo ; Alexandria | population 5.6M | https://en.wikipedia.org/wiki/Alexandria ; Giza | population 4.8M | https://en.wikipedia.org/wiki/Giza.", + output: s.array(s.object({ name: s.string, population: s.number, url: s.string })), +}); +export default cityInfoPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts new file mode 100644 index 0000000..b40fb5d --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts @@ -0,0 +1,8 @@ +import { agent, s } from "rig"; +// Agent role: invent five city records that match a strict schema. +const schemaCitiesPort = agent({ + model: "typecheck", + instructions: "Give 5 cities with their populations and Wikipedia URLs. Return only valid output.", + output: s.array(s.object({ name: s.string, population: s.number, url: s.string })), +}); +export default schemaCitiesPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts new file mode 100644 index 0000000..93e3701 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts @@ -0,0 +1,24 @@ +import { agent, s, workflow } from "rig"; + +// Agent role: check one TypeScript file for code quality issues. +const lintFile = agent({ + name: "lintFile", + model: "typecheck", + input: s.object({ file: s.path }), + output: s.object({ issues: s.array(s.string) }), + instructions: "Check the file for linting issues.", +}); + +// Workflow role: discover and lint TypeScript source files in parallel. +const linter = workflow({ + meta: { name: "linter", description: "Lint TypeScript files in parallel", phases: ["Discover", "Lint"] }, + body: async ({ call, phase, pipeline }) => { + phase("Discover"); + const raw = await call.text("List TypeScript source files to lint, one path per line."); + const files = (raw ?? "").split("\n").map((f) => f.trim()).filter(Boolean); + phase("Lint"); + return pipeline(files, (file) => call(lintFile, { file }, { label: file })); + }, +}); + +export default linter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts new file mode 100644 index 0000000..d9af390 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts @@ -0,0 +1,8 @@ +import { agent, p, s } from "rig"; +// Agent role: pick the most interesting rig sample files. +const listFilesPort = agent({ + model: "typecheck", + instructions: p`Review ${p.bash("find skills/rig/samples -maxdepth 1 -name '*.md' | sort")}. Select the 3 most interesting sample files.`, + output: s.object({ files: s.array(s.string) }), +}); +export default listFilesPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts new file mode 100644 index 0000000..5bc441f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts @@ -0,0 +1,8 @@ +import { agent, p, s } from "rig"; +// Agent role: propose minimal TODO implementations from the current workspace. +const todoPort = agent({ + model: "typecheck", + instructions: p`Check ${p.bash("rg -n 'TODO' src skills scripts . || true")}. For up to one actionable TODO, return the target file and the minimal implementation plan.`, + output: s.object({ todos: s.array(s.object({ file: s.string, plan: s.string })) }), +}); +export default todoPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts new file mode 100644 index 0000000..73c1ac3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts @@ -0,0 +1,8 @@ +import { agent, p, s } from "rig"; +// Agent role: turn the README into a short slide deck outline. +const slideDeckPort = agent({ + model: "typecheck", + instructions: p`Read ${p.read("README.md")} and draft a short markdown slide deck outline with terse titles and short bullets.`, + output: s.object({ slides: s.array(s.object({ title: s.string, bullets: s.array(s.string) })) }), +}); +export default slideDeckPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts new file mode 100644 index 0000000..49d23de --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts @@ -0,0 +1,8 @@ +import { agent, p, s } from "rig"; +// Agent role: review one rig sample in a terse critical voice. +const grumpyReviewPort = agent({ + model: "typecheck", + instructions: p`Review ${p.read("skills/rig/samples/36-subagent-delegation.md")} in a terse senior-engineer voice. Be specific, but keep each point short.`, + output: s.object({ findings: s.array(s.string), verdict: s.string }), +}); +export default grumpyReviewPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts new file mode 100644 index 0000000..4ffaa39 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts @@ -0,0 +1,23 @@ +import { agent, p, s } from "rig"; + +// Agent role: generate JSDoc comments for the TypeScript source file provided. +const jsdocWriter = agent({ + model: "typecheck", + input: s.object({ path: s.nonEmptyString, source: s.string }), + output: s.object({ annotated: s.string }), + instructions: "Add JSDoc comments to all exported functions and classes in the source file. Return only the annotated source.", +}); + +// Agent role: annotate TypeScript source files with JSDoc using a subagent, then write the results. +const annotator = agent({ + model: "typecheck", + instructions: p`Annotate each TypeScript file found by ${p.glob("src/**/*.ts")} using the jsdocWriter subagent, then write each annotated file back with ${p.write("src/annotated.ts", "placeholder")}. Hard-code the output path in the report.`, + output: s.object({ + processed: s.array(s.nonEmptyString), + skipped: s.array(s.nonEmptyString), + reportPath: s.string, + }), + agents: { jsdocWriter }, +}); + +export default annotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts new file mode 100644 index 0000000..6054b41 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts @@ -0,0 +1,29 @@ +import { agent, defineTool, p, s, repair } from "rig"; + +const parseYamlSteps = defineTool("parse_yaml_steps", { + description: "Extract step names and uses from a YAML workflow file.", + parameters: s.object({ path: s.nonEmptyString }), + handler: async ({ path }) => { + const { readFileSync } = await import("node:fs"); + try { + const content = readFileSync(path, "utf8"); + const steps = [...content.matchAll(/^\s+-\s+(?:name|uses):\s+(.+)$/gm)].map((m) => m[1]); + return JSON.stringify(steps); + } catch { return "[]"; } + }, +}); + +// Agent role: analyze CI workflow files and return a list of health issues. +const ciWorkflowAnalyzer = agent({ + model: "typecheck", + maxTurns: 3, + addons: repair(), + instructions: p`Scan ${p.glob(".github/workflows/*.yml")} and ${p.bashRaw`find .github/workflows -name '*.yaml' 2>/dev/null`} for workflow health issues. Use parse_yaml_steps to inspect individual files.`, + output: s.object({ + issues: s.array(s.object({ workflow: s.nonEmptyString, severity: s.enum("info", "warning", "error"), message: s.string, fix: s.optional(s.string) })), + healthy: s.boolean, + }), + tools: [parseYamlSteps], +}); + +export default ciWorkflowAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts new file mode 100644 index 0000000..d76a5c2 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts @@ -0,0 +1,17 @@ +import { agent, p, s } from "rig"; +// Agent role: summarize TypeScript source files found by glob and return a record keyed by path. +const fileSummarizer = agent({ + model: "typecheck", + input: s.object({ path: s.string, content: s.string }), + output: s.object({ path: s.string, summary: s.string }), + instructions: "Summarize the file content in one sentence.", +}); + +// Agent role: find all TypeScript files with p.glob, then use fileSummarizer to summarize each. +const globSummarizer = agent({ + model: "typecheck", + output: s.record(s.string, "summaries keyed by file path"), + agents: { fileSummarizer }, + instructions: p`Find TypeScript source files: ${p.glob("src/**/*.ts")}. For each file use fileSummarizer to produce a one-sentence summary, then return a record mapping each path to its summary.`, +}); +export default globSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts new file mode 100644 index 0000000..1030532 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts @@ -0,0 +1,31 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const validateSemver = defineTool("validateSemver", { + description: "Validate that a bump type is major, minor, or patch", + parameters: s.object({ bump: s.string }), + handler({ bump }) { + const valid = ["major", "minor", "patch"].includes(bump); + return { valid }; + }, +}); + +// Agent role: read recent git changes and produce a structured changelog entry with semver bump classification. +const changelogGenerator = agent({ + model: "typecheck", + instructions: p`Review ${p.bash("git diff HEAD~1 HEAD --stat")} and ${p.bash("git log HEAD~1..HEAD --oneline")} to produce a changelog entry. Classify each change by category and determine the semver bump type. Use the validateSemver tool to confirm the bump value. Write the markdown changelog to CHANGELOG.md via ${p.write("CHANGELOG.md", "")}`, + output: s.object({ + version: s.string, + bump: s.enum("major", "minor", "patch"), + entries: s.array(s.object({ + category: s.enum("feat", "fix", "chore", "docs", "refactor"), + description: s.string, + })), + markdown: s.string, + }), + tools: [validateSemver], + maxTurns: 6, + addons: repair(), +}); + +export default changelogGenerator; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts new file mode 100644 index 0000000..4a17622 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts @@ -0,0 +1,20 @@ +import { agent, p, s } from "rig"; + +// Agent role: scan source files for TODO/FIXME/HACK comments and produce a structured report. +const todoCommentTracker = agent({ + model: "typecheck", + instructions: p`Scan source files using ${p.bash("grep -rn 'TODO\\|FIXME\\|HACK' --include='*.ts' . 2>/dev/null || true")} and produce a structured list of all found comments. Write a markdown report to todo-report.md via ${p.write("todo-report.md", "")}`, + output: s.object({ + items: s.array(s.object({ + file: s.path, + line: s.int, + kind: s.enum("TODO", "FIXME", "HACK"), + message: s.string, + })), + totalCount: s.int, + markdown: s.string, + }), +}); + +export default todoCommentTracker; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts new file mode 100644 index 0000000..3564487 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts @@ -0,0 +1,29 @@ +import { agent, p, s, workflow } from "rig"; +// Agent role: summarize a single TypeScript file. +const fileSummarizer = agent({ + name: "fileSummarizer", + model: "typecheck", + input: s.object({ filePath: s.path }), + instructions: p`Summarize the TypeScript file at ${p.readInput("filePath")} in one concise sentence.`, + output: s.object({ summary: s.string }), +}); +// Workflow role: deterministically discover files, run subagent summaries in parallel, and aggregate by file path. +const multiFileSummarizer = workflow({ + meta: { name: "multiFileSummarizer", description: "Summarize TypeScript files", phases: ["Discover", "Summarize"] }, + body: async ({ call, phase, pipeline }) => { + phase("Discover"); + const raw = await call.text( + `List up to 10 TypeScript files from src (one path per line) using ${p.bash("find src -name '*.ts' -not -path '*/node_modules/*' 2>/dev/null | head -10 || true")}.`, + ); + const files = (raw ?? "").split("\n").map((x) => x.trim()).filter(Boolean); + phase("Summarize"); + const rows = await pipeline(files, async (filePath) => { + const out = await call(fileSummarizer, { filePath }, { label: filePath }); + return out ? [filePath, out.summary] as const : null; + }); + return Object.fromEntries(rows.filter((row): row is readonly [string, string] => !!row)); + }, +}); + +export default multiFileSummarizer; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts new file mode 100644 index 0000000..dfcc6c7 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts @@ -0,0 +1,31 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const validateScriptName = defineTool("validateScriptName", { + description: "Validate that a package.json script name follows conventional naming (lowercase, hyphens only)", + parameters: s.object({ name: s.string }), + handler({ name }) { + const valid = /^[a-z][a-z0-9:-]*$/.test(name); + const reason = valid ? "Name is conventional" : "Name should be lowercase with hyphens/colons only"; + return { valid, reason }; + }, +}); + +// Agent role: analyze package.json scripts for naming and structural health issues. +const packageScriptHealth = agent({ + model: "typecheck", + instructions: p`Read ${p.read("package.json")} and analyze all scripts entries. Use the validateScriptName tool for each script name. Classify each issue by severity and determine overall health.`, + output: s.object({ + issues: s.array(s.object({ + script: s.string, + issue: s.string, + status: s.enum("error", "warning", "ok"), + })), + overallHealth: s.enum("healthy", "degraded", "critical"), + }), + tools: [validateScriptName], + maxTurns: 6, + addons: repair(), +}); + +export default packageScriptHealth; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts new file mode 100644 index 0000000..98d8aef --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts @@ -0,0 +1,33 @@ +import { agent, p, s, defineTool } from "rig"; + +const parseSignatures = defineTool("parseSignatures", { + description: "Extract function signatures from TypeScript source content using regex", + parameters: s.object({ content: s.string }), + handler({ content }) { + const pattern = /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/g; + const functions: { name: string; paramCount: number; isExported: boolean }[] = []; + let match; + while ((match = pattern.exec(content)) !== null) { + const [full, name, params] = match; + const paramCount = params.trim() === "" ? 0 : params.split(",").length; + const isExported = full.trimStart().startsWith("export"); + functions.push({ name, paramCount, isExported }); + } + return { functions }; + }, +}); + +// Agent role: extract TypeScript function signatures from source files and return them keyed by file path. +const tsFunctionSignatures = agent({ + model: "typecheck", + instructions: p`Find TypeScript files using ${p.bash("find src -name '*.ts' 2>/dev/null | head -5 || echo 'no files'")} then read each file and use the parseSignatures tool to extract function signatures. Return results keyed by file path.`, + output: s.record(s.array(s.object({ + name: s.string, + paramCount: s.int, + isExported: s.boolean, + }))), + tools: [parseSignatures], +}); + +export default tsFunctionSignatures; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts new file mode 100644 index 0000000..1463280 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts @@ -0,0 +1,22 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: identify git branches that are candidates for pruning based on merge status and last commit date. +const gitBranchPruner = agent({ + model: "typecheck", + instructions: p`Analyze git branches using ${p.bash("git branch --merged HEAD 2>/dev/null || echo 'no branches'")} and ${p.bash("git for-each-ref --format='%(refname:short) %(committerdate:short)' refs/heads/ 2>/dev/null || echo 'no refs'")}. For each branch determine if it should be pruned (merged and not main/master/develop) or kept. Exclude the current branch from prune candidates.`, + output: s.object({ + candidates: s.array(s.object({ + branch: s.string, + lastCommitDate: s.optional(s.string), + action: s.enum("keep", "prune"), + reason: s.string, + })), + totalBranches: s.int, + pruneCount: s.int, + }), + maxTurns: 6, + addons: repair(), +}); + +export default gitBranchPruner; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts new file mode 100644 index 0000000..87df4b4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const detectConflicts = defineTool("detectConflicts", { + description: "Detect rule conflicts between Prettier and ESLint configs", + parameters: s.object({ prettierConfig: s.string, eslintConfig: s.string }), + handler({ prettierConfig, eslintConfig }) { + const conflicts: { rule: string; prettier: string; eslint: string; fixable: boolean }[] = []; + try { + const p = JSON.parse(prettierConfig || "{}"); + const e = JSON.parse(eslintConfig || "{}"); + const rules = (e.rules || {}); + if (p.printWidth && rules["max-len"]) { + conflicts.push({ rule: "line-length", prettier: `printWidth: ${p.printWidth}`, eslint: `max-len: ${JSON.stringify(rules["max-len"])}`, fixable: true }); + } + if (p.singleQuote !== undefined && rules["quotes"]) { + conflicts.push({ rule: "quotes", prettier: `singleQuote: ${p.singleQuote}`, eslint: `quotes: ${JSON.stringify(rules["quotes"])}`, fixable: true }); + } + } catch { + // invalid JSON — model will handle + } + return { conflicts }; + }, +}); + +// Agent role: check Prettier and ESLint configs for rule conflicts and report compatibility issues. +const prettierEslintCompat = agent({ + model: "typecheck", + instructions: p`Read the Prettier config ${p.readOptional(".prettierrc")} and ESLint config ${p.readOptional(".eslintrc.json")} then use the detectConflicts tool to find rule conflicts. Classify each conflict by severity.`, + output: s.object({ + conflicts: s.array(s.object({ + rule: s.string, + prettier: s.string, + eslint: s.string, + fixable: s.boolean, + severity: s.enum("error", "warning", "info"), + })), + compatible: s.boolean, + }), + tools: [detectConflicts], + maxTurns: 6, + addons: repair(), +}); + +export default prettierEslintCompat; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts new file mode 100644 index 0000000..b85ab02 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts @@ -0,0 +1,36 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze a single GitHub Actions workflow file for structural issues and job count. +const workflowAnalyzer = agent({ + name: "workflowAnalyzer", + model: "typecheck", + input: s.object({ filePath: s.path }), + instructions: p`Analyze the GitHub Actions workflow file at ${p.readInput("filePath")} for issues such as missing permissions, deprecated actions, hardcoded secrets, or missing timeout-minutes. Count the number of jobs defined.`, + output: s.object({ + issues: s.array(s.object({ + step: s.string, + problem: s.string, + severity: s.enum("error", "warning", "info"), + })), + jobCount: s.int, + }), +}); + +// Agent role: find all GitHub Actions workflow files and delegate analysis to workflowAnalyzer subagent, then aggregate results. +const workflowValidator = agent({ + model: "typecheck", + instructions: p`Find GitHub Actions workflow files using ${p.bash("find .github/workflows -name '*.yml' -o -name '*.yaml' 2>/dev/null | head -10 || echo 'no workflows'")} then delegate each file to the workflowAnalyzer subagent. Aggregate results keyed by filename, adding a pass/warn/fail status based on issue severity.`, + output: s.record(s.object({ + issues: s.array(s.object({ + step: s.string, + problem: s.string, + severity: s.enum("error", "warning", "info"), + })), + jobCount: s.int, + status: s.enum("pass", "warn", "fail"), + })), + agents: { workflowAnalyzer }, +}); + +export default workflowValidator; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts new file mode 100644 index 0000000..0b809d4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts @@ -0,0 +1,21 @@ +import { agent, p, s, steering, repair } from "rig"; + +// Agent role: rewrite recent git commit messages into conventional commit format with imperative mood. +const commitMsgRewriter = agent({ + model: "typecheck", + instructions: p`Review recent commits from ${p.bash("git log --oneline -20 2>/dev/null || echo 'no commits'")} and rewrite each message in conventional commit format (feat:/fix:/chore:/docs:/test:/refactor:/style: prefix) with imperative mood. Write a markdown summary of all rewrites via ${p.writeOutput("markdown", "commit-rewrites.md")}`, + output: s.object({ + rewrites: s.array(s.object({ + hash: s.string, + original: s.string, + revised: s.string, + category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), + })), + markdown: s.string, + }), + maxTurns: 6, + addons: [steering({ message: "Use imperative mood and conventional commit prefixes. Be consistent." }), repair()], +}); + +export default commitMsgRewriter; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts new file mode 100644 index 0000000..f4c7517 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts @@ -0,0 +1,28 @@ +import { agent, p, s, defineTool } from "rig"; + +const parseEnvKeys = defineTool("parseEnvKeys", { + description: "Extract KEY names from dotenv-style file content", + parameters: s.object({ content: s.string }), + handler({ content }) { + const keys = (content.match(/^([A-Z_][A-Z0-9_]*)=/gm) || []) + .map((line: string) => line.replace("=", "")); + return { keys }; + }, +}); + +// Agent role: compare .env.example required keys against .env actual keys to find missing and extra entries. +const envKeyChecker = agent({ + model: "typecheck", + instructions: p`Read the required env keys from ${p.readOptional(".env.example")} and the present keys from ${p.readOptional(".env")}. Use the parseEnvKeys tool on each file content to extract key names. Compare to find missing keys (in example but not env) and extra keys (in env but not example).`, + output: s.object({ + missing: s.array(s.string), + extra: s.array(s.string), + requiredCount: s.int, + presentCount: s.int, + status: s.enum("complete", "partial", "empty"), + }), + tools: [parseEnvKeys], +}); + +export default envKeyChecker; + diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts new file mode 100644 index 0000000..fd29459 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts @@ -0,0 +1,20 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: run the build and analyze the output for errors, warnings, and success status. +const buildLogAnalyzer = agent({ + model: "typecheck", + instructions: p`Run the build command and analyze its output: ${p.bash("npm run build 2>&1 || true")}. Extract all errors and warnings with their severity and file location if available. Determine whether the build succeeded overall.`, + output: s.object({ + errors: s.array(s.object({ + message: s.string, + file: s.optional(s.string), + severity: s.enum("error", "warning", "info"), + })), + buildSucceeded: s.boolean, + summary: s.string, + }), + maxTurns: 5, + addons: repair(), +}); + +export default buildLogAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts new file mode 100644 index 0000000..c0833c5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts @@ -0,0 +1,27 @@ +import { agent, p, s, defineTool } from "rig"; + +const categorizeAlias = defineTool("categorizeAlias", { + description: "Categorize a TypeScript type alias definition by its kind using regex", + parameters: s.object({ definition: s.string }), + handler({ definition }) { + const trimmed = definition.trim(); + if (/=\s*\w+\s*\|/.test(trimmed)) return { kind: "union" }; + if (/=\s*\w+\s*&/.test(trimmed)) return { kind: "intersection" }; + if (/=\s*\{[^}]*\[[^\]]+\]/.test(trimmed)) return { kind: "mapped" }; + if (/=\s*(string|number|boolean|null|undefined|never|any|unknown)\s*$/.test(trimmed)) return { kind: "primitive" }; + return { kind: "other" }; + }, +}); + +// Agent role: scan TypeScript files for type alias declarations and categorize each one. +const tsTypeAliasMapper = agent({ + model: "typecheck", + instructions: p`Find all TypeScript files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*'")} and scan their contents: ${p.bash("grep -rn 'type [A-Z]' --include='*.ts' --exclude-dir=node_modules --exclude-dir=.git . 2>/dev/null || true")}. Use the categorizeAlias tool to classify each type alias. For each alias, also record whether it is exported (starts with 'export type').`, + output: s.record(s.object({ + kind: s.enum("primitive", "union", "intersection", "mapped", "other"), + exported: s.boolean, + })), + tools: [categorizeAlias], +}); + +export default tsTypeAliasMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts new file mode 100644 index 0000000..b0298d4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts @@ -0,0 +1,14 @@ +import { agent, p, s } from "rig"; + +// Agent role: map git contributors to their commit counts, primary work areas, and role classification. +const gitContributorMapper = agent({ + model: "typecheck", + instructions: p`Analyze git contributors using: ${p.bash("git shortlog -sn --no-merges")} and ${p.bash("git log --no-merges --name-only --pretty=format:'%an' | head -500")}. For each contributor, count their commits, identify which directories they primarily touch, and classify their role as core (many commits across many files), peripheral (few commits or limited scope), or single-file.`, + output: s.record(s.object({ + commitCount: s.number, + primaryAreas: s.array(s.string), + role: s.enum("core", "peripheral", "single-file"), + })), +}); + +export default gitContributorMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts new file mode 100644 index 0000000..01fa916 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts @@ -0,0 +1,23 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize each top-level section of the README, then compile into a full report. +const sectionSummarizer = agent({ + name: "sectionSummarizer", + model: "typecheck", + instructions: p`Summarize the section of documentation provided in the input.`, + input: s.object({ heading: s.string, content: s.string }), + output: s.object({ heading: s.string, summary: s.string }), +}); + +// Agent role: read the project README, delegate per-section summarization, and write the final report. +const markdownDocSummarizer = agent({ + model: "typecheck", + instructions: p`Read the README: ${p.readOptional("README.md", "No README found.")}. Identify each top-level heading (##) and its content. Delegate summarization of each section to the sectionSummarizer agent. Compile all summaries into a report and write it to summaries/README-summary.md via ${p.writeOutput("reportPath", "summaries/README-summary.md")}.`, + output: s.object({ + sections: s.array(s.object({ heading: s.string, summary: s.string })), + reportPath: s.string, + }), + agents: { sectionSummarizer }, +}); + +export default markdownDocSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts new file mode 100644 index 0000000..1d32f32 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts @@ -0,0 +1,29 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseJson = defineTool("parseJson", { + description: "Parse a JSON string and return it, or report a parse error", + parameters: s.object({ content: s.string, filename: s.string }), + handler({ content, filename }) { + try { + const parsed = JSON.parse(content); + return { ok: true, parsed }; + } catch (e) { + return { ok: false, error: String(e), filename }; + } + }, +}); + +// Agent role: detect drift in workspace config files by reading them and comparing against known defaults. +const workspaceConfigDrift = agent({ + model: "typecheck", + instructions: p`Read project config files: ${p.readOptional("tsconfig.json", "{}")} (tsconfig.json), ${p.readOptional(".eslintrc.json", "{}")} (.eslintrc.json), ${p.readOptional(".prettierrc", "{}")} (.prettierrc). Use the parseJson tool to parse each file. For each config, identify fields that deviate from sensible defaults and report them as drifted. Assign status ok if no drift, warning for minor issues, error for significant mismatches.`, + output: s.record(s.object({ + driftedFields: s.array(s.string), + status: s.enum("ok", "warning", "error"), + })), + tools: [parseJson], + maxTurns: 4, + addons: repair(), +}); + +export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts new file mode 100644 index 0000000..28e2897 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair, steering } from "rig"; + +// Agent role: review recent git commits and suggest conventional-format rewrites for each one. +const commitFormatSuggester = agent({ + model: "typecheck", + instructions: p`Review recent git commits: ${p.bash("git log --oneline -20 --no-merges")}. For each commit, check whether its message follows conventional commit format (type: description). Suggest a rewritten message in conventional format. Classify each commit as one of: feat, fix, chore, docs, test, refactor, style. Write the full report to commit-report.md via ${p.writeOutput("reportWritten", "commit-report.md")}.`, + output: s.array(s.object({ + hash: s.string, + original: s.string, + suggested: s.string, + category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), + })), + maxTurns: 5, + addons: [steering(), repair()], +}); + +export default commitFormatSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts new file mode 100644 index 0000000..b960ec3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts @@ -0,0 +1,31 @@ +import { agent, p, s } from "rig"; + +// Agent role: analyze two JSON schema files to identify structural changes and produce a migration plan. +const diffAnalyzer = agent({ + name: "diffAnalyzer", + model: "typecheck", + instructions: p`Analyze the structural differences between the two JSON schemas provided in the input and list each change type (add, remove, modify, rename) with the JSON path and whether it is a breaking change.`, + input: s.object({ oldSchema: s.string, newSchema: s.string }), + output: s.array(s.object({ + changeType: s.enum("add", "remove", "modify", "rename"), + path: s.string, + description: s.string, + breakingChange: s.boolean, + })), +}); + +// Agent role: read two JSON schema files and coordinate a migration plan using the diffAnalyzer subagent. +const jsonSchemaMigration = agent({ + model: "typecheck", + input: s.object({ oldSchemaPath: s.path, newSchemaPath: s.path }), + instructions: p`Read the old schema at ${p.readInput("oldSchemaPath")} and new schema at ${p.readInput("newSchemaPath")}. Pass both to the diffAnalyzer subagent to identify all changes and whether each is a breaking change.`, + output: s.array(s.object({ + changeType: s.enum("add", "remove", "modify", "rename"), + path: s.string, + description: s.string, + breakingChange: s.boolean, + })), + agents: { diffAnalyzer }, +}); + +export default jsonSchemaMigration; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts new file mode 100644 index 0000000..ab26b5b --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts @@ -0,0 +1,41 @@ +import { agent, p, s, defineTool } from "rig"; + +const checkSecurityPattern = defineTool("checkSecurityPattern", { + description: "Check a Dockerfile line for known security anti-patterns", + parameters: s.object({ line: s.string, lineNumber: s.number }), + handler({ line, lineNumber }) { + const findings: Array<{ severity: string; message: string; rule: string }> = []; + if (/^USER\s+root\s*$/i.test(line.trim()) || /^RUN.*&&.*&&.*--no-check/.test(line)) { + findings.push({ severity: "critical", message: "Running as root user", rule: "no-root-user" }); + } + if (/ADD\s+/.test(line) && !/ADD\s+https?:\/\//.test(line)) { + findings.push({ severity: "medium", message: "Prefer COPY over ADD for local files", rule: "prefer-copy" }); + } + if (/FROM\s+\S+:latest/.test(line)) { + findings.push({ severity: "high", message: "Avoid :latest tag for reproducibility", rule: "no-latest-tag" }); + } + if (/ENV\s+\w*(KEY|SECRET|PASSWORD|TOKEN)\w*\s*=/.test(line)) { + findings.push({ severity: "critical", message: "Secret embedded in ENV instruction", rule: "no-secrets-in-env" }); + } + return { lineNumber, findings }; + }, +}); + +// Agent role: audit a Dockerfile for security issues by scanning each instruction for known anti-patterns. +const dockerfileSecurityAudit = agent({ + model: "typecheck", + input: s.object({ dockerfilePath: s.path }), + instructions: p`Read the Dockerfile at ${p.readInput("dockerfilePath")}. Use the checkSecurityPattern tool on each instruction line to detect security issues. Compile all findings with their severity, line number, rule, and message.`, + output: s.object({ + findings: s.array(s.object({ + severity: s.enum("critical", "high", "medium", "low"), + lineNumber: s.number, + message: s.string, + rule: s.string, + })), + passes: s.boolean, + }), + tools: [checkSecurityPattern], +}); + +export default dockerfileSecurityAudit; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts new file mode 100644 index 0000000..28553a8 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts @@ -0,0 +1,16 @@ +import { agent, p, s, repair } from "rig"; + +// Agent role: run npm audit, parse the JSON output, and produce a simplified vulnerability report. +const npmAuditSimplifier = agent({ + model: "typecheck", + instructions: p`Run ${p.bash("npm audit --json 2>/dev/null || echo '{}'")} to get the vulnerability report. Parse the JSON and group vulnerabilities by severity level (critical, high, moderate, low, info). Count the total number of vulnerabilities. Provide a one-sentence recommendation for remediation.`, + output: s.object({ + vulnerabilitiesByLevel: s.record(s.array(s.string)), + totalCount: s.number, + recommendation: s.string, + }), + maxTurns: 5, + addons: repair(), +}); + +export default npmAuditSimplifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts new file mode 100644 index 0000000..20fd44e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts @@ -0,0 +1,15 @@ +import { agent, p, s } from "rig"; + +// Agent role: inventory all git stashes with their descriptions, changed files, and staleness classification. +const gitStashInventory = agent({ + model: "typecheck", + instructions: p`List all git stashes: ${p.bash("git stash list 2>/dev/null || echo 'No stashes found'")}. For each stash entry shown, show its changed files: ${p.bash("git stash show --name-only 2>/dev/null || true")}. For each stash, classify its staleness as: fresh (< 1 week), aging (1-4 weeks), stale (1-3 months), ancient (> 3 months) based on the date shown in the stash list.`, + output: s.array(s.object({ + stashRef: s.string, + description: s.string, + changedFiles: s.array(s.string), + staleness: s.enum("fresh", "aging", "stale", "ancient"), + })), +}); + +export default gitStashInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts new file mode 100644 index 0000000..b0298d4 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts @@ -0,0 +1,14 @@ +import { agent, p, s } from "rig"; + +// Agent role: map git contributors to their commit counts, primary work areas, and role classification. +const gitContributorMapper = agent({ + model: "typecheck", + instructions: p`Analyze git contributors using: ${p.bash("git shortlog -sn --no-merges")} and ${p.bash("git log --no-merges --name-only --pretty=format:'%an' | head -500")}. For each contributor, count their commits, identify which directories they primarily touch, and classify their role as core (many commits across many files), peripheral (few commits or limited scope), or single-file.`, + output: s.record(s.object({ + commitCount: s.number, + primaryAreas: s.array(s.string), + role: s.enum("core", "peripheral", "single-file"), + })), +}); + +export default gitContributorMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts new file mode 100644 index 0000000..43704e3 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts @@ -0,0 +1,23 @@ +import { agent, p, s } from "rig"; + +// Agent role: summarize each top-level section of a markdown doc, then compile into a full report. +const sectionSummarizer = agent({ + name: "sectionSummarizer", + model: "typecheck", + instructions: p`Summarize the section of documentation provided in the input.`, + input: s.object({ heading: s.string, content: s.string }), + output: s.object({ heading: s.string, summary: s.string }), +}); + +// Agent role: read the project README, delegate per-section summarization, and write the final report. +const markdownDocSummarizer = agent({ + model: "typecheck", + instructions: p`Read the README: ${p.readOptional("README.md", "No README found.")}. Identify each top-level heading (##) and its content. Delegate summarization of each section to the sectionSummarizer agent. Compile all summaries into a report and write it to summaries/README-summary.md via ${p.writeOutput("reportPath", "summaries/README-summary.md")}.`, + output: s.object({ + sections: s.array(s.object({ heading: s.string, summary: s.string })), + reportPath: s.string, + }), + agents: { sectionSummarizer }, +}); + +export default markdownDocSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts new file mode 100644 index 0000000..1d32f32 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts @@ -0,0 +1,29 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const parseJson = defineTool("parseJson", { + description: "Parse a JSON string and return it, or report a parse error", + parameters: s.object({ content: s.string, filename: s.string }), + handler({ content, filename }) { + try { + const parsed = JSON.parse(content); + return { ok: true, parsed }; + } catch (e) { + return { ok: false, error: String(e), filename }; + } + }, +}); + +// Agent role: detect drift in workspace config files by reading them and comparing against known defaults. +const workspaceConfigDrift = agent({ + model: "typecheck", + instructions: p`Read project config files: ${p.readOptional("tsconfig.json", "{}")} (tsconfig.json), ${p.readOptional(".eslintrc.json", "{}")} (.eslintrc.json), ${p.readOptional(".prettierrc", "{}")} (.prettierrc). Use the parseJson tool to parse each file. For each config, identify fields that deviate from sensible defaults and report them as drifted. Assign status ok if no drift, warning for minor issues, error for significant mismatches.`, + output: s.record(s.object({ + driftedFields: s.array(s.string), + status: s.enum("ok", "warning", "error"), + })), + tools: [parseJson], + maxTurns: 4, + addons: repair(), +}); + +export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts new file mode 100644 index 0000000..28e2897 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts @@ -0,0 +1,17 @@ +import { agent, p, s, repair, steering } from "rig"; + +// Agent role: review recent git commits and suggest conventional-format rewrites for each one. +const commitFormatSuggester = agent({ + model: "typecheck", + instructions: p`Review recent git commits: ${p.bash("git log --oneline -20 --no-merges")}. For each commit, check whether its message follows conventional commit format (type: description). Suggest a rewritten message in conventional format. Classify each commit as one of: feat, fix, chore, docs, test, refactor, style. Write the full report to commit-report.md via ${p.writeOutput("reportWritten", "commit-report.md")}.`, + output: s.array(s.object({ + hash: s.string, + original: s.string, + suggested: s.string, + category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), + })), + maxTurns: 5, + addons: [steering(), repair()], +}); + +export default commitFormatSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts new file mode 100644 index 0000000..e9af2db --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts @@ -0,0 +1,32 @@ +import { agent, p, s, defineTool } from "rig"; + +const checkThresholds = defineTool("checkThresholds", { + description: "Validate environment values against minimum thresholds and return a list of issues", + parameters: s.object({ + nodeVersion: s.string, + heapMB: s.number, + }), + handler({ nodeVersion, heapMB }) { + const issues: string[] = []; + const majorVersion = parseInt(nodeVersion.replace("v", "").split(".")[0], 10); + if (majorVersion < 18) issues.push(`Node.js ${nodeVersion} is below minimum v18`); + if (heapMB < 256) issues.push(`Heap ${heapMB}MB is below 256MB minimum`); + return { issues }; + }, +}); + +// Agent role: inspect the runtime environment and report overall health. +const runtimeEnvChecker = agent({ + model: "typecheck", + instructions: p`Inspect the runtime environment using: ${p.bash("node --version")}, ${p.bash("uname -a")}, and ${p.bash("node -e \"console.log(Math.round(process.memoryUsage().heapTotal/1024/1024))\"")}. Use the checkThresholds tool to validate versions and memory. Determine overall health as ok, degraded, or critical based on issues found.`, + output: s.object({ + health: s.enum("ok", "degraded", "critical"), + nodeVersion: s.string, + os: s.string, + heapMB: s.number, + issues: s.array(s.string), + }), + tools: [checkThresholds], +}); + +export default runtimeEnvChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts new file mode 100644 index 0000000..148a79c --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts @@ -0,0 +1,16 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: analyze which source files are hot-spots by measuring churn and top contributors. +const hotspotFileAnalyzer = agent({ + model: "typecheck", + instructions: p`Analyze file churn in this repository. Get recently changed files using ${p.bash("git log --name-only --format='' HEAD~100..HEAD | sort | uniq -c | sort -rn | head -30")} and contributor data using ${p.bash("git shortlog -sn --no-merges HEAD~100..HEAD")}. For each hot-spot file, compute a churnScore 0–100 based on how often it changes, list topContributors, and classify riskLevel as low, medium, or high.`, + output: s.record(s.object({ + churnScore: s.number, + topContributors: s.array(s.string), + riskLevel: s.enum("low", "medium", "high"), + })), + maxTurns: 5, + addons: steering({ message: "Ensure every file entry has a numeric churnScore and at least one topContributor." }), +}); + +export default hotspotFileAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts new file mode 100644 index 0000000..19239a5 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts @@ -0,0 +1,45 @@ +import { agent, p, s, defineTool, repair } from "rig"; + +const scanInterfaces = defineTool("scanInterfaces", { + description: "Scan a TypeScript file for exported interface names using grep", + parameters: s.object({ filePath: s.string }), + async handler({ filePath }) { + const { execSync } = await import("node:child_process"); + try { + const result = execSync( + `grep -n "^export interface\\|^interface " "${filePath}" 2>/dev/null || true`, + { encoding: "utf8" } + ); + const names = result + .split("\n") + .filter(Boolean) + .map((line) => { + const m = line.match(/interface\s+(\w+)/); + return m ? m[1] : null; + }) + .filter(Boolean) as string[]; + return { filePath, names }; + } catch { + return { filePath, names: [] }; + } + }, +}); + +// Agent role: find duplicate TypeScript interface names across all source files in the project. +const tsInterfaceConflictChecker = agent({ + model: "typecheck", + instructions: p`Find all TypeScript source files using ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | head -80")}. Use the scanInterfaces tool on each file to collect interface names. Identify any interface name declared in more than one file. Classify each conflict as warning (same name, compatible) or error (likely clash). Set hasConflicts to true if any conflicts exist.`, + output: s.object({ + conflicts: s.array(s.object({ + interfaceName: s.string, + files: s.array(s.string), + severity: s.enum("warning", "error"), + })), + hasConflicts: s.boolean, + }), + tools: [scanInterfaces], + maxTurns: 6, + addons: repair(), +}); + +export default tsInterfaceConflictChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts new file mode 100644 index 0000000..c4f0cf1 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts @@ -0,0 +1,44 @@ +import { agent, p, s, defineTool } from "rig"; + +const parseWorktreePorcelain = defineTool("parseWorktreePorcelain", { + description: "Parse the output of git worktree list --porcelain into structured entries", + parameters: s.object({ output: s.string }), + handler({ output }) { + const entries: Array<{ path: string; branch?: string; state: string }> = []; + const blocks = output.trim().split("\n\n"); + for (const block of blocks) { + const lines = block.split("\n"); + const pathLine = lines.find((l) => l.startsWith("worktree ")); + const branchLine = lines.find((l) => l.startsWith("branch ")); + const isLocked = lines.some((l) => l.startsWith("locked")); + const isBare = lines.some((l) => l.startsWith("bare")); + const entry: { path: string; branch?: string; state: string } = { + path: pathLine ? pathLine.replace("worktree ", "") : "", + state: isLocked ? "locked" : isBare ? "bare" : "clean", + }; + if (branchLine) entry.branch = branchLine.replace("branch refs/heads/", ""); + if (entry.path) entries.push(entry); + } + return entries; + }, +}); + +// Agent role: list and classify all git worktrees in the current repository. +const gitWorktreeMapper = agent({ + model: "typecheck", + instructions: p`List all git worktrees using ${p.bash("git worktree list --porcelain")}. Use the parseWorktreePorcelain tool to parse the output. Determine the state of each worktree (locked, bare, clean, or dirty if there are uncommitted changes). Provide a summary with totalCount and activeCount (non-bare worktrees).`, + output: s.object({ + worktrees: s.array(s.object({ + path: s.string, + branch: s.optional(s.string), + state: s.enum("locked", "bare", "clean", "dirty"), + })), + summary: s.object({ + totalCount: s.number, + activeCount: s.number, + }), + }), + tools: [parseWorktreePorcelain], +}); + +export default gitWorktreeMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts new file mode 100644 index 0000000..b60200f --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts @@ -0,0 +1,18 @@ +import { agent, p, s, steering } from "rig"; + +// Agent role: audit test file naming conventions and report files that violate the standard pattern. +const testNamingEnforcer = agent({ + model: "typecheck", + instructions: p`Find all test files in this project using ${p.bash("find . \\( -name '*.test.ts' -o -name '*.spec.ts' -o -name '*.test.js' -o -name '*.spec.js' \\) -not -path '*/node_modules/*' | head -60")}. For each file, check whether it follows the convention of .test.ts or .spec.ts. Classify as correct if it matches, wrong-prefix if the name before the extension separator is unusual, wrong-suffix if it ends differently, or missing-spec if it should be a test file but lacks the marker. Suggest a corrected name where applicable. Set allConform to true only if every file is classified as correct.`, + output: s.object({ + files: s.record(s.object({ + convention: s.enum("correct", "wrong-prefix", "wrong-suffix", "missing-spec"), + suggestedName: s.optional(s.string), + })), + allConform: s.boolean, + }), + maxTurns: 5, + addons: steering({ message: "Ensure every discovered test file has an entry in files and allConform is a boolean." }), +}); + +export default testNamingEnforcer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts new file mode 100644 index 0000000..9990514 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts @@ -0,0 +1,36 @@ +import { agent, p, s, defineTool } from "rig"; + +const classifyDependency = defineTool("classifyDependency", { + description: "Classify a dependency as runtime, dev, or peer based on its presence in package.json sections", + parameters: s.object({ + name: s.string, + inDependencies: s.boolean, + inDevDependencies: s.boolean, + inPeerDependencies: s.boolean, + }), + handler({ inDependencies, inDevDependencies, inPeerDependencies }) { + if (inPeerDependencies) return "peer"; + if (inDevDependencies) return "dev"; + if (inDependencies) return "runtime"; + return "dev"; + }, +}); + +// Agent role: extract and classify direct dependencies from package.json, then describe the overall tree shape. +const pkgDependencyGraph = agent({ + model: "typecheck", + instructions: p`Read the project manifest: ${p.read("package.json")}. Get the resolved dependency tree using ${p.bash("npm ls --json --depth=1 2>/dev/null || echo '{}'")}. Use the classifyDependency tool to classify each direct dependency as runtime, dev, or peer. Also list all devDependency names. Estimate the treeShape as flat (<5 deps), shallow (5–20), or deep (>20) and set depthScore to the total direct dependency count.`, + output: s.object({ + directDeps: s.array(s.object({ + name: s.string, + version: s.string, + type: s.enum("runtime", "dev", "peer"), + })), + devDeps: s.array(s.string), + treeShape: s.enum("flat", "shallow", "deep"), + depthScore: s.number, + }), + tools: [classifyDependency], +}); + +export default pkgDependencyGraph; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts new file mode 100644 index 0000000..53a5b07 --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts @@ -0,0 +1,35 @@ +import { agent, defineTool, p, s } from "rig"; + +const getProcessInfo = defineTool("getProcessInfo", { + description: "Get running-process details for a named process using node:child_process", + parameters: s.object({ name: s.string("process name") }), + async handler({ name }) { + const { execSync } = await import("node:child_process"); + try { + const out = execSync( + `ps -eo pid,comm,rss,etime 2>/dev/null | grep "${name}" | head -5 || true`, + { encoding: "utf8" } + ); + return out.trim() || "not found"; + } catch { + return "not found"; + } + }, +}); + +// Agent role: summarize running Node.js processes and their resource usage. +const processReport = agent({ + model: "typecheck", + instructions: p`Inspect running processes with ${p.bash("ps aux | grep -E 'node|npm' | head -20")}. Use getProcessInfo for any named process you need details on.`, + output: s.object({ + processes: s.array(s.object({ + name: s.string, + pid: s.string, + status: s.enum("running", "idle", "unknown"), + })), + summary: s.string, + }), + tools: [getProcessInfo], +}); + +export default processReport; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts new file mode 100644 index 0000000..e2db29e --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts @@ -0,0 +1,25 @@ +import { agent, p, s } from "rig"; + +const ProbeResult = s.object({ + results: s.array(s.object({ url: s.url, status: s.string })), + allHealthy: s.boolean, +}); + +// Agent role: probe each endpoint and report its HTTP status code. +const endpointProbe = agent({ + name: "endpointProbe", + model: "typecheck", + input: s.object({ endpoints: s.array(s.url) }), + instructions: p`${p.bashEach("curl -s -o /dev/null -w '%{http_code}' {} --max-time 5", "endpoints")}`, + output: ProbeResult, +}); + +// Agent role: supply the endpoint list and delegate probing to endpointProbe. +const healthProbe = agent({ + model: "typecheck", + agents: { endpointProbe }, + instructions: p`Delegate to endpointProbe with endpoints ["https://example.com", "https://example.org"], then return its result unchanged.`, + output: ProbeResult, +}); + +export default healthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json b/scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json new file mode 100644 index 0000000..fa799ae --- /dev/null +++ b/scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "./*.ts" + ] +} \ No newline at end of file From c48c50054602990e345e4a92ae6e211c8de71869 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:12:02 +0000 Subject: [PATCH 3/4] Fix nested Rig sampler transport Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/daily-rig-sampler.lock.yml | 2 +- .github/workflows/daily-rig-sampler.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/daily-rig-sampler.lock.yml b/.github/workflows/daily-rig-sampler.lock.yml index ed20c8a..9b74336 100644 --- a/.github/workflows/daily-rig-sampler.lock.yml +++ b/.github/workflows/daily-rig-sampler.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"9f127e906fa8f488c8cdcfad79c42c23aff996fd3f32cba1386de7e8c5773c1a","body_hash":"39a5ac1e73343bf7052f6712c5dc5427f7b73ed3521291d4e9777706ac2b6176","compiler_version":"v0.83.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.73","copilot-sdk":"1.0.7"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"9f127e906fa8f488c8cdcfad79c42c23aff996fd3f32cba1386de7e8c5773c1a","body_hash":"76468540d57bf2b901310d760f0d8f42f27d52c803c61629afb0b06634cf008d","compiler_version":"v0.83.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.73","copilot-sdk":"1.0.7"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"v0.83.1","version":"v0.83.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.38","digest":"sha256:cb928eb62d9139a013c2d278dab19af232d35a2d83dca71a3d98eb431f786243","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.38@sha256:cb928eb62d9139a013c2d278dab19af232d35a2d83dca71a3d98eb431f786243"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.38","digest":"sha256:cd6145620d96acee46e1ede25180a13aa36002467e663db0caa453a8bc8eb60c","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.38@sha256:cd6145620d96acee46e1ede25180a13aa36002467e663db0caa453a8bc8eb60c"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.38","digest":"sha256:6c19094d95aad5f9f128ad5e583f0f2b894b158aa66c3b86dd9bcc90970a2917","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.38@sha256:6c19094d95aad5f9f128ad5e583f0f2b894b158aa66c3b86dd9bcc90970a2917"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.3","digest":"sha256:3c744710ea275cd5ee65db92a1099e0d980754bd9fafda9ce67704c67004dc83","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.3@sha256:3c744710ea275cd5ee65db92a1099e0d980754bd9fafda9ce67704c67004dc83"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748","pinned_image":"ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748"},{"image":"ghcr.io/github/github-mcp-server:v1.6.0","digest":"sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3","pinned_image":"ghcr.io/github/github-mcp-server:v1.6.0@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3"}]} # This file was automatically generated by gh-aw (v0.83.1). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/.github/workflows/daily-rig-sampler.md b/.github/workflows/daily-rig-sampler.md index 2ef753e..05b4121 100644 --- a/.github/workflows/daily-rig-sampler.md +++ b/.github/workflows/daily-rig-sampler.md @@ -39,7 +39,7 @@ Run this Rig program: ```rig import { agent, configureAgent, copilotEngine, defineTool, p, s } from "rig"; -configureAgent(copilotEngine()); +configureAgent(copilotEngine({ server: true })); const SampleRun = s.object({ path: s.path, @@ -69,7 +69,7 @@ const runRigSample = defineTool("run_rig_sample", { } return await new Promise((resolveRun, rejectRun) => { - const child = spawn(process.execPath, ["skills/rig/rig.ts"], { + const child = spawn(process.execPath, ["skills/rig/rig.ts", "--server"], { cwd: process.cwd(), env: { ...process.env, From 3b0b9c5d4c8ead0651f45e9d2c905ffb4d5b455f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:23:26 +0000 Subject: [PATCH 4/4] Remove generated sample typecheck files Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../02-review-git-diff.ts | 5 -- .../03-diagnose-test-failure.ts | 21 ----- .../04-generate-readme.ts | 16 ---- .../05-write-readme-intent.ts | 14 ---- .../06-list-source-files.ts | 15 ---- .../07-summarize-many-files.ts | 10 --- .../08-extract-package-scripts.ts | 8 -- .../09-classify-issue.ts | 14 ---- .../10-triage-pr.ts | 14 ---- .../100-workspace-config-drift-2.ts | 28 ------- .../101-commit-format-suggester-2.ts | 17 ---- .../102-runtime-env-checker-2.ts | 29 ------- .../103-hotspot-file-analyzer-2.ts | 15 ---- .../104-loc-statistics.ts | 35 -------- .../105-import-cycle-detector-2.ts | 18 ----- .../106-ts-export-usage.ts | 32 -------- .../107-git-rename-tracker.ts | 17 ---- .../108-yaml-lint-checker.ts | 36 --------- .../109-two-phase-complexity-review.ts | 29 ------- .../11-release-notes.ts | 13 --- .../110-workspace-config-drift-3.ts | 43 ---------- .../111-conventional-commit-suggester.ts | 27 ------- .../112-runtime-env-health.ts | 35 -------- .../113-git-hotspot-analyzer.ts | 26 ------ .../114-loc-statistics-gatherer.ts | 35 -------- .../115-import-cycle-detector.ts | 37 --------- .../116-barrel-file-generator.ts | 42 ---------- .../117-git-hook-inventory.ts | 38 --------- .../118-pr-review-checklist.ts | 39 --------- .../119-source-map-analyzer.ts | 43 ---------- .../12-security-scan-review.ts | 13 --- .../120-git-hotspot-v2.ts | 47 ----------- .../121-loc-stats-gatherer.ts | 44 ---------- .../122-import-cycle-detector.ts | 36 --------- .../123-coverage-badge-updater.ts | 30 ------- .../124-dep-license-auditor.ts | 45 ----------- .../125-test-coverage-mapper.ts | 50 ------------ .../126-tsconfig-options-auditor.ts | 57 ------------- .../127-git-commit-annotator.ts | 52 ------------ .../128-npm-script-dep-mapper.ts | 57 ------------- .../129-markdown-link-checker.ts | 57 ------------- .../13-test-plan.ts | 15 ---- .../130-git-hotspot-analyzer.ts | 15 ---- .../131-loc-statistics-gatherer.ts | 37 --------- .../132-import-cycle-detector.ts | 26 ------ .../133-coverage-badge-updater.ts | 22 ----- .../134-dep-license-auditor.ts | 37 --------- .../135-test-coverage-mapper.ts | 35 -------- .../136-pkg-version-drift.ts | 27 ------- .../137-git-author-stats.ts | 24 ------ .../138-ts-path-alias-validator.ts | 37 --------- .../139-markdown-frontmatter-checker.ts | 40 --------- .../14-changelog-categorizer.ts | 12 --- .../140-git-hotspot-analyzer.ts | 36 --------- .../141-loc-statistics-gatherer.ts | 45 ----------- .../142-import-cycle-detector.ts | 34 -------- .../143-coverage-badge-updater.ts | 29 ------- .../144-dep-license-auditor.ts | 50 ------------ .../145-test-coverage-mapper.ts | 51 ------------ .../146-file-permission-scanner.ts | 41 ---------- .../147-git-submodule-health.ts | 49 ----------- .../148-ts-decorator-scanner.ts | 47 ----------- .../149-dotfile-inventory.ts | 36 --------- .../15-api-diff-summary.ts | 12 --- .../150-git-hotspot-analyzer-v3.ts | 38 --------- .../151-loc-statistics-v2.ts | 52 ------------ .../152-import-cycle-detector-v3.ts | 34 -------- .../153-coverage-badge-updater-v2.ts | 35 -------- .../154-dep-license-auditor-v2.ts | 37 --------- .../155-test-coverage-mapper-v2.ts | 51 ------------ .../156-regex-pattern-tester.ts | 59 -------------- .../157-commit-churn-classifier.ts | 27 ------- .../158-npm-package-size.ts | 44 ---------- .../159-ts-branch-coverage.ts | 58 ------------- .../16-docs-gap-analysis.ts | 12 --- .../160-dead-code-detector.ts | 44 ---------- .../161-openapi-spec-validator.ts | 48 ----------- .../162-api-endpoint-extractor.ts | 36 --------- .../163-source-file-annotator.ts | 37 --------- .../164-stale-dependency-detector.ts | 42 ---------- .../165-git-tag-timeline.ts | 46 ----------- .../166-env-variable-type-inferrer.ts | 40 --------- .../167-makefile-target-extractor.ts | 43 ---------- .../168-test-fixture-generator.ts | 41 ---------- .../169-server-uptime-log-parser.ts | 41 ---------- .../17-refactor-plan.ts | 12 --- .../170-stale-dep-detector.ts | 36 --------- .../171-git-tag-timeline.ts | 36 --------- .../172-service-health-probe.ts | 19 ----- .../173-git-template-renderer.ts | 31 ------- .../174-changelog-entry-gen.ts | 29 ------- .../175-todo-comment-tracker.ts | 19 ----- .../176-css-variable-extractor.ts | 28 ------- .../177-openapi-route-coverage.ts | 32 -------- .../178-import-style-checker.ts | 37 --------- .../179-git-tag-semver-validator.ts | 40 --------- .../18-patch-writer-output.ts | 12 --- .../180-git-tag-timeline-reporter.ts | 31 ------- .../181-service-health-probe.ts | 20 ----- .../182-git-metadata-template-renderer.ts | 27 ------- .../183-changelog-entry-generator.ts | 32 -------- .../184-todo-fixme-tracker.ts | 20 ----- .../185-multi-file-glob-summarizer.ts | 20 ----- .../186-shell-script-analyzer.ts | 39 --------- .../187-lock-file-drift-detector.ts | 53 ------------ .../188-git-conflict-marker-scanner.ts | 20 ----- .../189-proto-field-extractor.ts | 50 ------------ .../19-fix-then-review.ts | 12 --- .../190-commit-msg-rewriter.ts | 17 ---- .../190-git-tag-timeline-reporter.ts | 50 ------------ .../191-env-key-checker.ts | 24 ------ .../191-service-health-probe.ts | 37 --------- .../192-git-metadata-template-renderer.ts | 41 ---------- .../192-json-schema-migration-planner.ts | 31 ------- .../193-changelog-entry-generator.ts | 29 ------- .../193-dockerfile-security-auditor.ts | 28 ------- .../194-npm-audit-simplifier.ts | 16 ---- .../194-todo-fixme-tracker.ts | 40 --------- .../195-git-stash-inventory.ts | 15 ---- .../195-multi-file-glob-summarizer.ts | 39 --------- .../196-git-remote-inspector.ts | 48 ----------- .../196-http-endpoint-health-checker.ts | 42 ---------- .../197-git-blame-ownership.ts | 37 --------- .../197-ts-enum-extractor.ts | 40 --------- .../198-json-config-merger.ts | 58 ------------- .../198-ts-generic-type-extractor.ts | 28 ------- .../199-shell-script-validator.ts | 33 -------- .../199-source-complexity-heatmap.ts | 40 --------- .../20-issue-reproducer.ts | 14 ---- .../200-npm-audit-simplifier.ts | 16 ---- .../201-git-stash-inventory.ts | 17 ---- .../202-ts-interface-conflict-checker.ts | 45 ----------- .../203-git-worktree-mapper.ts | 44 ---------- .../204-test-naming-enforcer.ts | 18 ----- .../205-pkg-dependency-graph.ts | 36 --------- .../206-ci-flake-triager.ts | 17 ---- .../207-config-drift-reconciler.ts | 20 ----- .../208-release-note-enricher.ts | 33 -------- .../209-docs-refactor-coordinator.ts | 31 ------- .../21-ci-log-diagnosis.ts | 14 ---- .../210-test-file-naming-enforcer.ts | 39 --------- .../211-pkg-dependency-graph-extractor.ts | 36 --------- .../212-ts-export-usage-counter.ts | 40 --------- .../213-git-rename-tracker.ts | 17 ---- .../214-yaml-lint-checker.ts | 41 ---------- .../215-two-phase-complexity-review.ts | 30 ------- .../216-dockerfile-layer-analyzer.ts | 41 ---------- .../217-git-worktree-status.ts | 38 --------- .../218-ts-interface-conflict-checker.ts | 52 ------------ .../219-npm-audit-simplifier.ts | 39 --------- .../22-config-normalizer.ts | 12 --- .../220-git-rename-tracker-v2.ts | 21 ----- .../221-yaml-workflow-linter.ts | 41 ---------- .../222-two-phase-complexity-review-v2.ts | 33 -------- .../223-barrel-file-generator-v2.ts | 31 ------- .../224-git-hook-inventory-v2.ts | 30 ------- .../225-pr-review-checklist-v2.ts | 28 ------- .../226-js-ast-node-counter.ts | 40 --------- .../227-git-tag-date-mapper.ts | 44 ---------- .../228-circular-import-detector.ts | 49 ----------- .../229-package-json-scorer.ts | 46 ----------- .../23-schema-inference.ts | 11 --- .../230-git-rename-tracker-v3.ts | 25 ------ .../231-yaml-workflow-linter-v2.ts | 41 ---------- .../232-two-phase-complexity-review-v3.ts | 69 ---------------- .../233-barrel-file-generator-v3.ts | 39 --------- .../234-git-hook-inventory-v3.ts | 44 ---------- .../235-pr-review-checklist-v3.ts | 30 ------- .../236-vitest-coverage-parser.ts | 61 -------------- .../237-git-log-stats-aggregator.ts | 48 ----------- .../238-ts-import-depth-analyzer.ts | 48 ----------- .../239-env-file-completeness-checker.ts | 47 ----------- .../24-error-message-improver.ts | 15 ---- .../240-git-commit-annotator.ts | 36 --------- .../241-npm-script-dep-mapper.ts | 54 ------------- .../242-markdown-link-checker.ts | 55 ------------- .../243-package-version-drift.ts | 31 ------- .../244-git-author-stats.ts | 28 ------- .../245-ts-path-alias-validator.ts | 39 --------- .../246-stale-branch-detector.ts | 43 ---------- .../247-license-header-checker.ts | 50 ------------ .../248-yaml-config-diff.ts | 53 ------------ .../249-monorepo-workspace-lister.ts | 53 ------------ .../25-migration-guide.ts | 12 --- .../250-git-commit-annotator.ts | 47 ----------- .../251-npm-script-dep-mapper.ts | 47 ----------- .../252-markdown-link-checker.ts | 56 ------------- .../253-package-version-drift.ts | 35 -------- .../254-git-author-stats.ts | 33 -------- .../255-ts-path-alias-validator.ts | 44 ---------- .../256-gh-actions-timing-analyzer.ts | 52 ------------ .../257-binary-file-detector.ts | 53 ------------ .../258-ts-interface-inheritance-graph.ts | 50 ------------ .../259-dep-license-matrix.ts | 58 ------------- .../26-design-review.ts | 16 ---- .../260-git-submodule-health.ts | 49 ----------- .../261-ts-decorator-scanner.ts | 45 ----------- .../262-dotfile-inventory.ts | 48 ----------- .../263-regex-pattern-tester.ts | 59 -------------- .../264-commit-churn-classifier.ts | 27 ------- .../265-npm-package-size.ts | 41 ---------- .../266-tsconfig-option-analyzer.ts | 52 ------------ .../267-git-patch-summarizer.ts | 50 ------------ .../268-npm-lifecycle-analyzer.ts | 47 ----------- .../269-ts-jsdoc-coverage.ts | 70 ---------------- .../27-dependency-upgrade-plan.ts | 14 ---- .../270-dotfile-inventory-mapper.ts | 53 ------------ .../271-regex-pattern-tester.ts | 54 ------------- .../272-commit-churn-classifier.ts | 36 --------- .../273-npm-package-size-estimator.ts | 39 --------- .../274-ts-branch-coverage-analyzer.ts | 52 ------------ .../275-env-variable-type-inferrer.ts | 41 ---------- .../276-git-hook-installer.ts | 50 ------------ .../277-ts-type-guard-generator.ts | 42 ---------- .../278-json-fixture-anonymizer.ts | 46 ----------- .../279-csv-to-markdown-table.ts | 40 --------- .../28-license-check.ts | 16 ---- .../280-commit-churn-classifier.ts | 27 ------- .../281-npm-package-size-estimator.ts | 37 --------- .../282-ts-branch-coverage-analyzer.ts | 40 --------- .../283-env-variable-type-inferrer.ts | 37 --------- .../284-makefile-target-extractor.ts | 58 ------------- .../285-test-fixture-generator.ts | 37 --------- .../286-toml-config-analyzer.ts | 40 --------- .../287-git-checkpoint-summarizer.ts | 40 --------- .../288-ts-literal-union-extractor.ts | 44 ---------- .../289-markdown-heading-validator.ts | 52 ------------ .../29-bug-report-draft.ts | 16 ---- .../290-commit-churn-classifier.ts | 26 ------ .../291-npm-package-size-estimator.ts | 33 -------- .../292-ts-branch-coverage-analyzer.ts | 38 --------- .../293-env-variable-type-inferrer.ts | 31 ------- .../294-makefile-target-extractor.ts | 37 --------- .../295-test-fixture-generator.ts | 33 -------- .../296-git-file-ownership-mapper.ts | 44 ---------- .../297-workflow-input-validator.ts | 48 ----------- .../298-ts-dead-export-finder.ts | 44 ---------- .../299-package-json-scripts-documenter.ts | 44 ---------- .../30-github-action-review.ts | 12 --- .../300-server-uptime-log-parser.ts | 42 ---------- .../301-css-variable-extractor.ts | 37 --------- .../302-openapi-route-coverage.ts | 47 ----------- .../303-import-style-checker.ts | 40 --------- .../304-git-tag-semver-validator.ts | 47 ----------- .../305-shell-script-safety-analyzer.ts | 44 ---------- .../306-git-diff-stats-summarizer.ts | 45 ----------- .../307-dotenv-template-generator.ts | 46 ----------- .../308-ts-class-hierarchy-extractor.ts | 52 ------------ .../309-git-bisect-helper.ts | 41 ---------- .../31-monorepo-package-map.ts | 12 --- .../310-lock-file-drift-detector.ts | 66 --------------- .../310-workflow-audit-verify.ts | 29 ------- .../311-git-conflict-marker-scanner.ts | 28 ------- .../312-proto-field-extractor.ts | 50 ------------ .../313-git-remote-url-inspector.ts | 46 ----------- .../314-ts-enum-value-extractor.ts | 44 ---------- .../315-json-config-merger.ts | 81 ------------------- .../316-markdown-toc-generator.ts | 42 ---------- .../317-git-author-email-domains.ts | 33 -------- .../318-ts-barrel-re-exporter.ts | 19 ----- .../319-workflow-step-duration-estimator.ts | 65 --------------- .../32-command-planner.ts | 19 ----- .../33-readonly-investigator.ts | 15 ---- .../34-intent-options.ts | 11 --- .../35-call-options.ts | 11 --- .../36-subagent-delegation.ts | 15 ---- .../37-output-with-nullable.ts | 22 ----- .../38-exact-literal-output.ts | 12 --- .../39-unknown-raw-output.ts | 13 --- .../40-record-output.ts | 11 --- .../41-parse-coverage.ts | 14 ---- .../42-json-repair.ts | 14 ---- .../43-snapshot-test-updater.ts | 12 --- .../44-flaky-test-analysis.ts | 12 --- .../45-code-owner-suggestion.ts | 12 --- .../46-prompt-intent-inspection.ts | 11 --- .../47-prompt-intents.ts | 11 --- .../48-custom-engine.ts | 8 -- .../49-timeout-signal-helper.ts | 8 -- .../50-end-to-end-release-agent.ts | 26 ------ .../51-subagent-task-harness.ts | 21 ----- .../52-claude-design.ts | 25 ------ .../53-ralf-loop.ts | 22 ----- .../54-large-scale-summarization.ts | 13 --- .../55-file-change-lint-middleware.ts | 23 ------ .../55-genaiscript-glossary-port.ts | 8 -- .../56-genaiscript-refactor-batch-port.ts | 10 --- .../57-genaiscript-issue-review-port.ts | 8 -- .../58-genaiscript-travel-plan-port.ts | 11 --- .../59-genaiscript-city-info-port.ts | 8 -- .../60-genaiscript-schema-cities-port.ts | 8 -- .../60-workflow-parallel-linter.ts | 24 ------ .../61-genaiscript-list-files-port.ts | 8 -- .../62-genaiscript-todo-port.ts | 8 -- .../63-genaiscript-slide-deck-port.ts | 8 -- .../64-genaiscript-grumpy-review-port.ts | 8 -- .../65-source-file-annotator.ts | 23 ------ .../66-ci-workflow-health.ts | 29 ------- .../67-glob-file-summarizer.ts | 17 ---- .../68-changelog-generator.ts | 31 ------- .../69-todo-comment-tracker.ts | 20 ----- .../70-multi-file-subagent-summarizer.ts | 29 ------- .../71-package-script-health.ts | 31 ------- .../72-ts-function-signatures.ts | 33 -------- .../73-git-branch-pruner.ts | 22 ----- .../74-prettier-eslint-compat.ts | 45 ----------- .../75-workflow-validator.ts | 36 --------- .../76-commit-msg-rewriter.ts | 21 ----- .../77-env-key-checker.ts | 28 ------- .../78-build-log-analyzer.ts | 20 ----- .../79-ts-type-alias-mapper.ts | 27 ------- .../80-git-contributor-mapper.ts | 14 ---- .../81-markdown-doc-summarizer.ts | 23 ------ .../82-workspace-config-drift.ts | 29 ------- .../83-commit-format-suggester.ts | 17 ---- .../84-json-schema-migration.ts | 31 ------- .../85-dockerfile-security-audit.ts | 41 ---------- .../86-npm-audit-simplifier.ts | 16 ---- .../87-git-stash-inventory.ts | 15 ---- .../88-git-contributor-mapper.ts | 14 ---- .../89-markdown-doc-summarizer.ts | 23 ------ .../90-workspace-config-drift.ts | 29 ------- .../91-commit-format-suggester.ts | 17 ---- .../92-runtime-env-checker.ts | 32 -------- .../93-hotspot-file-analyzer.ts | 16 ---- .../94-ts-interface-conflict-checker.ts | 45 ----------- .../95-git-worktree-mapper.ts | 44 ---------- .../96-test-naming-enforcer.ts | 18 ----- .../97-pkg-dependency-graph.ts | 36 --------- .../98-async-tool-node-builtins.ts | 35 -------- .../99-bash-each.ts | 25 ------ .../tsconfig.json | 6 -- 332 files changed, 10838 deletions(-) delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts delete mode 100644 scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts deleted file mode 100644 index bff8b9b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/02-review-git-diff.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { p } from "rig"; - -// Agent role: review the repository diff and return a structured summary. - -export default p`Review ${p.bash("git diff --stat")} and ${p.bash("git status --short")} and return a concise summary with key findings.`; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts deleted file mode 100644 index fe7d6b6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/03-diagnose-test-failure.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: review input.diff for correctness and regression risks. Return only the declared output shape. -const reviewer = agent({ - model: "typecheck", - output: s.object({ - summary: s.string, - risk: s.enum("low", "medium", "high"), - findings: s.array(s.object({ - severity: s.enum("info", "warning", "error"), - message: s.string, - file: s.optional(s.string), - line: s.optional(s.number) - })), - tests: s.array(s.string) - }), - instructions: ` - Review input.diff for correctness and regression risks. - Return only the declared output shape. - `, -}); -export default reviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts deleted file mode 100644 index e1284ef..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/04-generate-readme.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: diagnose the failing test result. Do not edit files. -const diagnose = agent({ - model: "typecheck", - output: s.object({ - rootCause: s.string, - confidence: s.number, - relevantFiles: s.array(s.string), - nextSteps: s.array(s.string) - }), - instructions: ` - Diagnose the failing test result. - Do not edit files. - `, -}); -export default diagnose; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts deleted file mode 100644 index 991121b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/05-write-readme-intent.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: generate a concise README for the package. Include install, usage, and API sections. -const readmeWriter = agent({ - model: "typecheck", - output: s.object({ - path: s.enum("README.md"), - contents: s.string - }), - instructions: ` - Generate a concise README for the package. - Include install, usage, and API sections. - `, -}); -export default readmeWriter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts deleted file mode 100644 index 3c92bec..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/06-list-source-files.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: list TypeScript source files and return a categorized summary. -const listSourceFiles = agent({ - model: "typecheck", - instructions: p`List and categorize the TypeScript files in this workspace. - -Files: ${p.glob("src/**/*.ts")}`, - output: s.object({ - files: s.array(s.path), - summary: s.string, - }), -}); - -export default listSourceFiles; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts deleted file mode 100644 index 313f6a3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/07-summarize-many-files.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: summarize the repository file list in one sentence. -const summarizeFiles = agent({ - model: "typecheck", - instructions: "Summarize the repository file list in one sentence.", - output: s.object({ - summary: s.string, - }), -}); -export default summarizeFiles; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts deleted file mode 100644 index 77143b9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/08-extract-package-scripts.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: extract package scripts and summarize what they do. -const extractScripts = agent({ - model: "typecheck", - instructions: p`Read ${p.read("package.json")} and summarize the package scripts. Use ${p.bash("find src -name '*.ts' -type f | sort")} only to call out source files that look relevant.`, - output: s.object({ scriptsByName: s.record(s.string), summary: s.string, relatedFiles: s.array(s.string) }), -}); -export default extractScripts; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts deleted file mode 100644 index 4be51bb..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/09-classify-issue.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; - -// Agent role: classify the issue. - -const classifyIssue = agent({ - model: "typecheck", - instructions: "Classify the issue.", - output: s.object({ - label: s.enum("bug", "feature", "question", "docs"), - confidence: s.enum("low", "medium", "high"), - }), -}); - -export default classifyIssue; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts deleted file mode 100644 index 178dd68..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/10-triage-pr.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: classify the GitHub issue and suggest labels. -const classifyIssue = agent({ - model: "typecheck", - output: s.object({ - kind: s.enum("bug", "feature", "question", "chore"), - priority: s.enum("p0", "p1", "p2", "p3"), - rationale: s.string, - labels: s.array(s.string) - }), - instructions: `Classify the GitHub issue and suggest labels.`, -}); - -export default classifyIssue; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts deleted file mode 100644 index 2cdbcbe..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/100-workspace-config-drift-2.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseJson = defineTool("parseJson", { - description: "Parse a JSON string and return parsed object or error", - parameters: s.object({ content: s.string, filename: s.string }), - handler({ content, filename }) { - try { - return { ok: true, parsed: JSON.parse(content), filename }; - } catch (e) { - return { ok: false, error: String(e), filename }; - } - }, -}); - -// Agent role: detect configuration drift across workspace config files. -const workspaceConfigDrift = agent({ - model: "typecheck", - instructions: p`Read and analyze these config files: tsconfig.json ${p.readOptional("tsconfig.json", "{}")}, .eslintrc.json ${p.readOptional(".eslintrc.json", "{}")}, .prettierrc ${p.readOptional(".prettierrc", "{}")}. Use the parseJson tool to validate each. For each config file, identify fields that deviate from sensible defaults (e.g. missing strict mode in tsconfig, missing semi in prettier). Return a record keyed by filename with driftedFields and status.`, - output: s.record(s.object({ - driftedFields: s.array(s.string), - status: s.enum("ok", "warning", "error"), - })), - tools: [parseJson], - maxTurns: 4, - addons: repair(), -}); - -export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts deleted file mode 100644 index 6ce037e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/101-commit-format-suggester-2.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair, steering } from "rig"; - -// Agent role: suggest conventional commit format for recent git commit messages. -const commitFormatSuggester = agent({ - model: "typecheck", - instructions: p`Review the last 10 git commits: ${p.bash("git log --oneline -10")}. For each commit, determine its conventional category (feat/fix/chore/docs/test/refactor/style), then propose an improved commit message following the conventional commits spec. Return an array with one entry per commit.`, - output: s.array(s.object({ - hash: s.string, - original: s.string, - suggested: s.string, - category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), - })), - maxTurns: 4, - addons: [steering({ message: "Every commit must have a suggested message in conventional format." }), repair()], -}); - -export default commitFormatSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts deleted file mode 100644 index fe4bb0d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/102-runtime-env-checker-2.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const checkThresholds = defineTool("checkThresholds", { - description: "Validate Node.js version and heap against minimum thresholds", - parameters: s.object({ nodeVersion: s.string, heapMB: s.number }), - handler({ nodeVersion, heapMB }) { - const issues: string[] = []; - const major = parseInt(nodeVersion.replace("v", "").split(".")[0], 10); - if (major < 18) issues.push(`Node.js ${nodeVersion} is below v18 minimum`); - if (heapMB < 256) issues.push(`Heap ${heapMB}MB is below 256MB minimum`); - return { issues }; - }, -}); - -// Agent role: inspect the runtime environment and report overall health. -const runtimeEnvChecker = agent({ - model: "typecheck", - instructions: p`Inspect the runtime environment: Node version ${p.bash("node --version")}, OS info ${p.bash("uname -a")}, and heap memory ${p.bash("node -p \"Math.round(process.memoryUsage().heapTotal/1024/1024)\"")}MB. Use the checkThresholds tool to validate. Report health as ok, degraded, or critical.`, - output: s.object({ - health: s.enum("ok", "degraded", "critical"), - nodeVersion: s.string, - platform: s.string, - heapMB: s.number, - issues: s.array(s.string), - }), - tools: [checkThresholds], -}); - -export default runtimeEnvChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts deleted file mode 100644 index 027a5ed..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/103-hotspot-file-analyzer-2.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: identify hot-spot files by measuring commit churn and contributor spread. -const hotspotFileAnalyzer = agent({ - model: "typecheck", - instructions: p`Find hot-spot files using commit history: ${p.bash("git log --name-only --format='' HEAD~100..HEAD | grep -v '^$' | sort | uniq -c | sort -rn | head -20")}. For each of the top 10 files, get top contributors via ${p.bash("git shortlog -sn --no-merges HEAD~100..HEAD | head -10")}. Compute a churnScore (0-100) based on commit frequency and list topContributors per file.`, - output: s.record(s.object({ - churnScore: s.number, - topContributors: s.array(s.string), - })), - maxTurns: 5, - addons: steering({ message: "Every file entry must have a numeric churnScore 0-100 and at least one topContributor." }), -}); - -export default hotspotFileAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts deleted file mode 100644 index b47d328..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/104-loc-statistics.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const aggregateByExtension = defineTool("aggregateByExtension", { - description: "Parse wc -l output lines and aggregate total line count and file count by extension", - parameters: s.object({ wcOutput: s.string }), - handler({ wcOutput }) { - const totals: Record = {}; - for (const line of wcOutput.split("\n")) { - const match = line.trim().match(/^(\d+)\s+(.+)$/); - if (!match) continue; - const count = parseInt(match[1], 10); - const path = match[2]; - if (path === "total") continue; - const ext = path.includes(".") ? "." + path.split(".").pop() : "(no ext)"; - if (!totals[ext]) totals[ext] = { lineCount: 0, fileCount: 0 }; - totals[ext].lineCount += count; - totals[ext].fileCount += 1; - } - return totals; - }, -}); - -// Agent role: gather lines-of-code statistics per file extension and classify complexity. -const locStatistics = agent({ - model: "typecheck", - instructions: p`Gather LOC statistics. First list files: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f \\( -name '*.ts' -o -name '*.js' -o -name '*.md' -o -name '*.json' \\) | head -200")}. Then count lines: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f \\( -name '*.ts' -o -name '*.js' -o -name '*.md' -o -name '*.json' \\) -exec wc -l {} + 2>/dev/null | tail -20")}. Use the aggregateByExtension tool to sum lines and files per extension. Classify each extension as small (<500 lines), medium (<2000), large (<10000), or xlarge (≥10000).`, - output: s.record(s.object({ - lineCount: s.number, - fileCount: s.number, - complexity: s.enum("small", "medium", "large", "xlarge"), - })), - tools: [aggregateByExtension], -}); - -export default locStatistics; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts deleted file mode 100644 index a9d2a28..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/105-import-cycle-detector-2.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: detect circular import cycles in TypeScript source files. -const importCycleDetector = agent({ - model: "typecheck", - instructions: p`Detect circular imports in TypeScript files. Check using: ${p.bash("npx --yes madge --circular --extensions ts . 2>&1 || echo 'madge-unavailable'")}. If madge is unavailable, fall back to analyzing imports manually: ${p.bash("grep -rn \"^import\" --include='*.ts' . | grep -v node_modules | head -50")}. For each detected cycle, list the file path chain and assign severity: high (3+ files), medium (2 files shared between critical paths), low (leaf-only cycles).`, - output: s.object({ - hasCycles: s.boolean, - cycles: s.array(s.object({ - path: s.array(s.string), - severity: s.enum("high", "medium", "low"), - })), - }), - maxTurns: 5, - addons: repair(), -}); - -export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts deleted file mode 100644 index 0c92ce1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/106-ts-export-usage.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const scanUsage = defineTool("scanUsage", { - description: "Count how many times a symbol name appears across TypeScript files (approximate usage)", - parameters: s.object({ symbol: s.string }), - async handler({ symbol }) { - const { execSync } = await import("node:child_process"); - try { - const result = execSync( - `grep -rn --include="*.ts" "\\b${symbol}\\b" . | grep -v "^.*export " | grep -v node_modules | wc -l`, - { encoding: "utf8" } - ).trim(); - return { count: parseInt(result, 10) || 0 }; - } catch { - return { count: 0 }; - } - }, -}); - -// Agent role: count usage of exported TypeScript symbols and classify coverage level. -const tsExportUsage = agent({ - model: "typecheck", - instructions: p`Find all exported symbols in TypeScript files: ${p.bash("grep -rn --include='*.ts' 'export (function|class|const|type|interface)' . | grep -v node_modules | head -40")}. For each symbol name, use the scanUsage tool to count references. Classify coverageLevel as none (0 usages), low (1-2), medium (3-9), high (≥10). Record the file where the symbol was last found as lastFile if available.`, - output: s.record(s.object({ - usageCount: s.number, - coverageLevel: s.enum("none", "low", "medium", "high"), - lastFile: s.optional(s.string), - })), - tools: [scanUsage], -}); - -export default tsExportUsage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts deleted file mode 100644 index a629cc7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/107-git-rename-tracker.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: track file renames in git history and produce a structured rename log. -const gitRenameTracker = agent({ - model: "typecheck", - instructions: p`Retrieve git file rename history: ${p.bash("git log --diff-filter=R --summary --pretty=format:'%h %ai' | head -60 2>/dev/null || echo 'No renames found'")}. Parse each rename entry (lines containing "rename from/to") and associate it with the commit hash and date from the preceding format line. Return an array of rename events sorted newest first.`, - output: s.array(s.object({ - hash: s.string, - date: s.string, - oldPath: s.string, - newPath: s.string, - })), - maxTurns: 4, - addons: repair(), -}); - -export default gitRenameTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts deleted file mode 100644 index daf30e4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/108-yaml-lint-checker.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const validateYaml = defineTool("validateYaml", { - description: "Structurally validate a YAML file's content for common issues and required top-level keys", - parameters: s.object({ filename: s.string, content: s.string }), - handler({ filename, content }) { - const issues: string[] = []; - const lines = content.split("\n"); - const lineCount = lines.length; - const isWorkflow = filename.includes(".github/workflows"); - if (isWorkflow) { - if (!content.includes("name:")) issues.push("Missing 'name' key"); - if (!content.includes("on:") && !content.includes("\"on\":")) issues.push("Missing 'on' trigger"); - if (!content.includes("jobs:")) issues.push("Missing 'jobs' key"); - } - if (content.includes("\t")) issues.push("Contains tab characters (use spaces in YAML)"); - const trailingWhitespace = lines.filter((l: string) => l !== l.trimEnd()).length; - if (trailingWhitespace > 0) issues.push(`${trailingWhitespace} lines with trailing whitespace`); - const status = issues.length === 0 ? "pass" : issues.some((i: string) => i.startsWith("Missing")) ? "fail" : "warn"; - return { issues, lineCount, status }; - }, -}); - -// Agent role: lint YAML files in the repository and report structural issues. -const yamlLintChecker = agent({ - model: "typecheck", - instructions: p`Find YAML files in this repository: ${p.bash("find . -name '*.yml' -o -name '*.yaml' | grep -v node_modules | grep -v .git | head -20")}. For each file, read its content and use the validateYaml tool to check for structural issues. Compile results keyed by relative file path.`, - output: s.record(s.object({ - issues: s.array(s.string), - lineCount: s.number, - status: s.enum("pass", "warn", "fail"), - })), - tools: [validateYaml], -}); - -export default yamlLintChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts deleted file mode 100644 index 9b341b2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/109-two-phase-complexity-review.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: extract TypeScript function names and line counts from source files. -const extractor = agent({ - name: "extractor", - model: "typecheck", - instructions: p`Scan TypeScript source files: ${p.bash("grep -rn --include='*.ts' 'function \\|=>.*(\\|async ' . | grep -v node_modules | grep -v '.test.' | head -60")}. For each function found, estimate its line count by looking at surrounding context. Return a JSON object mapping function names to their approximate line counts.`, - output: s.record(s.number), -}); - -// Agent role: classify function complexity based on line counts and produce a summary report. -const complexityReviewer = agent({ - name: "complexityReviewer", - model: "typecheck", - instructions: p`Delegate to extractor to obtain a JSON record of function names to line counts. Classify each function as: simple (<10 lines), moderate (10-29), complex (30-59), or critical (≥60). Count the total number of complex+critical functions for the summary.`, - output: s.object({ - functions: s.record(s.object({ - lineCount: s.number, - complexity: s.enum("simple", "moderate", "complex", "critical"), - })), - summary: s.object({ - totalFunctions: s.number, - complexCount: s.number, - }), - }), - agents: { extractor }, -}); - -export default complexityReviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts deleted file mode 100644 index a44ca23..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/11-release-notes.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: triage the pull request and recommend reviewers. -const triage = agent({ - model: "typecheck", - output: s.object({ - area: s.enum("runtime", "docs", "tests", "ci", "unknown"), - risk: s.enum("low", "medium", "high"), - reviewers: s.array(s.string), - reason: s.string - }), - instructions: `Triage the pull request and recommend reviewers.`, -}); -export default triage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts deleted file mode 100644 index abf3e4e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/110-workspace-config-drift-3.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -// Agent role: detect drift in workspace config files against a baseline. -const workspaceConfigDrift = agent({ - model: "typecheck", - maxTurns: 6, - addons: repair(), - input: s.object({ - baselineFile: s.path, - }), - instructions: p`Read the baseline config from ${p.readInput("baselineFile")}. -Compare it against the current workspace configs: -- tsconfig.json: ${p.readOptional("tsconfig.json", "{}")} -- .eslintrc.json: ${p.readOptional(".eslintrc.json", "{}")} -- .prettierrc: ${p.readOptional(".prettierrc", "{}")} - -Use the parseJson tool to parse each config. For each file, identify fields that differ from -the baseline. Return only the declared output.`, - tools: [ - defineTool("parseJson", { - description: "Parse a JSON string and return the keys", - parameters: s.object({ content: s.string }), - handler({ content }) { - try { - return Object.keys(JSON.parse(content)); - } catch { - return []; - } - }, - }), - ], - output: s.object({ - results: s.record( - s.object({ - driftedFields: s.array(s.string), - status: s.enum("ok", "warning", "error"), - }) - ), - overallStatus: s.enum("ok", "warning", "error"), - }), -}); - -export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts deleted file mode 100644 index 951e78f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/111-conventional-commit-suggester.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, p, s, repair, steering } from "rig"; - -// Agent role: suggest conventional-format rewrites for recent git commit messages. -const conventionalCommitSuggester = agent({ - model: "typecheck", - maxTurns: 6, - addons: [steering({ message: "Ensure each suggestion follows the conventional commits spec: (?): using imperative mood." }), repair()], - instructions: p`Review the recent git log and suggest conventional commit message rewrites: -${p.bash("git log --oneline -20")} - -For each commit, identify the best category (feat/fix/chore/docs/test/refactor/style) and -rewrite the message to follow the conventional commits spec in imperative mood. -Write the full report to output. Return only the declared output.`, - output: s.object({ - suggestions: s.array( - s.object({ - hash: s.string, - original: s.string, - suggested: s.string, - category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), - }) - ), - totalReviewed: s.int, - }), -}); - -export default conventionalCommitSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts deleted file mode 100644 index 0e3a448..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/112-runtime-env-health.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: inspect the runtime environment and report health status. -const runtimeEnvHealth = agent({ - model: "typecheck", - instructions: p`Inspect the runtime environment using the collected info: -Node.js version: ${p.bash("node --version")} -OS info: ${p.bash("uname -a")} -Memory: ${p.bash("free -m 2>/dev/null || vm_stat 2>/dev/null || echo 'unknown'")} - -Use the checkThreshold tool to validate Node.js version (minimum v18) and available memory -(minimum 256 MB). Return only the declared output.`, - tools: [ - defineTool("checkThreshold", { - description: "Check if a numeric value meets a minimum threshold", - parameters: s.object({ - value: s.number, - minimum: s.number, - label: s.string, - }), - handler({ value, minimum, label }) { - return { label, ok: value >= minimum, value, minimum }; - }, - }), - ], - output: s.object({ - nodeVersion: s.string, - os: s.string, - memoryMb: s.number, - health: s.enum("ok", "degraded", "critical"), - issues: s.array(s.string), - }), -}); - -export default runtimeEnvHealth; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts deleted file mode 100644 index 1988c19..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/113-git-hotspot-analyzer.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: identify hot-spot files by git churn and top contributors. -const gitHotspotAnalyzer = agent({ - model: "typecheck", - addons: steering({ message: "Focus only on the top 10 files by change frequency. Skip binary files and node_modules." }), - instructions: p`Analyze git history to find the most frequently changed files. - -Changed files from git log: -${p.bash("git log --follow --name-only --format='' -- . | sort | uniq -c | sort -rn | head -20")} - -For the top files identified, get contributor info: -${p.bash("git shortlog -sn --all -- . 2>/dev/null | head -10")} - -Select the top 10 files by churn score. For each file compute a churnScore -(number of commits) and list topContributors. Return only the declared output as a record -keyed by file path.`, - output: s.record( - s.object({ - churnScore: s.number, - topContributors: s.array(s.string), - }) - ), -}); - -export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts deleted file mode 100644 index 5596850..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/114-loc-statistics-gatherer.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: gather lines-of-code statistics per file extension. -const locStatisticsGatherer = agent({ - model: "typecheck", - instructions: p`Count lines of code by file extension in this workspace. - -Source files found: -${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' \\( -name '*.ts' -o -name '*.js' -o -name '*.py' -o -name '*.go' -o -name '*.rs' \\) 2>/dev/null | head -200")} - -Line counts: -${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' \\( -name '*.ts' -o -name '*.js' -o -name '*.py' \\) -exec wc -l {} + 2>/dev/null | tail -5")} - -Use the classifyComplexity tool to determine overall complexity. Aggregate results by extension. -Return only the declared output.`, - tools: [ - defineTool("classifyComplexity", { - description: "Classify total line count into complexity bucket", - parameters: s.object({ totalLines: s.int }), - handler({ totalLines }) { - if (totalLines < 1000) return "small"; - if (totalLines < 10000) return "medium"; - if (totalLines < 100000) return "large"; - return "xlarge"; - }, - }), - ], - output: s.object({ - byExtension: s.record(s.object({ lineCount: s.int, fileCount: s.int })), - totalLines: s.int, - complexity: s.enum("small", "medium", "large", "xlarge"), - }), -}); - -export default locStatisticsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts deleted file mode 100644 index 622abcd..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/115-import-cycle-detector.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: detect circular import cycles in the TypeScript project. -const importCycleDetector = agent({ - model: "typecheck", - maxTurns: 6, - addons: repair(), - instructions: p`Detect circular imports in this TypeScript project. - -TypeScript config: -${p.bash("cat tsconfig.json 2>/dev/null || echo '{}'")} - -Circular imports (via madge): -${p.bash("npx --yes madge --circular --extensions ts . 2>/dev/null || echo 'madge not available or no cycles found'")} - -Alternatively, check for potential cycles by scanning imports: -${p.bash("grep -r --include='*.ts' 'from.*\\.' . 2>/dev/null | grep -v node_modules | head -50")} - -Identify any circular import chains. For each cycle, classify severity: -- high: cycles in core/shared modules -- medium: cycles in feature modules -- low: cycles in utility or test files - -Return only the declared output.`, - output: s.object({ - hasCycles: s.boolean, - cycles: s.array( - s.object({ - path: s.array(s.string), - severity: s.enum("high", "medium", "low"), - }) - ), - cycleCount: s.int, - }), -}); - -export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts deleted file mode 100644 index 19ba718..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/116-barrel-file-generator.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: generate barrel index.ts files for TypeScript source directories. -const barrelFileGenerator = agent({ - model: "typecheck", - input: s.object({ - srcDir: s.path, - }), - instructions: p`Generate barrel index.ts files for TypeScript source directories. - -Source files found (excluding index.ts): -${p.bash("find . -name '*.ts' ! -name 'index.ts' ! -name '*.test.ts' ! -name '*.spec.ts' -not -path '*/node_modules/*' 2>/dev/null | head -100")} - -Use the classifyExports tool to identify exported symbols in files. Then generate barrel -content for each directory that has exported symbols. Write each barrel file using p.write. - -Count the total number of files scanned, barrel files that would be written, export count, -and directories involved. Return only the declared output.`, - tools: [ - defineTool("classifyExports", { - description: "Scan a TypeScript file path and detect export patterns", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { execSync } = await import("node:child_process"); - try { - const out = execSync(`grep -n "^export " "${filePath}" 2>/dev/null || true`, { encoding: "utf-8" }); - return { filePath, exportLines: out.trim().split("\n").filter(Boolean).length }; - } catch { - return { filePath, exportLines: 0 }; - } - }, - }), - ], - output: s.object({ - filesScanned: s.int, - barrelFilesWritten: s.int, - exportCount: s.int, - directories: s.array(s.string), - }), -}); - -export default barrelFileGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts deleted file mode 100644 index e43e1a7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/117-git-hook-inventory.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: inventory git hooks and classify each as active, stub, or missing. -const gitHookInventory = agent({ - model: "typecheck", - instructions: p`Inventory the git hooks in this repository. - -Available hooks in .git/hooks: -${p.bash("ls .git/hooks/ 2>/dev/null || echo 'no hooks directory'")} - -Sample hooks content: -${p.bash("for f in .git/hooks/pre-commit .git/hooks/commit-msg .git/hooks/pre-push; do echo \"=== $f ===\"; cat \"$f\" 2>/dev/null || echo 'missing'; done")} - -Use the classifyHook tool to classify each hook. Return a record keyed by hook name -with status, summary, and whether it runs asynchronously (uses & or async patterns). -Return only the declared output.`, - tools: [ - defineTool("classifyHook", { - description: "Classify a git hook by its content", - parameters: s.object({ name: s.string, content: s.string }), - handler({ content }) { - if (!content || content === "missing") return { status: "missing", isAsync: false }; - const isSample = content.includes("sample") || content.trim() === "#!/bin/sh"; - const isAsync = content.includes(" &") || content.includes("async"); - return { status: isSample ? "stub" : "active", isAsync }; - }, - }), - ], - output: s.record( - s.object({ - summary: s.string, - status: s.enum("active", "stub", "missing"), - isAsync: s.boolean, - }) - ), -}); - -export default gitHookInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts deleted file mode 100644 index 5c58d40..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/118-pr-review-checklist.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: generate a PR review checklist from the recent git diff. -const prReviewChecklist = agent({ - model: "typecheck", - maxTurns: 6, - addons: repair(), - instructions: p`Generate a PR review checklist based on the changes in this branch. - -Changed files: -${p.bash("git diff --name-only HEAD~1 2>/dev/null || git diff --name-only HEAD 2>/dev/null || echo 'no diff available'")} - -Diff summary: -${p.bash("git diff --stat HEAD~1 2>/dev/null || git diff --stat HEAD 2>/dev/null || echo 'no diff stats'")} - -Key changes: -${p.bash("git diff HEAD~1 -- . 2>/dev/null | head -200 || echo 'no diff content'")} - -For each concern in the changes, produce a checklist item with: -- A clear action item description -- Category (test/docs/security/performance/style) -- Priority (high/medium/low) - -Also list the changed files and indicate if the PR is ready for review. -Return only the declared output.`, - output: s.object({ - checklist: s.array( - s.object({ - item: s.string, - category: s.enum("test", "docs", "security", "performance", "style"), - priority: s.enum("high", "medium", "low"), - }) - ), - changedFiles: s.array(s.string), - ready: s.boolean, - }), -}); - -export default prReviewChecklist; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts deleted file mode 100644 index 6143673..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/119-source-map-analyzer.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: analyze JavaScript source map files and classify their mapping density. -const sourceMapAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze JavaScript source map files in this workspace. - -Source map files found: -${p.bash("find . -name '*.js.map' -not -path '*/node_modules/*' 2>/dev/null | head -50")} - -Use the parseSourceMap tool to read and analyze each source map file. -For each file, determine sourceCount, mapping density, and whether sourcesContent is present. -Return a record keyed by source map file path. Return only the declared output.`, - tools: [ - defineTool("parseSourceMap", { - description: "Parse a source map file and extract metadata", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf-8"); - const map = JSON.parse(content); - const sourceCount: number = Array.isArray(map.sources) ? map.sources.length : 0; - const mappingLen: number = typeof map.mappings === "string" ? map.mappings.length : 0; - const density = mappingLen < 100 ? "sparse" : mappingLen < 1000 ? "medium" : "dense"; - const hasSourcesContent = Array.isArray(map.sourcesContent) && map.sourcesContent.length > 0; - return { sourceCount, density, hasSourcesContent }; - } catch { - return { sourceCount: 0, density: "sparse", hasSourcesContent: false }; - } - }, - }), - ], - output: s.record( - s.object({ - sourceCount: s.int, - mappingDensity: s.enum("sparse", "medium", "dense"), - hasSourcesContent: s.boolean, - }) - ), -}); - -export default sourceMapAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts deleted file mode 100644 index 0dabc83..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/12-security-scan-review.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: write release notes from commits. Omit empty sections as empty arrays. -const releaseNotes = agent({ - model: "typecheck", - output: s.object({ - version: s.optional(s.string), - highlights: s.array(s.string), - breaking: s.array(s.string), - fixes: s.array(s.string) - }), - instructions: `Write release notes from commits. Omit empty sections as empty arrays.`, -}); -export default releaseNotes; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts deleted file mode 100644 index 71979e7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/120-git-hotspot-v2.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const getFileCommitCount = defineTool("getFileCommitCount", { - description: "Count how many commits touched a specific file", - parameters: s.object({ file: s.string }), - handler: async ({ file }) => { - const { execSync } = await import("node:child_process"); - try { - const result = execSync(`git log --follow --oneline -- "${file}" 2>/dev/null | wc -l`, { encoding: "utf8" }); - return result.trim(); - } catch { - return "0"; - } - }, -}); - -// Agent role: analyze git history to identify hot-spot files by commit frequency and contributor count -const gitHotspotAnalyzer = agent({ - name: "gitHotspotAnalyzer", - model: "typecheck", - maxTurns: 3, - addons: repair(), - instructions: p`Analyze the git history to identify file hot-spots. - -Changed files: ${p.bash("git log --follow --name-only --format='' -- . 2>/dev/null | sort | uniq -c | sort -rn | head -30")} - -Contributors: ${p.bash("git shortlog -sn --no-merges 2>/dev/null | head -10")} - -Use the getFileCommitCount tool to look up commit counts for the top files. -For each file, determine its hotspot level based on commit count: -- critical: 50+ commits -- high: 20–49 commits -- medium: 5–19 commits -- low: fewer than 5 commits - -Return a record keyed by file path with commitCount, topContributors array, and hotspotLevel.`, - output: s.record( - s.object({ - commitCount: s.int, - topContributors: s.array(s.string), - hotspotLevel: s.enum("low", "medium", "high", "critical"), - }) - ), - tools: [getFileCommitCount], -}); - -export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts deleted file mode 100644 index 3e557c7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/121-loc-stats-gatherer.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const countLinesByExtension = defineTool("countLinesByExtension", { - description: "Count total lines for files with a given extension", - parameters: s.object({ extension: s.string }), - handler: async ({ extension }) => { - const { execSync } = await import("node:child_process"); - try { - const result = execSync( - `find . -type f -name "*.${extension}" -not -path "*/node_modules/*" | xargs wc -l 2>/dev/null | tail -1`, - { encoding: "utf8" } - ); - return result.trim(); - } catch { - return "0"; - } - }, -}); - -// Agent role: gather lines-of-code statistics per file extension and rate the overall complexity -const locStatsGatherer = agent({ - name: "locStatsGatherer", - model: "typecheck", - instructions: p`Gather lines-of-code statistics for this workspace. - -File extension counts: ${p.bash("find . -type f -not -path '*/node_modules/*' -not -path '*/.git/*' | sed 's/.*\\.//' | sort | uniq -c | sort -rn | head -20")} - -TypeScript files: ${p.bash("find . -type f -name '*.ts' -not -path '*/node_modules/*' | head -100")} - -Total line count: ${p.bash("find . -type f -name '*.ts' -not -path '*/node_modules/*' | xargs wc -l 2>/dev/null | tail -1")} - -Use the countLinesByExtension tool to get line counts for the top extensions. -Compute byExtension record with fileCount and lineCount per extension. -Set complexityRating based on totalLines: small (<1000), medium (1000–10000), large (10000–100000), xlarge (100000+).`, - output: s.object({ - byExtension: s.record(s.object({ fileCount: s.int, lineCount: s.int })), - totalLines: s.int, - largestExtension: s.string, - complexityRating: s.enum("small", "medium", "large", "xlarge"), - }), - tools: [countLinesByExtension], -}); - -export default locStatsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts deleted file mode 100644 index d8fc697..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/122-import-cycle-detector.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: detect import cycles in a TypeScript project and assess their severity -const importCycleDetector = agent({ - name: "importCycleDetector", - model: "typecheck", - maxTurns: 3, - addons: repair(), - instructions: p`Detect circular imports in this TypeScript project. - -Madge circular analysis: ${p.bash("npx madge --circular --extensions ts . 2>/dev/null || echo 'madge not available, use heuristic analysis'")} - -TypeScript config: ${p.readOptional("tsconfig.json", "{}")} - -Source files: ${p.bash("find . -type f -name '*.ts' -not -path '*/node_modules/*' | head -30")} - -Identify any circular import cycles. For each cycle, list the file path array forming the cycle and rate severity: -- high: cycles involving core modules or many files -- medium: cycles involving 3–5 files -- low: simple two-file cycles - -Set hasCycles to true if any cycles exist. Provide a recommendation for resolving them.`, - output: s.object({ - hasCycles: s.boolean, - cycles: s.array( - s.object({ - path: s.array(s.string), - severity: s.enum("high", "medium", "low"), - }) - ), - cycleCount: s.int, - recommendation: s.string, - }), -}); - -export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts deleted file mode 100644 index d41c11b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/123-coverage-badge-updater.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: read coverage data and generate shields.io badge markdown, writing it to a file -const coverageBadgeUpdater = agent({ - name: "coverageBadgeUpdater", - model: "typecheck", - instructions: p`Read coverage data and generate badge markdown for README. - -Coverage summary: ${p.readOptional("coverage/coverage-summary.json", "{}")} - -Current README: ${p.read("README.md")} - -Parse the coverage summary JSON. Extract per-category percentages (lines, statements, functions, branches). -Compute the overall percentage as the average. -Set rating: green (>=80%), yellow (60–79%), red (<60%). -Generate shields.io badge markdown for each category and overall. -Set badgesWritten to true. -The badgeMarkdown field will be written to coverage-badge.md. - -${p.writeOutput("badgeMarkdown", "coverage-badge.md")}`, - output: s.object({ - coverageByCategory: s.record(s.number), - overallPct: s.number, - rating: s.enum("green", "yellow", "red"), - badgesWritten: s.boolean, - badgeMarkdown: s.string, - }), -}); - -export default coverageBadgeUpdater; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts deleted file mode 100644 index 5368c2b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/124-dep-license-auditor.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyLicense = defineTool("classifyLicense", { - description: "Classify a license string as permissive, copyleft, or unknown", - parameters: s.object({ license: s.string }), - handler: ({ license }) => { - const l = license.toLowerCase(); - const permissive = ["mit", "apache", "bsd", "isc", "0bsd", "unlicense", "wtfpl", "cc0", "zlib"]; - const copyleft = ["gpl", "lgpl", "agpl", "mpl", "eupl", "cddl"]; - if (permissive.some((p) => l.includes(p))) return "permissive"; - if (copyleft.some((c) => l.includes(c))) return "copyleft"; - return "unknown"; - }, -}); - -// Agent role: audit npm dependency licenses and flag copyleft or unknown licenses -const depLicenseAuditor = agent({ - name: "depLicenseAuditor", - model: "typecheck", - instructions: p`Audit the licenses of npm dependencies in this project. - -Direct dependencies: ${p.bash("npm ls --json --depth=0 2>/dev/null | head -200")} - -License fields: ${p.bash("cat node_modules/*/package.json 2>/dev/null | grep -E '\"license\"' | sort -u | head -50")} - -For each direct dependency, use the classifyLicense tool to classify its license as permissive, copyleft, or unknown. -Assign riskLevel: copyleft=review, unknown=review, permissive=safe; if license is missing set riskLevel=blocked. -Set hasCopyleft to true if any package has classification=copyleft.`, - output: s.object({ - packages: s.array( - s.object({ - name: s.string, - version: s.string, - license: s.string, - classification: s.enum("permissive", "copyleft", "unknown"), - riskLevel: s.enum("safe", "review", "blocked"), - }) - ), - hasCopyleft: s.boolean, - totalPackages: s.int, - }), - tools: [classifyLicense], -}); - -export default depLicenseAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts deleted file mode 100644 index 7128ec6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/125-test-coverage-mapper.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const findTestFile = defineTool("findTestFile", { - description: "Find the best matching test file for a given source file using filename heuristics", - parameters: s.object({ - sourceFile: s.string, - testFiles: s.array(s.string), - }), - handler: ({ sourceFile, testFiles }) => { - const baseName = sourceFile.replace(/\.ts$/, "").replace(/.*\//, ""); - const matches = testFiles.filter( - (t) => - t.includes(baseName + ".test") || - t.includes(baseName + ".spec") || - t.includes(baseName.replace(/([A-Z])/g, "-$1").toLowerCase()) - ); - return JSON.stringify(matches); - }, -}); - -// Agent role: map source files to their test files using filename heuristics -const testCoverageMapper = agent({ - name: "testCoverageMapper", - model: "typecheck", - maxTurns: 2, - addons: repair(), - instructions: p`Map source files to their corresponding test files using filename heuristics. - -Source files: ${p.bash("find . -type f -name '*.ts' -not -name '*.test.ts' -not -name '*.spec.ts' -not -path '*/node_modules/*' | head -50")} - -Test files: ${p.bash("find . -type f \\( -name '*.test.ts' -o -name '*.spec.ts' \\) -not -path '*/node_modules/*' | head -50")} - -For each source file, use the findTestFile tool to look up matching test files. -Set coverage: -- covered: one or more test files found -- partial: test file found but name match is weak -- uncovered: no test files found - -Return a record keyed by source file path.`, - output: s.record( - s.object({ - coverage: s.enum("covered", "uncovered", "partial"), - testFiles: s.array(s.string), - reason: s.string, - }) - ), - tools: [findTestFile], -}); - -export default testCoverageMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts deleted file mode 100644 index a2a9fb2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/126-tsconfig-options-auditor.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { agent, p, s, defineTool, steering, repair } from "rig"; - -const checkOption = defineTool("checkOption", { - description: "Check whether a tsconfig compiler option matches the recommended value", - parameters: s.object({ - option: s.string, - value: s.unknown, - recommended: s.unknown, - }), - handler: ({ value, recommended }) => { - return JSON.stringify(value) === JSON.stringify(recommended) ? "pass" : "fail"; - }, -}); - -// Agent role: audit TypeScript compiler options against best-practice recommendations -const tsconfigOptionsAuditor = agent({ - name: "tsconfigOptionsAuditor", - model: "typecheck", - addons: [steering(), repair()], - instructions: p`Audit TypeScript compiler options in this project against best-practice recommendations. - -tsconfig.json: ${p.readOptional("tsconfig.json", "{}")} - -tsconfig.base.json: ${p.readOptional("tsconfig.base.json", "{}")} - -Check the following recommended settings using the checkOption tool: -- strict: true -- noImplicitAny: true -- strictNullChecks: true -- noUnusedLocals: true -- noUnusedParameters: true -- exactOptionalPropertyTypes: true -- noFallthroughCasesInSwitch: true -- esModuleInterop: true -- skipLibCheck: true -- forceConsistentCasingInFileNames: true - -Determine complianceLevel: strict (9–10 pass), moderate (6–8 pass), loose (3–5 pass), unconfigured (<3 pass). -Return all options checked with status and reason.`, - output: s.object({ - options: s.array( - s.object({ - name: s.string, - currentValue: s.unknown, - recommendedValue: s.unknown, - status: s.enum("pass", "fail", "missing", "warn"), - reason: s.string, - }) - ), - complianceLevel: s.enum("strict", "moderate", "loose", "unconfigured"), - totalChecked: s.int, - passCount: s.int, - }), - tools: [checkOption], -}); - -export default tsconfigOptionsAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts deleted file mode 100644 index ffd9298..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/127-git-commit-annotator.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize a single git commit into a category and impact rating -const commitSummarizer = agent({ - name: "commitSummarizer", - model: "typecheck", - instructions: p`Analyze the git commit message provided in the input and classify it. - -Commit info: ${p.inputField("commitLine")} - -Classify the commit into a category (feat, fix, chore, docs, refactor, test, perf). -Write a concise one-sentence summary. -Rate the impact as low, medium, or high based on likely scope of change.`, - input: s.object({ commitLine: s.string }), - output: s.object({ - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - summary: s.string, - impact: s.enum("low", "medium", "high"), - }), -}); - -// Agent role: annotate recent git commits with category, summary, and impact, writing a markdown report -const gitCommitAnnotator = agent({ - name: "gitCommitAnnotator", - model: "typecheck", - agents: { commitSummarizer }, - instructions: p`Annotate the 20 most recent git commits with category, summary, and impact. - -Recent commits: ${p.bash("git log --oneline -20")} - -For each commit line, delegate to the commitSummarizer subagent. -Collect all annotations and build a markdown report with a table of hash, category, summary, and impact. -Set totalAnnotated to the number of commits annotated. -The report field will be written to commit-annotations.md. - -${p.writeOutput("report", "commit-annotations.md")}`, - output: s.object({ - annotations: s.array( - s.object({ - hash: s.string, - original: s.string, - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - summary: s.string, - impact: s.enum("low", "medium", "high"), - }) - ), - report: s.string, - totalAnnotated: s.int, - }), -}); - -export default gitCommitAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts deleted file mode 100644 index 1102bbf..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/128-npm-script-dep-mapper.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseScriptDeps = defineTool("parseScriptDeps", { - description: "Parse pre/post hooks and npm run references for a script", - parameters: s.object({ - scriptName: s.string, - scriptBody: s.string, - allScripts: s.record(s.string), - }), - handler: ({ scriptName, scriptBody, allScripts }) => { - const deps: string[] = []; - const runRefs = scriptBody.match(/npm run ([\w:-]+)/g) || []; - runRefs.forEach((r) => deps.push(r.replace("npm run ", ""))); - const preName = "pre" + scriptName; - const postName = "post" + scriptName; - if (allScripts[preName]) deps.push(preName); - if (allScripts[postName]) deps.push(postName); - return JSON.stringify(deps); - }, -}); - -// Agent role: map npm script dependencies by analyzing pre/post hooks and npm run references -const npmScriptDepMapper = agent({ - name: "npmScriptDepMapper", - model: "typecheck", - maxTurns: 2, - addons: repair(), - instructions: p`Map npm script dependencies by analyzing the package.json scripts. - -package.json: ${p.read("package.json")} - -For each script, use the parseScriptDeps tool to find its dependencies (npm run references and pre/post hooks). -Classify each script category: -- build: scripts that compile or bundle -- test: scripts that run tests -- lint: scripts that lint or format -- dev: scripts for development -- deploy: scripts for deployment -- util: utility scripts -- hook: pre/post lifecycle hooks -- other: anything else - -Set hasPreHook and hasPostHook based on whether pre or post scripts exist. -Return a record keyed by script name.`, - output: s.record( - s.object({ - command: s.string, - dependsOn: s.array(s.string), - category: s.enum("build", "test", "lint", "dev", "deploy", "util", "hook", "other"), - hasPreHook: s.boolean, - hasPostHook: s.boolean, - }) - ), - tools: [parseScriptDeps], -}); - -export default npmScriptDepMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts deleted file mode 100644 index d8e4dce..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/129-markdown-link-checker.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const checkUrl = defineTool("checkUrl", { - description: "Check HTTP status of a URL using curl", - parameters: s.object({ url: s.string }), - handler: async ({ url }) => { - const { execSync } = await import("node:child_process"); - try { - const code = execSync( - `curl --head --silent --max-time 5 -o /dev/null -w "%{http_code}" "${url}" 2>/dev/null`, - { encoding: "utf8", timeout: 8000 } - ).trim(); - return code; - } catch { - return "timeout"; - } - }, -}); - -// Agent role: check HTTP status of links found in markdown files -const markdownLinkChecker = agent({ - name: "markdownLinkChecker", - model: "typecheck", - addons: repair(), - instructions: p`Find and check HTTP links in markdown files. - -Markdown files: ${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -20")} - -URLs found: ${p.bash("grep -roh 'https\\?://[^)\"\\s]*' . --include='*.md' 2>/dev/null | sort -u | head -50")} - -For each unique URL, use the checkUrl tool to get the HTTP status code. -Classify status: -- ok: 200–299 -- redirect: 301, 302, 307, 308 -- broken: 400–599 -- timeout: curl timed out -- skipped: non-http or malformed URL - -Set allValid to true only if no links are broken. -Include foundInFile for each link if determinable.`, - output: s.object({ - links: s.array( - s.object({ - url: s.url, - status: s.enum("ok", "broken", "redirect", "timeout", "skipped"), - httpCode: s.optional(s.int), - foundInFile: s.optional(s.path), - }) - ), - totalChecked: s.int, - brokenCount: s.int, - allValid: s.boolean, - }), - tools: [checkUrl], -}); - -export default markdownLinkChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts deleted file mode 100644 index 1a80a67..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/13-test-plan.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: review dependency security posture from the provided outputs. -const securityReview = agent({ - model: "typecheck", - output: s.object({ - status: s.enum("clean", "needs-action", "unknown"), - findings: s.array(s.object({ - package: s.string, - severity: s.string, - action: s.string - })) - }), - instructions: `Review dependency security posture from the provided outputs.`, -}); -export default securityReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts deleted file mode 100644 index 41e706e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/130-git-hotspot-analyzer.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: analyze which files are hot-spots by measuring commit churn and top contributors. -const gitHotspotAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze file churn in this repository. List all tracked files: ${p.bash("git ls-files --exclude-standard | head -100")}. Get commit counts per file: ${p.bash("git log --follow --name-only --format='' -- . | sort | uniq -c | sort -rn | head -40")}. Get top contributors per file via: ${p.bash("git shortlog -sn --no-merges HEAD~50..HEAD 2>/dev/null || git shortlog -sn --no-merges | head -20")}. For each hot-spot file compute a churnScore 0–100 (based on commit frequency relative to max) and list topContributors.`, - output: s.record(s.object({ - churnScore: s.number, - topContributors: s.array(s.string), - })), - maxTurns: 5, - addons: [steering({ message: "Every file must have a numeric churnScore between 0 and 100 and at least one topContributor entry." })], -}); - -export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts deleted file mode 100644 index 885bbfb..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/131-loc-statistics-gatherer.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const aggregateByExtension = defineTool("aggregateByExtension", { - description: "Parse wc -l output and aggregate line and file counts by extension", - parameters: s.object({ wcOutput: s.string }), - handler: ({ wcOutput }) => { - const totals: Record = {}; - for (const line of wcOutput.trim().split("\n")) { - const match = line.trim().match(/^(\d+)\s+(.+)$/); - if (!match) continue; - const count = parseInt(match[1], 10); - const filePath = match[2]; - if (filePath === "total") continue; - const ext = filePath.includes(".") ? "." + filePath.split(".").pop()! : "(none)"; - if (!totals[ext]) totals[ext] = { lineCount: 0, fileCount: 0 }; - totals[ext].lineCount += count; - totals[ext].fileCount += 1; - } - return JSON.stringify(totals); - }, -}); - -// Agent role: gather lines-of-code statistics per file extension and classify overall complexity. -const locStatisticsGatherer = agent({ - model: "typecheck", - instructions: p`Gather lines-of-code statistics for this repository. List files: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f | head -200")}. Count lines per file: ${p.bash("find . -not -path '*/node_modules/*' -not -path '*/.git/*' -type f -exec wc -l {} + 2>/dev/null | tail -30")}. Use aggregateByExtension to sum lineCount and fileCount per extension. Compute complexityRating: small (<1000 total lines), medium (<5000), large (<20000), xlarge (>=20000).`, - output: s.object({ - byExtension: s.record(s.object({ - lineCount: s.int, - fileCount: s.int, - })), - complexityRating: s.enum("small", "medium", "large", "xlarge"), - }), - tools: [aggregateByExtension], -}); - -export default locStatisticsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts deleted file mode 100644 index e8e2e91..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/132-import-cycle-detector.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: detect circular import cycles in the TypeScript project and classify severity. -const importCycleDetector = agent({ - model: "typecheck", - maxTurns: 6, - addons: [repair()], - instructions: p`Detect circular imports in this TypeScript project. - -TypeScript config: ${p.bash("cat tsconfig.json 2>/dev/null || echo '{}'")} - -Circular dependency check: ${p.bash("npx --yes madge --circular --extensions ts . 2>/dev/null || echo 'madge unavailable'")} - -Import graph sample: ${p.bash("grep -r --include='*.ts' -h 'from ' . 2>/dev/null | grep -v node_modules | head -60")} - -Identify all circular import chains. For each cycle, list the path as an array of module names and classify severity: high (core/shared modules), medium (feature modules), low (utility/test files). Set hasCycles to true if any cycles were found.`, - output: s.object({ - hasCycles: s.boolean, - cycles: s.array(s.object({ - path: s.array(s.string), - severity: s.enum("high", "medium", "low"), - })), - }), -}); - -export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts deleted file mode 100644 index 587d496..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/133-coverage-badge-updater.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: read coverage summary and generate shields.io badge markdown, writing it to a coverage report file. -const coverageBadgeUpdater = agent({ - model: "typecheck", - instructions: p`Read coverage data and generate shields.io badge markdown. - -Coverage summary: ${p.readOptional("coverage/coverage-summary.json", "{}")} - -Current README: ${p.readOptional("README.md", "")} - -Parse the coverage summary JSON. Extract per-category percentages for statements, branches, functions, and lines. Compute overallPct as the average. Set rating: green (>=80%), yellow (60–79%), red (<60%). Generate shields.io badge markdown for each category and the overall percentage. Write the badge markdown to the output field badgeMarkdown. Set badgesWritten to true after generating. ${p.writeOutput("badgeMarkdown", "coverage-badges.md")}`, - output: s.object({ - coverageByCategory: s.record(s.number), - overallPct: s.number, - rating: s.enum("green", "yellow", "red"), - badgesWritten: s.boolean, - badgeMarkdown: s.string, - }), -}); - -export default coverageBadgeUpdater; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts deleted file mode 100644 index 7f363f9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/134-dep-license-auditor.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyLicense = defineTool("classifyLicense", { - description: "Classify a license identifier as permissive, copyleft, or unknown", - parameters: s.object({ license: s.string }), - handler: ({ license }) => { - const l = license.toLowerCase(); - const permissive = ["mit", "isc", "apache", "bsd", "0bsd", "unlicense", "cc0", "wtfpl", "zlib"]; - const copyleft = ["gpl", "lgpl", "agpl", "mpl", "eupl", "cddl"]; - if (permissive.some((p) => l.includes(p))) return "permissive"; - if (copyleft.some((c) => l.includes(c))) return "copyleft"; - return "unknown"; - }, -}); - -// Agent role: audit npm dependency licenses and flag copyleft or unknown packages. -const depLicenseAuditor = agent({ - model: "typecheck", - instructions: p`Audit the licenses of all direct npm dependencies. - -Direct dependencies: ${p.bash("npm ls --json --depth=0 2>/dev/null | head -300")} - -License fields from node_modules: ${p.bash("node -e \"const fs=require('fs'); const d='./node_modules'; if(fs.existsSync(d)) { fs.readdirSync(d).filter(n=>!n.startsWith('.')).slice(0,60).forEach(n=>{ try{const p=JSON.parse(fs.readFileSync(d+'/'+n+'/package.json','utf8')); console.log(n+'|'+(p.license||'NONE'))}catch(e){} }) }\" 2>/dev/null")} - -For each direct dependency, use classifyLicense to classify its license. Set hasCopyleft to true if any package has classification copyleft.`, - output: s.object({ - packages: s.array(s.object({ - name: s.string, - license: s.string, - classification: s.enum("permissive", "copyleft", "unknown"), - })), - hasCopyleft: s.boolean, - }), - tools: [classifyLicense], -}); - -export default depLicenseAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts deleted file mode 100644 index 87dfe01..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/135-test-coverage-mapper.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const matchTestFile = defineTool("matchTestFile", { - description: "Find matching test files for a source file using filename heuristics", - parameters: s.object({ sourceFile: s.string, testFiles: s.array(s.string) }), - handler: ({ sourceFile, testFiles }) => { - const base = sourceFile.replace(/\.tsx?$/, "").replace(/.*\//, ""); - const matches = testFiles.filter( - (t) => t.includes(base + ".test") || t.includes(base + ".spec") - ); - return JSON.stringify({ matches, partial: matches.length === 0 ? testFiles.filter((t) => t.includes(base)).slice(0, 2) : [] }); - }, -}); - -// Agent role: map each TypeScript source file to its test files using filename heuristics. -const testCoverageMapper = agent({ - model: "typecheck", - maxTurns: 4, - addons: [repair()], - instructions: p`Map source files to their test counterparts. - -Source files: ${p.bash("find . -type f -name '*.ts' -not -name '*.test.ts' -not -name '*.spec.ts' -not -path '*/node_modules/*' | head -50")} - -Test files: ${p.bash("find . -type f \\( -name '*.test.ts' -o -name '*.spec.ts' \\) -not -path '*/node_modules/*' | head -50")} - -For each source file use matchTestFile to find matches. Classify coverage: covered (matches found), partial (weak match), uncovered (none). Return a record keyed by source file path.`, - output: s.record(s.object({ - coverage: s.enum("covered", "uncovered", "partial"), - testFiles: s.array(s.string), - reason: s.string, - })), - tools: [matchTestFile], -}); - -export default testCoverageMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts deleted file mode 100644 index 071d21e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/136-pkg-version-drift.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: compare installed npm package versions against latest published versions and report drift. -const pkgVersionDrift = agent({ - model: "typecheck", - instructions: p`Compare installed npm package versions to the latest published versions. - -Package manifest: ${p.read("package.json")} - -Installed versions: ${p.bash("npm ls --depth=0 --json 2>/dev/null | head -200")} - -Latest versions for key packages: ${p.bash("npm outdated --json 2>/dev/null | head -200 || echo '{}'")} - -For each dependency, classify driftLevel: ok (up to date), patch (patch version behind), minor (minor version behind), major (major version behind). Write a human-readable drift summary report via ${p.writeOutput("report", "version-drift-report.md")}. Set reportWritten to true.`, - output: s.object({ - packages: s.array(s.object({ - name: s.string, - current: s.string, - latest: s.string, - driftLevel: s.enum("ok", "patch", "minor", "major"), - })), - reportWritten: s.boolean, - report: s.string, - }), -}); - -export default pkgVersionDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts deleted file mode 100644 index ac28932..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/137-git-author-stats.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: aggregate commit statistics per git author, including first/last commit dates and total counts. -const gitAuthorStats = agent({ - model: "typecheck", - instructions: p`Aggregate git commit statistics per author. - -Commit counts by author: ${p.bash("git shortlog -sne --all 2>/dev/null | head -40")} - -Commit log with dates: ${p.bash("git log --format='%ae|%ad' --date=short 2>/dev/null | head -200")} - -For each author email, compute commitCount, firstCommit date, and lastCommit date. Identify the topAuthor with the most commits. Compute totalCommits across all authors.`, - output: s.object({ - authors: s.record(s.object({ - commitCount: s.int, - firstCommit: s.string, - lastCommit: s.string, - })), - topAuthor: s.string, - totalCommits: s.int, - }), -}); - -export default gitAuthorStats; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts deleted file mode 100644 index ac1f7bd..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/138-ts-path-alias-validator.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { existsSync } from "node:fs"; - -const checkAlias = defineTool("checkAlias", { - description: "Check whether a TypeScript path alias target directory exists", - parameters: s.object({ alias: s.string, target: s.string }), - handler: ({ alias, target }) => { - const resolved = target.replace(/\/\*$/, ""); - const exists = existsSync(resolved); - return JSON.stringify({ alias, target, exists }); - }, -}); - -// Agent role: validate TypeScript path aliases from tsconfig against actual filesystem paths. -const tsPathAliasValidator = agent({ - model: "typecheck", - instructions: p`Validate TypeScript path alias configuration. - -tsconfig.json: ${p.read("tsconfig.json")} - -Files with aliased imports: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | xargs grep -l 'from [\"\\x27]' 2>/dev/null | head -20")} - -Import alias usage: ${p.bash("grep -r --include='*.ts' -h 'from [\"\\x27]' . 2>/dev/null | grep -v node_modules | grep -v '\\.' | head -40")} - -For each alias in compilerOptions.paths, use checkAlias to verify the target exists. Classify as valid (exists and used), broken (target missing), or unused (exists but no imports found). Report totalAliases and brokenCount.`, - output: s.object({ - aliases: s.record(s.object({ - target: s.string, - status: s.enum("valid", "broken", "unused"), - })), - totalAliases: s.int, - brokenCount: s.int, - }), - tools: [checkAlias], -}); - -export default tsPathAliasValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts deleted file mode 100644 index 44453de..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/139-markdown-frontmatter-checker.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFileSync, existsSync } from "node:fs"; - -const parseFrontmatter = defineTool("parseFrontmatter", { - description: "Parse YAML frontmatter from a markdown file and check for required fields", - parameters: s.object({ filePath: s.string }), - handler: ({ filePath }) => { - if (!existsSync(filePath)) return JSON.stringify({ error: "file not found" }); - const content = readFileSync(filePath, "utf8"); - if (!content.startsWith("---")) return JSON.stringify({ presentFields: [], missingFields: ["title", "description", "date"], status: "missing" }); - const end = content.indexOf("---", 3); - if (end === -1) return JSON.stringify({ presentFields: [], missingFields: ["title", "description", "date"], status: "missing" }); - const fm = content.slice(3, end); - const required = ["title", "description", "date"]; - const present = required.filter((f) => new RegExp(`^${f}\\s*:`, "m").test(fm)); - const missing = required.filter((f) => !present.includes(f)); - const status = missing.length === 0 ? "complete" : present.length === 0 ? "missing" : "partial"; - return JSON.stringify({ presentFields: present, missingFields: missing, status }); - }, -}); - -// Agent role: check markdown files for required YAML frontmatter fields (title, description, date). -const markdownFrontmatterChecker = agent({ - model: "typecheck", - maxTurns: 4, - addons: [repair()], - instructions: p`Check markdown files for required YAML frontmatter fields. - -Markdown files: ${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -50")} - -For each markdown file, use parseFrontmatter to detect which required fields (title, description, date) are present or missing. Return a record keyed by filename.`, - output: s.record(s.object({ - presentFields: s.array(s.string), - missingFields: s.array(s.string), - status: s.enum("complete", "partial", "missing"), - })), - tools: [parseFrontmatter], -}); - -export default markdownFrontmatterChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts deleted file mode 100644 index 7287628..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/14-changelog-categorizer.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: create a focused validation plan for the current changes. -const planner = agent({ - model: "typecheck", - output: s.object({ - commands: s.array(s.string), - manualChecks: s.array(s.string), - rationale: s.string - }), - instructions: `Create a focused validation plan for the current changes.`, -}); -export default planner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts deleted file mode 100644 index 4d547ee..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/140-git-hotspot-analyzer.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const scoreFile = defineTool("scoreFile", { - description: "Compute a churn score from commit count for a file.", - parameters: s.object({ filename: s.string, commitCount: s.int }), - handler({ commitCount }) { - const score = Math.log1p(commitCount) * 10; - return { churnScore: Math.round(score * 100) / 100 }; - }, -}); - -// Agent role: Analyze git history to identify hot-spot files by churn frequency. -const gitHotspotAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze the git log to find frequently-changed files. - -Use the git history: -${p.bash("git log --name-only --format= | sort | uniq -c | sort -rn | head -30")} - -For each file in the top results, get contributor info: -${p.bash("git shortlog -sn --no-merges -- . | head -10")} - -Use the scoreFile tool to compute a churnScore for each file. -Return s.record output keyed by file path with churnScore, commitCount, and topContributors.`, - tools: [scoreFile], - addons: steering({ message: "Ensure all top files appear in the output keyed by their path." }), - output: s.record( - s.object({ - churnScore: s.number, - commitCount: s.int, - topContributors: s.array(s.string), - }), - ), -}); - -export default gitHotspotAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts deleted file mode 100644 index 876e587..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/141-loc-statistics-gatherer.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const aggregateByExtension = defineTool("aggregateByExtension", { - description: "Aggregate line counts and file counts by extension from wc -l output.", - parameters: s.object({ wcOutput: s.string }), - handler({ wcOutput }) { - const lines = wcOutput.trim().split("\n"); - const result: Record = {}; - for (const line of lines) { - const match = line.trim().match(/^(\d+)\s+(.+)$/); - if (!match) continue; - const count = parseInt(match[1], 10); - const file = match[2]; - const ext = file.includes(".") ? "." + file.split(".").pop()! : "(no-ext)"; - if (!result[ext]) result[ext] = { lineCount: 0, fileCount: 0 }; - result[ext].lineCount += count; - result[ext].fileCount += 1; - } - return result; - }, -}); - -// Agent role: Gather lines-of-code statistics grouped by file extension. -const locStatisticsGatherer = agent({ - model: "typecheck", - instructions: p`Count lines of code across the workspace grouped by file extension. - -Find source files and count lines: -${p.bash("find . -maxdepth 4 -type f \\( -name '*.ts' -o -name '*.js' -o -name '*.py' -o -name '*.go' -o -name '*.md' \\) ! -path '*/node_modules/*' ! -path '*/.git/*' | xargs wc -l 2>/dev/null | tail -n +1")} - -Use the aggregateByExtension tool to group by extension. -Classify each extension's complexity based on total lineCount: -- small: < 500, medium: 500-2000, large: 2000-10000, xlarge: > 10000 -Return s.record output keyed by extension with lineCount, fileCount, and complexity.`, - tools: [aggregateByExtension], - output: s.record( - s.object({ - lineCount: s.int, - fileCount: s.int, - complexity: s.enum("small", "medium", "large", "xlarge"), - }), - ), -}); - -export default locStatisticsGatherer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts deleted file mode 100644 index 88be4f8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/142-import-cycle-detector.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: Detect import cycles in TypeScript source using madge and classify severity. -const importCycleDetector = agent({ - model: "typecheck", - maxTurns: 3, - instructions: p`Detect circular import cycles in this TypeScript project. - -Run madge to find circular dependencies: -${p.bash("npx madge --circular --json . 2>/dev/null || echo '[]'")} - -Also read the TypeScript config: -${p.readOptional("tsconfig.json", "{}")} - -For each cycle found, classify severity: -- high: cycle involves more than 3 files or includes entry points -- medium: cycle involves 2-3 files -- low: short cycle between utility files - -Return the structured output with hasCycles, cycles array, and totalCycles count.`, - addons: repair(), - output: s.object({ - hasCycles: s.boolean, - cycles: s.array( - s.object({ - path: s.array(s.string), - severity: s.enum("high", "medium", "low"), - }), - ), - totalCycles: s.int, - }), -}); - -export default importCycleDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts deleted file mode 100644 index ff5f447..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/143-coverage-badge-updater.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: Update README.md with shields.io coverage badges from coverage summary JSON. -const coverageBadgeUpdater = agent({ - model: "typecheck", - instructions: p`Read the coverage summary and generate shields.io badge markdown. - -Coverage summary: -${p.readOptional("coverage/coverage-summary.json", "{}")} - -Compute coverage percentages per category (lines, statements, functions, branches) and overall. -Generate shields.io badge markdown URL for each category. -Classify overall coverage rating: -- green: >= 80%, yellow: 50-79%, red: < 50% - -Write the badge summary markdown to README.md using the p.writeOutput intent below. -${p.writeOutput("badgeSummary", "README.md")} - -Return coverageByCategory (record of percentages), overallPct, rating, badgesWritten, and badgeSummary.`, - output: s.object({ - coverageByCategory: s.record(s.number), - overallPct: s.number, - rating: s.enum("green", "yellow", "red"), - badgesWritten: s.boolean, - badgeSummary: s.string, - }), -}); - -export default coverageBadgeUpdater; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts deleted file mode 100644 index e2087b4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/144-dep-license-auditor.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const extractLicense = defineTool("extractLicense", { - description: "Read license field from a package in node_modules.", - parameters: s.object({ packageName: s.string }), - async handler({ packageName }) { - const { readFileSync } = await import("node:fs"); - try { - const pkgPath = `node_modules/${packageName}/package.json`; - const pkg = JSON.parse(readFileSync(pkgPath, "utf8")); - const license: string = pkg.license ?? pkg.licenses?.[0]?.type ?? "UNKNOWN"; - let category: "permissive" | "copyleft" | "unknown" = "unknown"; - const upper = license.toUpperCase(); - if (["MIT", "ISC", "BSD", "APACHE", "0BSD", "WTFPL"].some((l: string) => upper.includes(l))) { - category = "permissive"; - } else if (["GPL", "LGPL", "AGPL", "MPL", "EUPL"].some((l: string) => upper.includes(l))) { - category = "copyleft"; - } - return { license, category }; - } catch { - return { license: "UNKNOWN", category: "unknown" as const }; - } - }, -}); - -// Agent role: Audit dependency licenses and flag copyleft packages. -const depLicenseAuditor = agent({ - model: "typecheck", - instructions: p`Audit dependency licenses for this project. - -List installed packages: -${p.bash("npm ls --json --depth=0 2>/dev/null | node -e \"const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));console.log(Object.keys(d.dependencies||{}).join('\\n'))\" 2>/dev/null || ls node_modules | head -50")} - -For each package, use the extractLicense tool to get its license and category. -Return packages array, hasCopyleft flag, and totalPackages count.`, - tools: [extractLicense], - output: s.object({ - packages: s.array( - s.object({ - name: s.string, - license: s.string, - category: s.enum("permissive", "copyleft", "unknown"), - }), - ), - hasCopyleft: s.boolean, - totalPackages: s.int, - }), -}); - -export default depLicenseAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts deleted file mode 100644 index aac78db..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/145-test-coverage-mapper.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const matchTestFile = defineTool("matchTestFile", { - description: "Heuristically find test files matching a source file by name.", - parameters: s.object({ sourcePath: s.string, testFiles: s.array(s.string) }), - handler({ sourcePath, testFiles }) { - const baseName = sourcePath.split("/").pop()!.replace(/\.ts$/, ""); - const patterns = [ - `${baseName}.test.ts`, - `${baseName}.spec.ts`, - `${baseName}.test.js`, - `${baseName}.spec.js`, - ]; - const matched = testFiles.filter((f: string) => - patterns.some((p: string) => f.endsWith(p)) - ); - return { matched }; - }, -}); - -// Agent role: Map source files to their test counterparts and classify coverage. -const testCoverageMapper = agent({ - model: "typecheck", - maxTurns: 2, - instructions: p`Map source files to test files using filename heuristics. - -Source files: -${p.bash("find . -type f -name '*.ts' ! -name '*.test.ts' ! -name '*.spec.ts' ! -path '*/node_modules/*' ! -path '*/.git/*' | head -40")} - -Test files: -${p.bash("find . -type f \\( -name '*.test.ts' -o -name '*.spec.ts' \\) ! -path '*/node_modules/*' | head -40")} - -For each source file, use matchTestFile to find matching test files. -Classify coverage: -- covered: at least one test file matched -- uncovered: no test files matched -- partial: test file exists but may not cover all exports (use heuristics) - -Return s.record output keyed by source file path.`, - tools: [matchTestFile], - addons: repair(), - output: s.record( - s.object({ - coverage: s.enum("covered", "uncovered", "partial"), - testFiles: s.array(s.string), - reason: s.string, - }), - ), -}); - -export default testCoverageMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts deleted file mode 100644 index 5c29107..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/146-file-permission-scanner.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parsePermissions = defineTool("parsePermissions", { - description: "Parse a unix permission string and classify risk level.", - parameters: s.object({ permissions: s.string, filename: s.string }), - handler({ permissions }) { - const isExecutable = permissions[3] === "x" || permissions[6] === "x" || permissions[9] === "x"; - const isWorldWritable = permissions[8] === "w"; - let riskLevel: "safe" | "warn" | "danger" = "safe"; - if (isWorldWritable) riskLevel = "danger"; - else if (isExecutable) riskLevel = "warn"; - return { isExecutable, isWorldWritable, riskLevel }; - }, -}); - -// Agent role: Scan workspace file permissions and flag dangerous or unusual access modes. -const filePermissionScanner = agent({ - model: "typecheck", - instructions: p`Scan file permissions in the workspace and classify risk. - -List files with permissions: -${p.bash("find . -maxdepth 3 -type f ! -path '*/node_modules/*' ! -path '*/.git/*' | head -50 | xargs ls -la 2>/dev/null")} - -For each file, use parsePermissions to determine isExecutable, isWorldWritable, and riskLevel. -Return s.object with files record (keyed by filename), dangerCount, and allSafe.`, - tools: [parsePermissions], - output: s.object({ - files: s.record( - s.object({ - mode: s.string, - isExecutable: s.boolean, - isWorldWritable: s.boolean, - riskLevel: s.enum("safe", "warn", "danger"), - }), - ), - dangerCount: s.int, - allSafe: s.boolean, - }), -}); - -export default filePermissionScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts deleted file mode 100644 index ef58fb6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/147-git-submodule-health.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parseSubmoduleStatus = defineTool("parseSubmoduleStatus", { - description: "Parse a git submodule status line into structured fields.", - parameters: s.object({ line: s.string }), - handler({ line }) { - const trimmed = line.trimStart(); - if (!trimmed) return null; - const statusChar = line[0]; - const rest = trimmed.replace(/^[\+\- U]/, "").trim(); - const parts = rest.split(/\s+/); - const sha = parts[0] ?? ""; - const path = parts[1] ?? ""; - let status: "clean" | "modified" | "uninitialized" | "missing" = "clean"; - if (statusChar === "+") status = "modified"; - else if (statusChar === "-") status = "uninitialized"; - else if (statusChar === "U") status = "missing"; - return { path, sha, status }; - }, -}); - -// Agent role: Inventory git submodules and report their health status. -const gitSubmoduleHealth = agent({ - model: "typecheck", - instructions: p`Check the health of all git submodules in this repository. - -Submodule status: -${p.bash("git submodule status 2>/dev/null || echo '(no submodules)'")} - -Submodule config: -${p.readOptional(".gitmodules", "(no .gitmodules file)")} - -For each status line, use parseSubmoduleStatus to extract path, sha, and status. -Return submodules array, allClean flag, and totalCount.`, - tools: [parseSubmoduleStatus], - output: s.object({ - submodules: s.array( - s.object({ - path: s.string, - sha: s.string, - status: s.enum("clean", "modified", "uninitialized", "missing"), - }), - ), - allClean: s.boolean, - totalCount: s.int, - }), -}); - -export default gitSubmoduleHealth; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts deleted file mode 100644 index dc25285..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/148-ts-decorator-scanner.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyDecorator = defineTool("classifyDecorator", { - description: "Classify a decorator as class, method, property, or parameter based on context.", - parameters: s.object({ name: s.string, context: s.string }), - handler({ context }) { - const trimmed = context.trim(); - if (/^@\w+\s*\n?\s*(export\s+)?(abstract\s+)?class\s+/.test(trimmed) || - /class\s+\w+/.test(trimmed)) { - return { type: "class" }; - } - if (/\(.*:/.test(trimmed) && trimmed.includes("constructor")) { - return { type: "parameter" }; - } - if (/^\s*(public|private|protected|readonly)/.test(trimmed) || - /\w+\s*[=:!]/.test(trimmed)) { - return { type: "property" }; - } - return { type: "method" }; - }, -}); - -// Agent role: Scan TypeScript files for decorator usage and classify each by decorator type. -const tsDecoratorScanner = agent({ - model: "typecheck", - instructions: p`Find and classify TypeScript decorators across the codebase. - -Scan for decorators: -${p.bash("grep -rn '@[A-Z][a-zA-Z]*' --include='*.ts' . 2>/dev/null | grep -v node_modules | grep -v '.git' | head -60")} - -For each unique decorator found, use classifyDecorator with one representative context line. -Determine if any experimental decorators are used (e.g., @Inject, @Component, @NgModule). -Return decorators record (keyed by decorator name with count and type), totalCount, and hasExperimental.`, - tools: [classifyDecorator], - output: s.object({ - decorators: s.record( - s.object({ - count: s.int, - type: s.enum("class", "method", "property", "parameter"), - }), - ), - totalCount: s.int, - hasExperimental: s.boolean, - }), -}); - -export default tsDecoratorScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts deleted file mode 100644 index 8dd9ad1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/149-dotfile-inventory.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: Discover and categorize dotfiles in the workspace root and nearby directories. -const dotfileInventory = agent({ - model: "typecheck", - instructions: p`Inventory all dotfiles in the workspace and categorize them. - -Find dotfiles: -${p.bash("find . -maxdepth 2 -name '.*' -type f ! -path '*/.git/*' 2>/dev/null")} - -Read common dotfiles for context: -${p.bash("find . -maxdepth 2 -name '.*' -type f ! -path '*/.git/*' 2>/dev/null | head -10 | xargs head -c 200 2>/dev/null")} - -For each dotfile, determine its purpose and category: -- editor: .editorconfig, .vscode/*, .nvmrc -- git: .gitignore, .gitattributes, .gitmodules -- shell: .bashrc, .zshrc, .profile, .env -- package: .npmrc, .yarnrc, .nvmrc, .node-version -- ci: .travis.yml, .circleci, .github, .eslintrc -- other: anything else - -Return dotfiles record (keyed by filename) with purpose and category, totalFound, and categorySummary (record of counts per category).`, - addons: repair(), - output: s.object({ - dotfiles: s.record( - s.object({ - purpose: s.string, - category: s.enum("editor", "git", "shell", "package", "ci", "other"), - }), - ), - totalFound: s.int, - categorySummary: s.record(s.int), - }), -}); - -export default dotfileInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts deleted file mode 100644 index a50c0b9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/15-api-diff-summary.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: convert the change description to Keep a Changelog style. -const categorize = agent({ - model: "typecheck", - output: s.object({ - category: s.enum("added", "changed", "deprecated", "removed", "fixed", "security"), - entry: s.string - }), - instructions: `Convert the change description to Keep a Changelog style.`, -}); - -export default categorize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts deleted file mode 100644 index 8fd37de..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/150-git-hotspot-analyzer-v3.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; - -// Agent role: identify hot-spot files by git churn and classify risk level. -const gitHotspotAnalyzerV3 = agent({ - model: "typecheck", - addons: steering({ message: "Focus on files that appear most frequently. Assign riskLevel based on churnScore: >20=critical, >10=high, >5=medium, else low." }), - instructions: p`Analyze git history to find frequently changed files and classify their risk. - -Recently changed files (with churn counts): -${p.bash("git log --name-only --format='' HEAD~50..HEAD | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} - -Top contributors overall: -${p.bash("git shortlog -sn HEAD~50..HEAD 2>/dev/null | head -10")} - -Use the countChurn tool to parse the churn output for each file. For each file, determine -the churnScore, assign topContributors from the shortlog output, and classify riskLevel. -Return a record keyed by file path with the declared output shape.`, - tools: [ - defineTool("countChurn", { - description: "Parse a line of uniq -c output to extract count and filename", - parameters: s.object({ line: s.string }), - handler({ line }) { - const m = line.trim().match(/^(\d+)\s+(.+)$/); - if (!m) return { count: 0, file: "" }; - return { count: parseInt(m[1], 10), file: m[2].trim() }; - }, - }), - ], - output: s.record( - s.object({ - churnScore: s.int, - topContributors: s.array(s.string), - riskLevel: s.enum("low", "medium", "high", "critical"), - }) - ), -}); - -export default gitHotspotAnalyzerV3; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts deleted file mode 100644 index 7f230b8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/151-loc-statistics-v2.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: gather lines-of-code statistics per file extension. -const locStatisticsV2 = agent({ - model: "typecheck", - instructions: p`Count lines of code per file extension in this workspace. - -TypeScript files found: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | head -50")} - -Line counts for TypeScript files: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | head -20 | xargs wc -l 2>/dev/null | tail -1")} - -JavaScript files found: -${p.bash("find . -name '*.js' -not -path '*/node_modules/*' | head -20")} - -Use the aggregateExtension tool to compute totals. Then classify complexity for each -extension: xlarge > 10000 lines, large > 5000, medium > 1000, small otherwise. -Return a record keyed by extension (e.g. ".ts", ".js") with lineCount, fileCount, -and complexity.`, - tools: [ - defineTool("aggregateExtension", { - description: "Count lines in files matching a given extension", - parameters: s.object({ extension: s.string, sampleFile: s.string }), - async handler({ extension, sampleFile }) { - const { execSync } = await import("node:child_process"); - try { - const count = execSync( - `find . -name '*${extension}' -not -path '*/node_modules/*' | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}'`, - { encoding: "utf-8" } - ).trim(); - const files = execSync( - `find . -name '*${extension}' -not -path '*/node_modules/*' | wc -l`, - { encoding: "utf-8" } - ).trim(); - return { extension, lineCount: parseInt(count) || 0, fileCount: parseInt(files) || 0, sampleFile }; - } catch { - return { extension, lineCount: 0, fileCount: 0, sampleFile }; - } - }, - }), - ], - output: s.record( - s.object({ - lineCount: s.int, - fileCount: s.int, - complexity: s.enum("small", "medium", "large", "xlarge"), - }) - ), -}); - -export default locStatisticsV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts deleted file mode 100644 index a3d6e92..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/152-import-cycle-detector-v3.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: detect circular import cycles in TypeScript source and classify severity. -const importCycleDetectorV3 = agent({ - model: "typecheck", - maxTurns: 3, - addons: repair(), - instructions: p`Detect circular import cycles in this TypeScript project. - -Circular dependency analysis: -${p.bash("npx madge --circular --extensions ts src 2>/dev/null || echo 'No cycles found or madge not available'")} - -TypeScript configuration: -${p.readOptional("tsconfig.json", "{}")} - -Analyze the output above. Each cycle is a group of files that import each other in a -circle. Classify severity: high if the cycle involves more than 3 files or core modules, -medium for 2-3 files, low for simple two-file cycles. - -Return hasCycles (true if any cycles found), the cycles array with path (array of file -strings in the cycle) and severity, and totalCycles count.`, - output: s.object({ - hasCycles: s.boolean, - cycles: s.array( - s.object({ - path: s.array(s.string), - severity: s.enum("high", "medium", "low"), - }) - ), - totalCycles: s.int, - }), -}); - -export default importCycleDetectorV3; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts deleted file mode 100644 index a65f803..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/153-coverage-badge-updater-v2.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: read coverage summary and update README with shields.io badge links. -const coverageBadgeUpdaterV2 = agent({ - model: "typecheck", - instructions: p`Read coverage data and update the README with shields.io coverage badges. - -Coverage summary (JSON): -${p.readOptional("coverage/coverage-summary.json", "{}")} - -Current README: -${p.readOptional("README.md", "# Project\n")} - -Compute the coverage percentage for each category (statements, branches, functions, lines) -from the total section. Compute overallPct as the average. Classify rating: green >= 80%, -yellow >= 60%, red < 60%. - -Generate shields.io badge markdown for each category using URL format: -https://img.shields.io/badge/coverage-XX%25-green - -Write the updated README with badges added at the top using p.write. - -${p.write("README.md", "")} - -Return coverageByCategory (record of category to percentage), overallPct, rating, and -badgesWritten (true if README was updated).`, - output: s.object({ - coverageByCategory: s.record(s.number), - overallPct: s.number, - rating: s.enum("green", "yellow", "red"), - badgesWritten: s.boolean, - }), -}); - -export default coverageBadgeUpdaterV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts deleted file mode 100644 index 31f71d6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/154-dep-license-auditor-v2.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: audit npm dependency licenses and flag copyleft packages. -const depLicenseAuditorV2 = agent({ - model: "typecheck", - instructions: p`Audit the licenses of npm dependencies and classify each one. - -Installed dependencies (JSON tree): -${p.bash("npm ls --json --depth=0 2>/dev/null || echo '{}'")} - -Package dependency names: -${p.bash("node -e \"try{const p=require('./package.json');console.log(JSON.stringify(Object.keys(p.dependencies||{})))}catch(e){console.log('[]')}\"")} - -Package license fields from node_modules: -${p.bash("node -e \"const fs=require('fs');const d='./node_modules';if(fs.existsSync(d)){const pkgs=fs.readdirSync(d).filter(x=>!x.startsWith('.'));pkgs.slice(0,30).forEach(p=>{try{const m=JSON.parse(fs.readFileSync(d+'/'+p+'/package.json','utf8'));console.log(p+':'+m.license)}catch(e){}});}\" 2>/dev/null || echo 'unavailable'")} - -For each dependency, determine its license. Classify as: -- permissive: MIT, ISC, BSD, Apache, CC0, Unlicense, 0BSD -- copyleft: GPL, LGPL, AGPL, MPL, EUPL, CC-BY-SA -- unknown: anything else or unspecified - -Return the packages array with name, license, and classification, hasCopyleft (true if any -copyleft found), and totalCount.`, - output: s.object({ - packages: s.array( - s.object({ - name: s.string, - license: s.string, - classification: s.enum("permissive", "copyleft", "unknown"), - }) - ), - hasCopyleft: s.boolean, - totalCount: s.int, - }), -}); - -export default depLicenseAuditorV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts deleted file mode 100644 index 7d65660..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/155-test-coverage-mapper-v2.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -// Agent role: map source files to their test files using filename heuristics. -const testCoverageMapperV2 = agent({ - model: "typecheck", - maxTurns: 2, - addons: repair(), - instructions: p`Map TypeScript source files to their corresponding test files. - -Source files (non-test TypeScript): -${p.bash("find . -name '*.ts' -not -name '*.test.ts' -not -name '*.spec.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -30")} - -Test files: -${p.bash("find . -name '*.test.ts' -o -name '*.spec.ts' | grep -v node_modules | head -30")} - -Use the matchTestFile tool for each source file to find its corresponding test file using -filename heuristics (e.g., src/foo.ts -> src/foo.test.ts or tests/foo.test.ts). - -Return a record keyed by source file path with coverage ("covered" if test found, -"uncovered" if none, "partial" if indirect match), testFiles (array of matched test paths), -and reason explaining the determination.`, - tools: [ - defineTool("matchTestFile", { - description: "Find test files that match a source file using naming heuristics", - parameters: s.object({ sourceFile: s.string, testFiles: s.array(s.string) }), - handler({ sourceFile, testFiles }) { - const base = sourceFile.replace(/\.tsx?$/, "").replace(/^.*\//, ""); - const direct = testFiles.filter((t) => - t.includes(`${base}.test`) || t.includes(`${base}.spec`) - ); - const partial = direct.length === 0 - ? testFiles.filter((t) => t.toLowerCase().includes(base.toLowerCase())) - : []; - return { - matched: direct, - partial, - coverage: direct.length > 0 ? "covered" : partial.length > 0 ? "partial" : "uncovered", - }; - }, - }), - ], - output: s.record( - s.object({ - coverage: s.enum("covered", "uncovered", "partial"), - testFiles: s.array(s.string), - reason: s.string, - }) - ), -}); - -export default testCoverageMapperV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts deleted file mode 100644 index 595ebe6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/156-regex-pattern-tester.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -// Agent role: run regex patterns against test cases and report pass/fail results. -const regexPatternTester = agent({ - model: "typecheck", - addons: repair(), - input: s.object({ - patterns: s.array( - s.object({ - name: s.string, - regex: s.string, - testCases: s.array( - s.object({ - input: s.string, - expected: s.boolean, - }) - ), - }) - ), - }), - instructions: p`Run each regex pattern against its test cases and report results. - -Input patterns and test cases: -${p.json("input")} - -Use the runRegexTest tool for each (pattern, input) pair. Then build the results array -with patternName, input, expected, actual (from tool), and passed (expected === actual). -Count passCount and failCount. Set allPassed to true only if failCount is 0.`, - tools: [ - defineTool("runRegexTest", { - description: "Test a regex pattern against an input string", - parameters: s.object({ pattern: s.string, input: s.string }), - handler({ pattern, input }) { - try { - const matched = new RegExp(pattern).test(input); - return { matched }; - } catch { - return { matched: false }; - } - }, - }), - ], - output: s.object({ - results: s.array( - s.object({ - patternName: s.string, - input: s.string, - expected: s.boolean, - actual: s.boolean, - passed: s.boolean, - }) - ), - passCount: s.int, - failCount: s.int, - allPassed: s.boolean, - }), -}); - -export default regexPatternTester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts deleted file mode 100644 index aca03e5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/157-commit-churn-classifier.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: classify files by commit churn frequency and assign a risk level. -const commitChurnClassifier = agent({ - model: "typecheck", - addons: steering({ message: "Be precise: assign riskLevel based on churnCount: >20=critical, >10=volatile, >5=active, else stable." }), - instructions: p`Classify repository files by how frequently they are committed (churn). - -File churn counts from last 100 commits (count file): -${p.bash("git log --name-only --format='' HEAD~100..HEAD 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} - -For each file in the output above, parse the churn count and assign a riskLevel: -- critical: churnCount > 20 -- volatile: churnCount > 10 -- active: churnCount > 5 -- stable: churnCount <= 5 - -Return a record keyed by file path with churnCount (integer) and riskLevel.`, - output: s.record( - s.object({ - churnCount: s.int, - riskLevel: s.enum("stable", "active", "volatile", "critical"), - }) - ), -}); - -export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts deleted file mode 100644 index 1540dea..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/158-npm-package-size.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: estimate npm package publish size and rate it with a recommendation. -const npmPackageSize = agent({ - model: "typecheck", - instructions: p`Estimate the npm package publish size and provide a recommendation. - -Files that would be included in npm publish (dry run): -${p.bash("npm pack --dry-run 2>&1 | head -40")} - -Overall workspace size: -${p.bash("du -sh . 2>/dev/null | cut -f1")} - -Package metadata: -${p.readOptional("package.json", "{}")} - -Parse the npm pack output to extract file sizes. Use the classifySize tool to rate the -total estimated size. Provide a recommendation based on the rating (e.g., suggest adding -files to .npmignore if large/xlarge). - -Return estimatedSizeKb (total in KB), topFiles (up to 5 largest files with file and -sizeKb), sizeRating, and a recommendation string.`, - tools: [ - defineTool("classifySize", { - description: "Classify a package size in KB into a rating tier", - parameters: s.object({ sizeKb: s.number }), - handler({ sizeKb }) { - if (sizeKb < 10) return { rating: "tiny" }; - if (sizeKb < 50) return { rating: "small" }; - if (sizeKb < 200) return { rating: "medium" }; - if (sizeKb < 1000) return { rating: "large" }; - return { rating: "xlarge" }; - }, - }), - ], - output: s.object({ - estimatedSizeKb: s.number, - topFiles: s.array(s.object({ file: s.string, sizeKb: s.number })), - sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), - recommendation: s.string, - }), -}); - -export default npmPackageSize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts deleted file mode 100644 index d041006..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/159-ts-branch-coverage.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: identify branch statements in a TypeScript file and estimate coverage. -const branchAnalyzer = agent({ - name: "branchAnalyzer", - model: "typecheck", - input: s.string, - instructions: p`Analyze the TypeScript source code provided and identify all branch points. - -For each branch (if statements, ternaries, switch cases, nullish coalescing), determine: -- functionName: the enclosing function name (or "module" if top-level) -- line: approximate line number -- branchType: "if", "ternary", "switch", or "nullish" -- covered: false (assume uncovered unless the code contains obvious test guards) - -Return only the declared output array.`, - output: s.array( - s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "nullish"), - covered: s.boolean, - }) - ), -}); - -// Agent role: coordinate branch coverage analysis by delegating to branchAnalyzer subagent. -const tsBranchCoverage = agent({ - model: "typecheck", - input: s.object({ filePath: s.path }), - instructions: p`Analyze TypeScript branch coverage for the file at the provided path. - -File content: -${p.readInput("filePath")} - -Delegate the analysis to the branchAnalyzer subagent. Then aggregate results into: -- branches: the full array returned by branchAnalyzer -- summary: totalBranches (length of array), coveredBranches (count where covered=true), - uncoveredBranches (count where covered=false)`, - agents: { branchAnalyzer }, - output: s.object({ - branches: s.array( - s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "nullish"), - covered: s.boolean, - }) - ), - summary: s.object({ - totalBranches: s.int, - coveredBranches: s.int, - uncoveredBranches: s.int, - }), - }), -}); - -export default tsBranchCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts deleted file mode 100644 index ebdc9c9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/16-docs-gap-analysis.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: compare public API declarations and identify breaking changes. -const apiDiff = agent({ - model: "typecheck", - output: s.object({ - breaking: s.boolean, - summary: s.string, - changes: s.array(s.string) - }), - instructions: `Compare public API declarations and identify breaking changes.`, -}); -export default apiDiff; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts deleted file mode 100644 index 1d42806..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/160-dead-code-detector.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, defineTool, p, repair, s } from "rig"; - -// Agent role: detect dead TypeScript exports by scanning for exported symbols and estimating usage counts. -const deadCodeDetector = agent({ - model: "typecheck", - instructions: p`Detect dead code in this TypeScript project. - -Files in project: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -40")} - -Exported symbols found: -${p.bash("grep -rn '^export ' --include='*.ts' . 2>/dev/null | grep -v node_modules | head -60")} - -Use the estimateUsage tool for each exported symbol name to count how many times it appears across the codebase. Classify each as: "used" (>1 reference), "possibly-dead" (exactly 1, the declaration itself), or "dead" (0 references outside declaration). Return only the declared output.`, - tools: [ - defineTool("estimateUsage", { - description: "Count non-declaration usages of an exported symbol across the codebase", - parameters: s.object({ symbol: s.string }), - async handler({ symbol }) { - const { execSync } = await import("node:child_process"); - try { - const out = execSync( - `grep -rn "\\b${symbol}\\b" --include="*.ts" . 2>/dev/null | grep -v "^export " | grep -v node_modules | wc -l`, - { encoding: "utf-8" } - ); - return { symbol, usageCount: parseInt(out.trim(), 10) }; - } catch { - return { symbol, usageCount: 0 }; - } - }, - }), - ], - addons: [repair()], - output: s.object({ - symbols: s.record(s.object({ - usageCount: s.int, - status: s.enum("used", "possibly-dead", "dead"), - })), - totalExported: s.int, - deadCount: s.int, - }), -}); - -export default deadCodeDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts deleted file mode 100644 index 4165b0c..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/161-openapi-spec-validator.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: validate an OpenAPI spec file for structural correctness and report issues. -const openapiSpecValidator = agent({ - model: "typecheck", - instructions: p`Validate the OpenAPI specification in this workspace. - -openapi.json content: -${p.readOptional("openapi.json")} - -openapi.yaml content: -${p.readOptional("openapi.yaml")} - -Use the checkStructure tool to validate the spec content. Check for: required fields (openapi version, info.title, info.version, paths), valid HTTP methods, proper response codes, and schema references. Return only the declared output.`, - tools: [ - defineTool("checkStructure", { - description: "Check structural validity of OpenAPI spec content", - parameters: s.object({ content: s.string }), - handler({ content }) { - const issues: Array<{ type: "error" | "warning" | "info"; message: string; path?: string }> = []; - try { - const spec = JSON.parse(content); - if (!spec.openapi) issues.push({ type: "error", message: "Missing required field 'openapi'", path: "openapi" }); - if (!spec.info) issues.push({ type: "error", message: "Missing required field 'info'", path: "info" }); - else { - if (!spec.info.title) issues.push({ type: "error", message: "Missing info.title", path: "info.title" }); - if (!spec.info.version) issues.push({ type: "error", message: "Missing info.version", path: "info.version" }); - } - if (!spec.paths) issues.push({ type: "error", message: "Missing required field 'paths'", path: "paths" }); - } catch { - issues.push({ type: "warning", message: "Content is not valid JSON — may be YAML or empty" }); - } - return { issues }; - }, - }), - ], - output: s.object({ - valid: s.boolean, - issues: s.array(s.object({ - type: s.enum("error", "warning", "info"), - message: s.string, - path: s.optional(s.string), - })), - issueCount: s.int, - }), -}); - -export default openapiSpecValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts deleted file mode 100644 index 5a66a8f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/162-api-endpoint-extractor.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: classify purpose of each API endpoint found in route files. -const endpointClassifier = agent({ - name: "endpointClassifier", - model: "typecheck", - input: s.object({ route: s.string }), - instructions: p`Classify this API route: return purpose and description.`, - output: s.object({ - purpose: s.enum("read", "write", "delete", "auth", "health", "other"), - description: s.string, - }), -}); - -// Agent role: extract API endpoints from route/controller files and classify each by purpose. -const apiEndpointExtractor = agent({ - model: "typecheck", - agents: { endpointClassifier }, - instructions: p`Extract and classify all API endpoints in this workspace. - -Route patterns found: -${p.bash("grep -rn '\\.(get|post|put|delete|patch)(' --include='*.ts' --include='*.js' . 2>/dev/null | grep -v node_modules | head -40")} - -For each unique route pattern found, delegate to the endpointClassifier subagent to determine its purpose. Return all discovered endpoints with method, path, and purpose. Return only the declared output.`, - output: s.object({ - endpoints: s.array(s.object({ - method: s.enum("GET", "POST", "PUT", "DELETE", "PATCH"), - path: s.string, - purpose: s.enum("read", "write", "delete", "auth", "health", "other"), - })), - totalCount: s.int, - hasCrud: s.boolean, - }), -}); - -export default apiEndpointExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts deleted file mode 100644 index d3f755b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/163-source-file-annotator.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: generate JSDoc annotations for TypeScript source files and write annotated output. -const jsDocAnnotator = agent({ - name: "jsDocAnnotator", - model: "typecheck", - input: s.object({ filePath: s.path, content: s.string }), - instructions: p`Add JSDoc comments to every exported function, class, and interface in the TypeScript source. Return only the declared output.`, - output: s.object({ - annotatedContent: s.string, - annotationsAdded: s.int, - }), -}); - -// Agent role: annotate TypeScript source files with JSDoc comments using a subagent and write results. -const sourceFileAnnotator = agent({ - model: "typecheck", - agents: { jsDocAnnotator }, - instructions: p`Annotate TypeScript source files with JSDoc comments. - -TypeScript files in workspace: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.test.ts' -not -name '*.d.ts' | head -20")} - -For each file, read its content, delegate to the jsDocAnnotator subagent, then write the annotated version back using p.write. Track which files were processed successfully and which were skipped. - -${p.write("annotated-summary.md", "# Annotation Summary\n")} - -Return only the declared output.`, - output: s.object({ - filesProcessed: s.int, - filesSkipped: s.int, - totalAnnotations: s.int, - processedPaths: s.array(s.path), - }), -}); - -export default sourceFileAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts deleted file mode 100644 index b39346d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/164-stale-dependency-detector.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { agent, defineTool, p, repair, s } from "rig"; - -// Agent role: detect stale npm dependencies by comparing installed versions with latest published versions. -const staleDependencyDetector = agent({ - model: "typecheck", - instructions: p`Identify stale npm dependencies that need updating. - -package.json contents: -${p.read("package.json")} - -npm outdated results: -${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} - -Use the classifyDrift tool for each outdated package to classify the version drift level. Determine the overall risk for the project. Return only the declared output.`, - tools: [ - defineTool("classifyDrift", { - description: "Classify version drift between current and latest version", - parameters: s.object({ current: s.string, latest: s.string }), - handler({ current, latest }) { - const parse = (v: string) => v.replace(/^[^0-9]*/, "").split(".").map(Number); - const [cMaj, cMin] = parse(current); - const [lMaj, lMin] = parse(latest); - if (lMaj > cMaj) return { driftLevel: "major" as const }; - if (lMin > cMin) return { driftLevel: "minor" as const }; - return { driftLevel: "patch" as const }; - }, - }), - ], - addons: [repair()], - output: s.object({ - packages: s.array(s.object({ - name: s.string, - current: s.string, - latest: s.string, - driftLevel: s.enum("major", "minor", "patch", "ok"), - })), - overallRisk: s.enum("safe", "moderate", "critical"), - staleCount: s.int, - }), -}); - -export default staleDependencyDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts deleted file mode 100644 index ac4577f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/165-git-tag-timeline.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize commits and authors between two git tags. -const timelineSummarizer = agent({ - name: "timelineSummarizer", - model: "typecheck", - input: s.object({ - tag: s.string, - prevTag: s.string, - commits: s.string, - }), - instructions: p`Summarize the git log between two tags and return structured timeline entry.`, - output: s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - }), -}); - -// Agent role: build a release timeline from git tags showing commit counts and top authors per tag. -const gitTagTimeline = agent({ - model: "typecheck", - agents: { timelineSummarizer }, - instructions: p`Build a git tag release timeline. - -Git tags (sorted by date): -${p.bash("git tag --sort=version:refname 2>/dev/null | tail -20 || echo 'No tags found'")} - -Recent commit log: -${p.bash("git log --oneline --format='%h %an %ad %s' --date=short -40 2>/dev/null || echo 'No commits'")} - -For each tag pair, delegate to the timelineSummarizer subagent with the relevant commit log section. Also check for unreleased commits after the latest tag. Return only the declared output.`, - output: s.object({ - timeline: s.array(s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - })), - hasUnreleasedCommits: s.boolean, - totalTags: s.int, - }), -}); - -export default gitTagTimeline; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts deleted file mode 100644 index beeed21..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/166-env-variable-type-inferrer.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -// Agent role: infer the type and purpose of each variable defined in a .env.example file. -const envVariableTypeInferrer = agent({ - model: "typecheck", - instructions: p`Infer the type and purpose of each environment variable in the project. - -.env.example contents: -${p.readOptional(".env.example")} - -.env.sample contents: -${p.readOptional(".env.sample")} - -For each KEY=value pair found, use the inferType tool to classify the value type. Produce a description of each variable's likely purpose based on its name. Determine whether all variables appear to be documented (have a non-empty value or comment). Return only the declared output.`, - tools: [ - defineTool("inferType", { - description: "Infer the type of an environment variable value", - parameters: s.object({ key: s.string, value: s.string }), - handler({ value }) { - const v = value.trim(); - if (/^https?:\/\//i.test(v)) return { type: "url" as const }; - if (/^\/|^\.\.?\//.test(v)) return { type: "path" as const }; - if (/^(true|false)$/i.test(v)) return { type: "boolean" as const }; - if (/^\d+(\.\d+)?$/.test(v)) return { type: "number" as const }; - if (v === "") return { type: "unknown" as const }; - return { type: "string" as const }; - }, - }), - ], - output: s.object({ - variables: s.record(s.object({ - type: s.enum("string", "number", "boolean", "url", "path", "unknown"), - description: s.string, - })), - totalCount: s.int, - allDocumented: s.boolean, - }), -}); - -export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts deleted file mode 100644 index 76b0664..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/167-makefile-target-extractor.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { agent, defineTool, p, repair, s } from "rig"; - -// Agent role: extract and classify Makefile targets into phony vs real file targets with descriptions. -const makefileTargetExtractor = agent({ - model: "typecheck", - instructions: p`Extract and classify all targets from the Makefile in this workspace. - -Makefile contents: -${p.readOptional("Makefile")} - -Use the parseTargets tool to extract target names, then classify each. Phony targets are declared with .PHONY or have no corresponding file. Check if each target has an adjacent comment (##) for help text. Return only the declared output.`, - tools: [ - defineTool("parseTargets", { - description: "Parse Makefile content and extract target names with their type", - parameters: s.object({ content: s.string }), - handler({ content }) { - const phonyTargets = new Set(); - const phonyMatch = content.match(/^\.PHONY\s*:(.*)/gm) || []; - for (const line of phonyMatch) { - line.replace(/^\.PHONY\s*:/, "").trim().split(/\s+/).forEach((t: string) => phonyTargets.add(t)); - } - const targetLines = content.match(/^([a-zA-Z0-9_-]+)\s*:/gm) || []; - const targets = targetLines - .map((l: string) => l.replace(/:.*/, "").trim()) - .filter((t: string) => t && t !== ".PHONY"); - return { targets, phonyTargets: [...phonyTargets] }; - }, - }), - ], - addons: [repair()], - output: s.object({ - targets: s.array(s.object({ - name: s.string, - isPhony: s.boolean, - hasHelp: s.boolean, - description: s.optional(s.string), - })), - totalCount: s.int, - phonyCount: s.int, - }), -}); - -export default makefileTargetExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts deleted file mode 100644 index 3701159..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/168-test-fixture-generator.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze a TypeScript function's signature and generate a test fixture file. -const signatureAnalyzer = agent({ - name: "signatureAnalyzer", - model: "typecheck", - input: s.object({ content: s.string, functionName: s.string }), - instructions: p`Analyze the TypeScript source and identify the signature for the requested function. Return parameter types, return type, and any needed imports.`, - output: s.object({ - params: s.array(s.object({ name: s.string, type: s.string })), - returnType: s.string, - requiredImports: s.array(s.string), - }), -}); - -// Agent role: generate a test fixture file for a specific TypeScript function. -const testFixtureGenerator = agent({ - model: "typecheck", - agents: { signatureAnalyzer }, - input: s.object({ - sourceFile: s.path, - functionName: s.string, - }), - instructions: p`Generate a test fixture file for a TypeScript function. - -Source file contents: -${p.readInput("sourceFile")} - -Delegate to the signatureAnalyzer subagent to extract the function signature for the requested functionName. Then generate complete test fixture code including sample inputs, expected outputs, and a describe/it test scaffold. Write the fixture file. - -${p.writeOutput("suggestedFileName", "fixture-output.ts")} - -Return only the declared output.`, - output: s.object({ - fixtureCode: s.string, - imports: s.array(s.string), - suggestedFileName: s.path, - }), -}); - -export default testFixtureGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts deleted file mode 100644 index d5dfc08..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/169-server-uptime-log-parser.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; - -// Agent role: parse server uptime logs to extract start/stop/crash events and compute uptime statistics. -const serverUptimeLogParser = agent({ - model: "typecheck", - instructions: p`Parse server uptime events from system logs. - -System journal / log output: -${p.bash("journalctl -u '*' --no-pager -n 100 2>/dev/null || cat /var/log/syslog 2>/dev/null | tail -100 || echo 'No system logs available'")} - -Use the parseLogLine tool to classify each log entry as a start, stop, crash, or restart event. For each event, extract the timestamp and compute duration from the previous stop/start. Flag anomalies (multiple crashes in quick succession) for steering. Return only the declared output.`, - tools: [ - defineTool("parseLogLine", { - description: "Classify a log line as a server lifecycle event", - parameters: s.object({ line: s.string }), - handler({ line }) { - const lower = line.toLowerCase(); - if (/start(?:ed|ing)|boot(?:ed|ing)|up\b/.test(lower)) return { event: "start" as const }; - if (/crash(?:ed)?|segfault|oom|killed/.test(lower)) return { event: "crash" as const }; - if (/restart(?:ed|ing)/.test(lower)) return { event: "restart" as const }; - if (/stop(?:ped|ping)|shut(?:down)?|halt(?:ed)?/.test(lower)) return { event: "stop" as const }; - return { event: null }; - }, - }), - ], - addons: [ - steering({ message: "If you detect multiple crashes within an hour, flag this as a crash loop anomaly in the output." }), - ], - output: s.object({ - uptimeEvents: s.array(s.object({ - event: s.enum("start", "stop", "crash", "restart"), - timestamp: s.string, - durationSeconds: s.optional(s.number), - })), - crashCount: s.int, - totalUptimeHours: s.number, - hasCrashLoop: s.boolean, - }), -}); - -export default serverUptimeLogParser; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts deleted file mode 100644 index 80aac26..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/17-refactor-plan.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: find documentation gaps against the source API. -const docsGap = agent({ - model: "typecheck", - output: s.object({ - missing: s.array(s.string), - stale: s.array(s.string), - quickFixes: s.array(s.string) - }), - instructions: `Find documentation gaps against the source API.`, -}); -export default docsGap; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts deleted file mode 100644 index 1cfe623..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/170-stale-dep-detector.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, repair } from "rig"; -import { defineTool } from "rig"; - -const classifyDrift = defineTool("classifyDrift", { - description: "Classify version drift between current and latest semver strings", - parameters: s.object({ current: s.string, latest: s.string }), - handler({ current, latest }) { - const parse = (v: string) => v.replace(/^[^0-9]*/, "").split(".").map(Number); - const [cMaj, cMin] = parse(current); - const [lMaj, lMin] = parse(latest); - if (lMaj > cMaj) return "major"; - if (lMin > cMin) return "minor"; - if (latest !== current) return "patch"; - return "ok"; - }, -}); - -// Agent role: detect stale npm dependencies and classify version drift. -const staleDependencyDetector = agent({ - model: "typecheck", - maxTurns: 3, - addons: repair(), - tools: [classifyDrift], - instructions: p`Analyze outdated npm packages using ${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} and the manifest ${p.read("package.json")}. For each outdated package, use the classifyDrift tool to determine drift level. Compute overallRisk: "critical" if any major drift, "moderate" if any minor drift, else "safe".`, - output: s.object({ - packages: s.array(s.object({ - name: s.string, - current: s.string, - latest: s.string, - driftLevel: s.enum("major", "minor", "patch", "ok"), - })), - overallRisk: s.enum("safe", "moderate", "critical"), - }), -}); - -export default staleDependencyDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts deleted file mode 100644 index c3f3024..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/171-git-tag-timeline.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize a release timeline from git tag/commit data (nano). -const timelineSummarizer = agent({ - name: "timelineSummarizer", - model: "typecheck", - instructions: p`Given raw git tag data in the input, produce a structured timeline. For each tag entry extract tag name, date, commit count, and top authors.`, - input: s.object({ rawData: s.string }), - output: s.object({ - timeline: s.array(s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - })), - hasUnreleasedCommits: s.boolean, - }), -}); - -// Agent role: gather git tag and commit metadata then delegate timeline summarization. -const gitTagTimeline = agent({ - model: "typecheck", - agents: { timelineSummarizer }, - instructions: p`List tags with ${p.bash("git tag --sort=-version:refname 2>/dev/null || true")} and recent commits with ${p.bash("git log --oneline -30 --format='%H %ad %an %s' --date=short 2>/dev/null || true")}. Also check for unreleased commits with ${p.bash("git log $(git describe --tags --abbrev=0 2>/dev/null || echo '')..HEAD --oneline 2>/dev/null || true")}. Pass all raw data to the timelineSummarizer subagent and return its output directly.`, - output: s.object({ - timeline: s.array(s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - })), - hasUnreleasedCommits: s.boolean, - }), -}); - -export default gitTagTimeline; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts deleted file mode 100644 index cf7115e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/172-service-health-probe.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: probe service health endpoints and classify status for each URL. -const serviceHealthProbe = agent({ - model: "typecheck", - addons: steering({ message: "For unexpected or missing HTTP codes, classify status as 'unknown' rather than failing." }), - instructions: p`Probe the comma-separated URLs in ${p.env("HEALTH_CHECK_URLS", "https://example.com,https://example.org")}. Use ${p.bash("echo 'probe each URL with: curl -o /dev/null -s -w \\'%{http_code}\\' --max-time 5'")} as a reference. For each URL, probe it and classify its status: "up" (2xx), "down" (4xx/5xx/connection refused), "slow" (timeout), "unknown" (other). Compute healthyCount and overallStatus.`, - output: s.object({ - endpoints: s.array(s.object({ - url: s.url, - status: s.enum("up", "down", "slow", "unknown"), - httpCode: s.int, - })), - healthyCount: s.int, - overallStatus: s.enum("all-healthy", "degraded", "critical"), - }), -}); - -export default serviceHealthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts deleted file mode 100644 index ecd80fc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/173-git-template-renderer.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s } from "rig"; -import { defineTool } from "rig"; - -const parseGitLog = defineTool("parseGitLog", { - description: "Parse a git log line in format 'HASH|AUTHOR|DATE|SUBJECT' into fields", - parameters: s.object({ logLine: s.string }), - handler({ logLine }) { - const parts = logLine.split("|"); - return { - commit: parts[0]?.trim() ?? "", - author: parts[1]?.trim() ?? "", - date: parts[2]?.trim() ?? "", - message: parts[3]?.trim() ?? "", - }; - }, -}); - -// Agent role: render a git-metadata template by filling placeholders from git log output. -const gitTemplateRenderer = agent({ - model: "typecheck", - tools: [parseGitLog], - input: s.string, - instructions: p`Read the template string from input. Gather git metadata: ${p.bash("git log -1 --format='%H|%an|%ad|%s' --date=short 2>/dev/null || echo '|||(no commits)'")} and branch: ${p.bash("git branch --show-current 2>/dev/null || echo 'main'")}. Use the parseGitLog tool to extract fields. Replace {{commit}}, {{author}}, {{branch}}, {{date}}, {{message}} placeholders in the template. Write rendered output via ${p.write("rendered-output.txt", "{{rendered}}")}. Return the rendered text and which placeholders were replaced.`, - output: s.object({ - rendered: s.string, - placeholdersReplaced: s.array(s.string), - outputFile: s.path, - }), -}); - -export default gitTemplateRenderer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts deleted file mode 100644 index 20592e2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/174-changelog-entry-gen.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const validateSemverBump = defineTool("validateSemverBump", { - description: "Validate that a semver bump type string is one of major/minor/patch", - parameters: s.object({ bumpType: s.string }), - handler({ bumpType }) { - const valid = /^(major|minor|patch)$/.test(bumpType); - return { valid, normalized: valid ? bumpType : "patch" }; - }, -}); - -// Agent role: generate a changelog entry from recent git changes and write it to CHANGELOG.md. -const changelogEntryGen = agent({ - model: "typecheck", - tools: [validateSemverBump], - instructions: p`Analyze recent changes: ${p.bash("git diff HEAD~1 HEAD --stat 2>/dev/null || true")} and ${p.bash("git log HEAD~1..HEAD --oneline 2>/dev/null || true")}. Determine the appropriate semver bump type and validate it with the validateSemverBump tool. Categorize commits into breaking changes, features, and fixes. Propose a next version and write a changelog entry to ${p.write("CHANGELOG.md", "## Unreleased\n")}. Return structured output.`, - output: s.object({ - version: s.string, - bumpType: s.enum("major", "minor", "patch"), - changes: s.object({ - breaking: s.array(s.string), - features: s.array(s.string), - fixes: s.array(s.string), - }), - written: s.boolean, - }), -}); - -export default changelogEntryGen; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts deleted file mode 100644 index 5b2acfa..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/175-todo-comment-tracker.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: scan source files for TODO/FIXME/HACK comments and write a markdown report. -const todoCommentTracker = agent({ - model: "typecheck", - instructions: p`Scan source files: ${p.bash("grep -rn 'TODO\\|FIXME\\|HACK' --include='*.ts' --include='*.js' --include='*.tsx' . 2>/dev/null || true")}. Parse each matching line to extract file path, line number, comment type (TODO/FIXME/HACK), and comment text. Write a grouped markdown report via ${p.write("todo-report.md", "# TODO Report\n")}. Return all found comments and the total count.`, - output: s.object({ - comments: s.array(s.object({ - file: s.path, - line: s.int, - type: s.enum("TODO", "FIXME", "HACK"), - text: s.string, - })), - totalCount: s.int, - reportWritten: s.boolean, - }), -}); - -export default todoCommentTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts deleted file mode 100644 index 2441183..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/176-css-variable-extractor.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const parseCssVar = defineTool("parseCssVar", { - description: "Parse a CSS custom property declaration line and extract name and value", - parameters: s.object({ line: s.string }), - handler({ line }) { - const match = line.match(/(--[\w-]+)\s*:\s*(.+?)\s*;?$/); - if (!match) return null; - return { name: match[1], value: match[2].trim() }; - }, -}); - -// Agent role: extract CSS custom properties and identify unused variables. -const cssVariableExtractor = agent({ - model: "typecheck", - tools: [parseCssVar], - instructions: p`Find CSS/SCSS files: ${p.bash("find . -name '*.css' -o -name '*.scss' 2>/dev/null | grep -v node_modules | head -20")}. Extract declarations: ${p.bash("grep -rh --include='*.css' --include='*.scss' -- '--[a-z]' . 2>/dev/null | grep -v node_modules | head -100")}. Also scan for usages: ${p.bash("grep -roh --include='*.css' --include='*.scss' --include='*.ts' --include='*.tsx' -- 'var(--[^)]+)' . 2>/dev/null | grep -o -- '--[^)]*' | sort | uniq -c | sort -rn | head -50")}. Use parseCssVar to parse each declaration line. For each variable track value and usage count. Identify unused variables (declared but never used).`, - output: s.object({ - variables: s.record(s.object({ - value: s.string, - usageCount: s.int, - })), - totalVars: s.int, - unusedVars: s.array(s.string), - }), -}); - -export default cssVariableExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts deleted file mode 100644 index 94a5fd3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/177-openapi-route-coverage.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { agent, p, s } from "rig"; -import { defineTool } from "rig"; - -const extractRoutes = defineTool("extractRoutes", { - description: "Parse grep output lines to extract route method and path from Express-style code", - parameters: s.object({ grepLine: s.string }), - handler({ grepLine }) { - const match = grepLine.match(/app\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)/i) - ?? grepLine.match(/router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)/i); - if (!match) return null; - return { method: match[1].toUpperCase(), path: match[2] }; - }, -}); - -// Agent role: compare OpenAPI spec routes with Express route handler implementations. -const openapiRouteCoverage = agent({ - model: "typecheck", - tools: [extractRoutes], - instructions: p`Read the OpenAPI spec: ${p.readOptional("openapi.json", "{}")}. Also check ${p.readOptional("openapi.yaml", "")}. Scan source for route handlers: ${p.bash("grep -rn 'app\\.get\\|app\\.post\\|app\\.put\\|app\\.delete\\|router\\.' --include='*.ts' --include='*.js' . 2>/dev/null | grep -v node_modules | head -50")}. Use the extractRoutes tool to parse each grep line. Compare defined routes (from spec) vs implemented routes (from grep). Mark each as "implemented", "missing", or "extra". Compute coveragePercent.`, - output: s.object({ - routes: s.array(s.object({ - path: s.string, - method: s.enum("GET", "POST", "PUT", "DELETE", "PATCH"), - status: s.enum("implemented", "missing", "extra"), - })), - coveragePercent: s.number, - totalDefined: s.int, - totalImplemented: s.int, - }), -}); - -export default openapiRouteCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts deleted file mode 100644 index 9b9b072..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/178-import-style-checker.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, repair } from "rig"; -import { defineTool } from "rig"; - -const classifyStyle = defineTool("classifyStyle", { - description: "Classify a JS file's module style based on require and import counts", - parameters: s.object({ requireCount: s.int, importCount: s.int }), - handler({ requireCount, importCount }) { - if (requireCount > 0 && importCount > 0) return "mixed"; - if (requireCount > 0) return "cjs"; - if (importCount > 0) return "esm"; - return "unknown"; - }, -}); - -// Agent role: classify each JavaScript file as ESM, CJS, mixed, or unknown module style. -const importStyleChecker = agent({ - model: "typecheck", - maxTurns: 3, - addons: repair(), - tools: [classifyStyle], - instructions: p`Find JS files: ${p.bash("find . -name '*.js' -not -path '*/node_modules/*' 2>/dev/null | head -30")}. For each file run both grep counts in one call: ${p.bash("find . -name '*.js' -not -path '*/node_modules/*' 2>/dev/null | head -30 | xargs -I{} sh -c 'echo {}:$(grep -c \"require(\" {} 2>/dev/null || echo 0):$(grep -c \"^import \" {} 2>/dev/null || echo 0)'")}. Use classifyStyle tool with the counts for each file. Aggregate summary counts by style.`, - output: s.object({ - files: s.record(s.object({ - style: s.enum("esm", "cjs", "mixed", "unknown"), - requireCount: s.int, - importCount: s.int, - })), - summary: s.object({ - esmCount: s.int, - cjsCount: s.int, - mixedCount: s.int, - }), - totalFiles: s.int, - }), -}); - -export default importStyleChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts deleted file mode 100644 index 12f8871..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/179-git-tag-semver-validator.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, p, s, steering } from "rig"; -import { defineTool } from "rig"; - -const parseSemver = defineTool("parseSemver", { - description: "Parse a git tag string and determine if it is valid semver", - parameters: s.object({ tag: s.string }), - handler({ tag }) { - const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/); - if (!match) return { valid: false }; - return { - valid: true, - major: parseInt(match[1], 10), - minor: parseInt(match[2], 10), - patch: parseInt(match[3], 10), - }; - }, -}); - -// Agent role: validate all git tags against semver format and identify the latest valid tag. -const gitTagSemverValidator = agent({ - model: "typecheck", - addons: steering({ message: "For tags with date-based or non-semver formats, mark valid as false and omit the parsed field." }), - tools: [parseSemver], - instructions: p`List all git tags: ${p.bash("git tag --list 2>/dev/null || true")}. For each tag, call the parseSemver tool to check if it conforms to semver (e.g. v1.2.3 or 1.2.3). Count invalid tags. Identify the latest valid semver tag by finding the highest version number.`, - output: s.object({ - tags: s.array(s.object({ - tag: s.string, - valid: s.boolean, - parsed: s.optional(s.object({ - major: s.int, - minor: s.int, - patch: s.int, - })), - })), - invalidCount: s.int, - latestValid: s.optional(s.string), - }), -}); - -export default gitTagSemverValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts deleted file mode 100644 index e72cc6a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/18-patch-writer-output.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: plan a minimal, low-risk refactor. Do not edit files. -const refactorPlan = agent({ - model: "typecheck", - output: s.object({ - steps: s.array(s.string), - files: s.array(s.string), - risks: s.array(s.string) - }), - instructions: `Plan a minimal, low-risk refactor. Do not edit files.`, -}); -export default refactorPlan; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts deleted file mode 100644 index c5a7233..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/180-git-tag-timeline-reporter.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize release details for a single git tag range. -const timelineSummarizer = agent({ - name: "timelineSummarizer", - model: "typecheck", - input: s.object({ fromTag: s.string, toTag: s.string, logOutput: s.string }), - instructions: p`Given the git log output between two tags, extract the commit count and top 3 authors.`, - output: s.object({ - commitCount: s.int, - topAuthors: s.array(s.string), - }), -}); - -// Agent role: build a release timeline from git tags and report whether unreleased commits exist. -const gitTagTimelineReporter = agent({ - model: "typecheck", - instructions: p`List all git tags sorted by date: ${p.bash("git tag --sort=creatordate 2>/dev/null || echo ''")}. For each consecutive pair of tags, examine the log: ${p.bash("git log --oneline --format='%an' $(git tag --sort=creatordate | head -2 | tail -1)..HEAD 2>/dev/null | head -20 || echo ''")}. Delegate each tag range to the timelineSummarizer subagent. Also check for unreleased commits since the latest tag using ${p.bash("git log $(git describe --tags --abbrev=0 2>/dev/null || echo '')..HEAD --oneline 2>/dev/null | wc -l || echo 0")}. Build the full timeline and return structured results.`, - output: s.object({ - timeline: s.array(s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - })), - hasUnreleasedCommits: s.boolean, - }), - agents: { timelineSummarizer }, -}); - -export default gitTagTimelineReporter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts deleted file mode 100644 index a197304..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/181-service-health-probe.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: probe each URL endpoint and classify its health status. -const serviceHealthProbe = agent({ - model: "typecheck", - addons: [steering({ message: "For any URL that times out or returns a non-standard code, classify as 'unknown' rather than failing." })], - instructions: p`Probe the comma-separated URLs in ${p.env("HEALTH_CHECK_URLS", "https://example.com,https://example.org")} using curl: ${p.bash("echo 'example: curl -o /dev/null -s -w \\'%{http_code}\\' --max-time 5 '")}. Run a separate curl command for each URL. Classify each: 'up' (2xx), 'down' (4xx/5xx/refused), 'slow' (timeout after 5s), 'unknown' (other). Count healthyCount and determine overallStatus: 'all-healthy' if all up, 'critical' if more than half are down, otherwise 'degraded'.`, - output: s.object({ - endpoints: s.array(s.object({ - url: s.url, - status: s.enum("up", "down", "slow", "unknown"), - httpCode: s.optional(s.int), - responseTimeMs: s.optional(s.int), - })), - healthyCount: s.int, - overallStatus: s.enum("all-healthy", "degraded", "critical"), - }), -}); - -export default serviceHealthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts deleted file mode 100644 index 791cf46..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/182-git-metadata-template-renderer.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const parseGitLogLine = defineTool("parseGitLogLine", { - description: "Parse a git log line in format 'HASH|AUTHOR|EMAIL|DATE|SUBJECT' into structured fields", - parameters: s.object({ line: s.string }), - handler({ line }) { - const parts = line.split("|"); - if (parts.length < 5) return null; - const [hash, author, email, date, ...subjectParts] = parts; - return { hash, author, email, date, subject: subjectParts.join("|") }; - }, -}); - -// Agent role: read a template file, fill git metadata placeholders, and write the rendered output. -const gitMetadataTemplateRenderer = agent({ - model: "typecheck", - tools: [parseGitLogLine], - instructions: p`Read the template using ${p.read("docs/commit-template.md")}. Gather recent commit metadata: ${p.bash("git log --format='%H|%an|%ae|%ai|%s' -10 2>/dev/null || echo ''")} and current branch: ${p.bash("git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown'")}. Use parseGitLogLine to parse each log line. Replace {{commit}}, {{author}}, {{branch}}, {{date}}, {{message}} placeholders in the template with actual values. Write the rendered content using ${p.writeOutput("renderedContent", "docs/commit-rendered.md")}. Return which placeholders were replaced.`, - output: s.object({ - rendered: s.boolean, - placeholdersReplaced: s.array(s.string), - outputPath: s.path, - renderedContent: s.string, - }), -}); - -export default gitMetadataTemplateRenderer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts deleted file mode 100644 index 8b460bc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/183-changelog-entry-generator.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const validateSemverBump = defineTool("validateSemverBump", { - description: "Validate and classify a semver bump type based on commit message keywords", - parameters: s.object({ commitMessages: s.string }), - handler({ commitMessages }) { - const lower = commitMessages.toLowerCase(); - if (/breaking.change|BREAKING CHANGE/i.test(commitMessages)) return "major"; - if (/^feat[:(]/m.test(lower) || /feature/i.test(lower)) return "minor"; - return "patch"; - }, -}); - -// Agent role: analyze recent git changes, determine semver bump type, and write a changelog entry. -const changelogEntryGenerator = agent({ - model: "typecheck", - tools: [validateSemverBump], - instructions: p`Analyze recent git diff: ${p.bash("git diff HEAD~1 HEAD --stat 2>/dev/null || true")} and commit log: ${p.bash("git log HEAD~1..HEAD --oneline 2>/dev/null || echo 'no commits'")}. Use validateSemverBump to determine the bump type. Categorize commits into breaking changes, features, fixes, and chores. Propose a next version string (e.g. 1.2.3). Write the changelog entry using ${p.write("CHANGELOG.md", "## [Unreleased]\n")}. Return structured results.`, - output: s.object({ - bumpType: s.enum("patch", "minor", "major"), - categories: s.object({ - breaking: s.array(s.string), - features: s.array(s.string), - fixes: s.array(s.string), - chores: s.array(s.string), - }), - entryWritten: s.boolean, - version: s.string, - }), -}); - -export default changelogEntryGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts deleted file mode 100644 index 1fdc29b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/184-todo-fixme-tracker.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: scan source files for TODO/FIXME/HACK comments and write a grouped markdown report. -const todoFixmeTracker = agent({ - model: "typecheck", - instructions: p`Scan source files for comment markers: ${p.bash("grep -rn 'TODO\\|FIXME\\|HACK' --include='*.ts' --include='*.js' --include='*.tsx' --include='*.py' . 2>/dev/null | grep -v node_modules | head -100 || echo ''")}. Parse each matching line to extract file path, line number, comment type (TODO, FIXME, or HACK), and the message text. Count occurrences by type. Write a grouped markdown report using ${p.write("todo-report.md", "# TODO/FIXME/HACK Report\n")}. Return all found items and summary counts.`, - output: s.object({ - todos: s.array(s.object({ - file: s.path, - line: s.int, - type: s.enum("TODO", "FIXME", "HACK"), - message: s.string, - })), - totalCount: s.int, - byType: s.record(s.int), - reportWritten: s.boolean, - }), -}); - -export default todoFixmeTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts deleted file mode 100644 index c120b34..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/185-multi-file-glob-summarizer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize a single TypeScript source file in one sentence. -const fileSummarizer = agent({ - name: "fileSummarizer", - model: "typecheck", - input: s.object({ filePath: s.path }), - instructions: p`Read and summarize the file: ${p.readInput("filePath")}. Return a one-sentence summary of what the file does.`, - output: s.string, -}); - -// Agent role: find TypeScript source files and delegate summarization to fileSummarizer, then aggregate results keyed by path. -const multiFileGlobSummarizer = agent({ - model: "typecheck", - instructions: p`Find TypeScript source files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -15 || echo ''")}. For each file path found, delegate to the fileSummarizer subagent passing the file path. Collect all summaries into a record keyed by file path. If no files are found, return an empty record.`, - output: s.record(s.string), - agents: { fileSummarizer }, -}); - -export default multiFileGlobSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts deleted file mode 100644 index 520b234..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/186-shell-script-analyzer.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const analyzeShellScript = defineTool("analyzeShellScript", { - description: "Read a shell script file and analyze its safety flags and shebang", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf8"); - const lines = content.split("\n"); - const shebang = lines[0]?.startsWith("#!") ? lines[0] : null; - const hasSetE = /\bset\s+-[a-z]*e/.test(content) || /\bset\s+-e\b/.test(content); - const hasSetU = /\bset\s+-[a-z]*u/.test(content) || /\bset\s+-u\b/.test(content); - const hasPipefail = /set\s+-o\s+pipefail/.test(content); - const safetyLevel = hasSetE && hasSetU && hasPipefail ? "strict" - : hasSetE || hasSetU ? "partial" - : "unsafe"; - return { shebang, hasSetE, hasSetU, hasPipefail, safetyLevel }; - } catch { - return { shebang: null, hasSetE: false, hasSetU: false, hasPipefail: false, safetyLevel: "unsafe" }; - } - }, -}); - -// Agent role: find shell scripts and analyze each for safety flag usage. -const shellScriptAnalyzer = agent({ - model: "typecheck", - tools: [analyzeShellScript], - instructions: p`Find shell scripts: ${p.bash("find . -name '*.sh' -not -path '*/node_modules/*' 2>/dev/null | head -20 || echo ''")}. For each .sh file found, call analyzeShellScript to inspect its shebang and safety flags (set -e, set -u, set -o pipefail). Return a record keyed by file path.`, - output: s.record(s.object({ - shebang: s.optional(s.string), - hasSetE: s.boolean, - hasSetU: s.boolean, - hasPipefail: s.boolean, - safetyLevel: s.enum("strict", "partial", "unsafe"), - })), -}); - -export default shellScriptAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts deleted file mode 100644 index d6a33df..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/187-lock-file-drift-detector.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const crossCheckVersions = defineTool("crossCheckVersions", { - description: "Cross-check declared package.json versions against package-lock.json resolved versions", - parameters: s.object({ packageJson: s.string, lockJson: s.string }), - handler({ packageJson, lockJson }) { - try { - const pkg = JSON.parse(packageJson); - const lock = JSON.parse(lockJson); - const declared: Record = { - ...pkg.dependencies, - ...pkg.devDependencies, - }; - const lockPackages = lock.packages || {}; - const drifted: Array<{ name: string; declared: string; locked: string; severity: string }> = []; - for (const [name, declaredVersion] of Object.entries(declared)) { - const lockEntry = lockPackages[`node_modules/${name}`]; - if (!lockEntry) continue; - const locked = lockEntry.version as string; - const declStr = String(declaredVersion).replace(/^[\^~]/, ""); - if (locked !== declStr) { - const [dMaj, dMin] = declStr.split(".").map(Number); - const [lMaj, lMin] = locked.split(".").map(Number); - const severity = lMaj !== dMaj ? "major" : lMin !== dMin ? "minor" : "patch"; - drifted.push({ name, declared: String(declaredVersion), locked, severity }); - } - } - return drifted; - } catch (e) { - return { error: String(e) }; - } - }, -}); - -// Agent role: detect version drift between package.json declarations and package-lock.json resolved versions. -const lockFileDriftDetector = agent({ - model: "typecheck", - addons: [repair()], - tools: [crossCheckVersions], - instructions: p`Read package.json: ${p.bash("cat package.json 2>/dev/null || echo '{}'")} and package-lock.json: ${p.bash("cat package-lock.json 2>/dev/null || echo '{}'")}. Call crossCheckVersions with both file contents to find drifted packages. Return driftedPackages list, total driftCount, and whether all packages are in sync.`, - output: s.object({ - driftedPackages: s.array(s.object({ - name: s.string, - declared: s.string, - locked: s.string, - severity: s.enum("patch", "minor", "major", "unknown"), - })), - driftCount: s.int, - allInSync: s.boolean, - }), -}); - -export default lockFileDriftDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts deleted file mode 100644 index c2cf93c..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/188-git-conflict-marker-scanner.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: scan the repository for git conflict markers and report affected files. -const gitConflictMarkerScanner = agent({ - model: "typecheck", - addons: [steering({ message: "Check all text file types including .ts, .js, .json, .md, .yaml. Report every line where a conflict marker appears." })], - instructions: p`Scan for git conflict markers in tracked files: ${p.bash("grep -rn '<<<<<<< \\|=======$\\|>>>>>>> ' --include='*.ts' --include='*.js' --include='*.json' --include='*.md' --include='*.yaml' --include='*.yml' . 2>/dev/null | grep -v node_modules | head -100 || echo ''")}. Also check all text files: ${p.bash("grep -rn '^<<<<<<< ' . 2>/dev/null | grep -v node_modules | grep -v '.git' | head -50 || echo ''")}. For each match, extract the file path, line number, and which marker it is. Deduplicate affected file paths. Return all conflict locations, the unique affected files list, total count, and whether the repo is clean.`, - output: s.object({ - conflicts: s.array(s.object({ - file: s.path, - line: s.int, - marker: s.enum("<<<<<<<", "=======", ">>>>>>>"), - })), - affectedFiles: s.array(s.path), - conflictCount: s.int, - isClean: s.boolean, - }), -}); - -export default gitConflictMarkerScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts deleted file mode 100644 index 84c7975..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/189-proto-field-extractor.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const extractProtoMessages = defineTool("extractProtoMessages", { - description: "Read a .proto file and extract message names with their field definitions", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf8"); - const result: Record> = {}; - const messageRegex = /message\s+(\w+)\s*\{([^}]*)\}/gs; - const fieldRegex = /^\s*(repeated\s+)?(\w+)\s+(\w+)\s*=\s*(\d+)/gm; - let msgMatch; - while ((msgMatch = messageRegex.exec(content)) !== null) { - const [, messageName, body] = msgMatch; - const fields: Array<{ fieldName: string; fieldType: string; fieldNumber: number; isRepeated: boolean }> = []; - let fieldMatch; - fieldRegex.lastIndex = 0; - while ((fieldMatch = fieldRegex.exec(body)) !== null) { - const [, repeated, fieldType, fieldName, fieldNumberStr] = fieldMatch; - fields.push({ - fieldName, - fieldType, - fieldNumber: parseInt(fieldNumberStr, 10), - isRepeated: !!repeated, - }); - } - result[messageName] = fields; - } - return result; - } catch (e) { - return { error: String(e) }; - } - }, -}); - -// Agent role: find .proto files and extract message field definitions from each. -const protoFieldExtractor = agent({ - model: "typecheck", - tools: [extractProtoMessages], - instructions: p`Find .proto files: ${p.bash("find . -name '*.proto' -not -path '*/node_modules/*' 2>/dev/null | head -20 || echo ''")}. For each .proto file found, call extractProtoMessages to parse message definitions and field lists. Merge all results into a record keyed by message name. If no .proto files exist, return an empty record.`, - output: s.record(s.array(s.object({ - fieldName: s.string, - fieldType: s.string, - fieldNumber: s.int, - isRepeated: s.boolean, - }))), -}); - -export default protoFieldExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts deleted file mode 100644 index 3cd7cef..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/19-fix-then-review.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: return a complete replacement for the target file. -const patcher = agent({ - model: "typecheck", - output: s.object({ - path: s.string, - contents: s.string, - summary: s.string - }), - instructions: `Return a complete replacement for the target file.`, -}); -export default patcher; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts deleted file mode 100644 index e67cf12..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-commit-msg-rewriter.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, steering, repair } from "rig"; - -// Agent role: rewrite recent git commit messages into conventional commit format with imperative mood. -const commitMsgRewriter = agent({ - model: "typecheck", - instructions: p`Review recent commits from ${p.bash("git log --oneline -20 2>/dev/null || echo 'no commits'")} and rewrite each message in conventional commit format with imperative mood (e.g. "Add feature" not "Added feature"). Classify each by category.`, - output: s.array(s.object({ - hash: s.string, - original: s.string, - revised: s.string, - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - })), - maxTurns: 6, - addons: [steering({ message: "Use imperative mood and conventional commit prefixes." }), repair()], -}); - -export default commitMsgRewriter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts deleted file mode 100644 index 17d643f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/190-git-tag-timeline-reporter.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize a git tag release interval into structured timeline data. -const timelineSummarizer = agent({ - model: "typecheck", - name: "timelineSummarizer", - input: s.object({ - tag: s.string, - date: s.string, - commitLog: s.string, - }), - instructions: p`Summarize the commit log for release ${p.inputField("tag")} on ${p.inputField("date")}. -Commit log: -${p.inputField("commitLog")} -Return the top authors (up to 3) and the commit count.`, - output: s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - }), -}); - -// Agent role: report git tag release timeline with commit stats between consecutive tags. -const gitTagTimelineReporter = agent({ - model: "typecheck", - instructions: p`You are a git release timeline reporter. - -List all git tags sorted by version: -${p.bash("git tag --sort=version:refname")} - -For each consecutive pair of tags, run: git log --oneline TAG1..TAG2 --format="%h %an %s" -to find commits between them. Also check for unreleased commits after the latest tag with: -${p.bash("git log --oneline $(git describe --tags --abbrev=0 2>/dev/null || echo '')..HEAD 2>/dev/null | wc -l")} - -For each tag interval, delegate to the timelineSummarizer subagent with the tag name, date, and commit log. -Aggregate all results into the output array.`, - agents: { timelineSummarizer }, - output: s.object({ - timeline: s.array(s.object({ - tag: s.string, - date: s.string, - commitCount: s.int, - topAuthors: s.array(s.string), - })), - hasUnreleasedCommits: s.boolean, - }), -}); - -export default gitTagTimelineReporter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts deleted file mode 100644 index c184a3c..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-env-key-checker.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const extractKeys = defineTool("extractKeys", { - description: "Extract KEY names from dotenv-style file content", - parameters: s.object({ content: s.string }), - handler({ content }) { - const keys = (content.match(/^([A-Z_][A-Z0-9_]*)=/gm) ?? []).map((l: string) => l.replace("=", "")); - return { keys }; - }, -}); - -// Agent role: compare .env.example required keys against .env actual keys to find missing and extra entries. -const envKeyChecker = agent({ - model: "typecheck", - instructions: p`Read required keys from ${p.readOptional(".env.example")} and present keys from ${p.readOptional(".env")}. Use extractKeys on each content. Compare to find missing (in example, not in env) and extra (in env, not in example) keys.`, - output: s.object({ - missing: s.array(s.string), - extra: s.array(s.string), - status: s.enum("complete", "partial", "empty"), - }), - tools: [extractKeys], -}); - -export default envKeyChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts deleted file mode 100644 index 1a952ba..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/191-service-health-probe.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: probe HTTP endpoints and classify their health status. -const serviceHealthProbe = agent({ - model: "typecheck", - input: s.object({ - urls: s.array(s.string), - }), - instructions: p`You are a service health probe. - -For each URL in the input list, run: curl -o /dev/null -s -w '%{http_code}' -using the command once per element. -${p.bashEach("curl -o /dev/null -s -w '%{http_code}' --max-time 5 {}", "urls")} - -Classify each endpoint: -- "up": HTTP 2xx -- "down": HTTP 5xx or connection refused -- "slow": HTTP 408 or timeout -- "unknown": anything else - -Count healthy endpoints (status "up") and set overallStatus: -- "all-healthy": all up -- "degraded": some up -- "critical": none up`, - addons: [steering({ message: "Re-check any endpoint that returned an ambiguous or unexpected status code before finalizing." })], - output: s.object({ - endpoints: s.array(s.object({ - url: s.url, - status: s.enum("up", "down", "slow", "unknown"), - httpCode: s.optional(s.int), - })), - healthyCount: s.int, - overallStatus: s.enum("all-healthy", "degraded", "critical"), - }), -}); - -export default serviceHealthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts deleted file mode 100644 index 780aa6f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-git-metadata-template-renderer.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const parseCommit = defineTool("parseCommit", { - description: "Parse a pipe-delimited git log line into structured commit fields", - parameters: s.object({ line: s.string }), - handler({ line }) { - const [hash, author, email, date, ...rest] = line.split("|"); - return { hash, author, email, date, message: rest.join("|") }; - }, -}); - -// Agent role: render a file template using git commit metadata as placeholder values. -const gitMetadataTemplateRenderer = agent({ - model: "typecheck", - input: s.object({ - templatePath: s.path, - outputPath: s.path, - }), - instructions: p`You are a git metadata template renderer. - -Template content: -${p.readInput("templatePath")} - -Current commit metadata (hash|author|email|date|message): -${p.bash("git log -1 --format=%H|%an|%ae|%aI|%s")} - -Current branch: -${p.bash("git rev-parse --abbrev-ref HEAD")} - -Use the parseCommit tool to parse the commit metadata line. -Replace all occurrences of {{commit}}, {{author}}, {{branch}}, {{date}}, {{message}} in the template with their actual values. -Count how many distinct placeholder types were replaced. -${p.writeInput("outputPath", "rendered")}`, - tools: [parseCommit], - output: s.object({ - rendered: s.string, - placeholdersFilled: s.int, - }), -}); - -export default gitMetadataTemplateRenderer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts deleted file mode 100644 index 29bbae1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/192-json-schema-migration-planner.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze structural differences between two JSON schemas and list each change. -const diffAnalyzer = agent({ - name: "diffAnalyzer", - model: "typecheck", - instructions: p`Analyze the structural differences between the two JSON schemas provided in the input and list each change with its path and whether it is a breaking change.`, - input: s.object({ oldSchema: s.string, newSchema: s.string }), - output: s.array(s.object({ - changeType: s.enum("add", "remove", "modify", "rename"), - path: s.string, - description: s.string, - breakingChange: s.boolean, - })), -}); - -// Agent role: read two JSON schema files and produce a migration plan using the diffAnalyzer subagent. -const jsonSchemaMigrationPlanner = agent({ - model: "typecheck", - input: s.object({ oldSchemaPath: s.path, newSchemaPath: s.path }), - instructions: p`Read the old schema at ${p.readInput("oldSchemaPath")} and the new schema at ${p.readInput("newSchemaPath")}. Delegate the structural diff analysis to the diffAnalyzer subagent.`, - output: s.array(s.object({ - changeType: s.enum("add", "remove", "modify", "rename"), - path: s.string, - description: s.string, - breakingChange: s.boolean, - })), - agents: { diffAnalyzer }, -}); - -export default jsonSchemaMigrationPlanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts deleted file mode 100644 index d9a6190..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-changelog-entry-generator.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const validateBumpType = defineTool("validateBumpType", { - description: "Validate that a semver bump type is major, minor, or patch", - parameters: s.object({ bumpType: s.string }), - handler: ({ bumpType }) => { const v = /^(major|minor|patch)$/.test(bumpType); return { valid: v, reason: v ? "ok" : `expected major|minor|patch, got: ${bumpType}` }; }, -}); -// Agent role: generate a structured changelog entry from the current git diff. -const changelogEntryGenerator = agent({ - model: "typecheck", - instructions: p`Generate a changelog entry from this diff: ${p.bash("git diff HEAD")} -Categorize into added, fixed, changed, breaking. Validate bumpType with validateBumpType. -Latest tag: ${p.bash("git describe --tags --abbrev=0 2>/dev/null || echo '0.0.0'")} -Write a human-readable entry in "entry". ${p.writeOutput("entry", "CHANGELOG_ENTRY.md")}`, - tools: [validateBumpType], - addons: [repair()], - output: s.object({ - entry: s.string, - version: s.string, - changes: s.object({ - added: s.array(s.string), - fixed: s.array(s.string), - changed: s.array(s.string), - breaking: s.array(s.string), - }), - bumpType: s.enum("major", "minor", "patch"), - }), -}); -export default changelogEntryGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts deleted file mode 100644 index 68ae20a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/193-dockerfile-security-auditor.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const RULES = [ - { re: /^USER\s+root\s*$/im, sev: "critical", pattern: "root USER", suggestion: "Use a non-root user" }, - { re: /^ADD\s+(?!https?:\/\/)/m, sev: "medium", pattern: "ADD for local files", suggestion: "Use COPY instead of ADD" }, - { re: /:latest/, sev: "high", pattern: ":latest tag", suggestion: "Pin to a specific image version" }, - { re: /ENV\s+\w*(SECRET|PASSWORD|TOKEN|KEY)\w*\s*=/, sev: "critical", pattern: "secret in ENV", suggestion: "Use build args or secrets" }, -]; -const auditPatterns = defineTool("auditPatterns", { - description: "Check a Dockerfile line for known insecure patterns", - parameters: s.object({ line: s.string, lineNumber: s.int }), - handler: ({ line, lineNumber }) => ({ - lineNumber, - findings: RULES.filter(r => r.re.test(line)).map(({ sev: severity, pattern, suggestion }) => ({ severity, pattern, suggestion })), - }), -}); -// Agent role: audit a Dockerfile for security anti-patterns and produce a severity-ranked findings report. -const dockerfileSecurityAuditor = agent({ - model: "typecheck", - instructions: p`Read the Dockerfile: ${p.readOptional("Dockerfile", "# no Dockerfile")}. Use auditPatterns on each instruction line to detect security issues. Compute an overall score from 0–100 (100 = no issues).`, - output: s.object({ - findings: s.array(s.object({ line: s.int, pattern: s.string, severity: s.enum("low", "medium", "high", "critical"), suggestion: s.string })), - passes: s.boolean, - score: s.int, - }), - tools: [auditPatterns], -}); -export default dockerfileSecurityAuditor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts deleted file mode 100644 index d1a780a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-npm-audit-simplifier.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: run npm audit and produce a simplified grouped vulnerability report with remediation advice. -const npmAuditSimplifier = agent({ - model: "typecheck", - instructions: p`Run ${p.bash("npm audit --json 2>/dev/null || echo '{}'")} to get the vulnerability report. Parse the JSON, group vulnerability package names by severity level, count totals, and provide a concise remediation recommendation.`, - output: s.object({ - vulnerabilitiesByLevel: s.record(s.array(s.string)), - totalCount: s.number, - recommendation: s.string, - }), - maxTurns: 5, - addons: repair(), -}); - -export default npmAuditSimplifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts deleted file mode 100644 index 4277ee8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/194-todo-fixme-tracker.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const classifyComment = defineTool("classifyComment", { - description: "Classify a source code comment line by marker type and whether it has an owner", - parameters: s.object({ line: s.string }), - handler({ line }) { - const match = line.match(/\b(TODO|FIXME|HACK|XXX)\b/); - const type = (match?.[1] ?? "TODO") as "TODO" | "FIXME" | "HACK" | "XXX"; - const hasOwner = /\([\w.@-]+\)/.test(line); - return { type, hasOwner }; - }, -}); - -// Agent role: scan source files for TODO/FIXME/HACK/XXX comments and produce a structured report. -const todoFixmeTracker = agent({ - model: "typecheck", - instructions: p`You are a TODO/FIXME/HACK/XXX comment tracker. - -Scan TypeScript and JavaScript source files for comment markers: -${p.bash("grep -rn 'TODO\\|FIXME\\|HACK\\|XXX' --include='*.ts' --include='*.js' . 2>/dev/null | grep -v node_modules || true")} - -For each matching line, use the classifyComment tool to determine the type and whether it names an owner. -Collect all items and compute totalCount and byType counts. -Write a markdown summary in the "report" field. -${p.writeOutput("report", "TODO_REPORT.md")}`, - tools: [classifyComment], - output: s.object({ - report: s.string, - items: s.array(s.object({ - file: s.path, - line: s.int, - type: s.enum("TODO", "FIXME", "HACK", "XXX"), - text: s.string, - })), - totalCount: s.int, - byType: s.record(s.int), - }), -}); - -export default todoFixmeTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts deleted file mode 100644 index 8df27cf..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-git-stash-inventory.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: inventory all git stashes, listing changed files and classifying staleness. -const gitStashInventory = agent({ - model: "typecheck", - instructions: p`List all stashes: ${p.bash("git stash list 2>/dev/null || echo 'no stashes'")}. For each stash ref, show changed files: ${p.bash("git stash show --name-only 2>/dev/null || true")}. Classify staleness: fresh (< 1 week), aging (1–4 weeks), stale (1–3 months), ancient (> 3 months).`, - output: s.array(s.object({ - stashRef: s.string, - description: s.string, - changedFiles: s.array(s.string), - staleness: s.enum("fresh", "aging", "stale", "ancient"), - })), -}); - -export default gitStashInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts deleted file mode 100644 index e7a2acf..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/195-multi-file-glob-summarizer.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize a single TypeScript file's purpose and exports. -const fileSummarizer = agent({ - model: "typecheck", - name: "fileSummarizer", - input: s.object({ path: s.path }), - instructions: p`Summarize the following TypeScript file. - -File contents: -${p.readInput("path")} - -Return a one-sentence summary, the number of lines, and whether the file has any exports.`, - output: s.object({ - summary: s.string, - lineCount: s.int, - hasExports: s.boolean, - }), -}); - -// Agent role: discover TypeScript files in the workspace and summarize each via a subagent. -const multiFileGlobSummarizer = agent({ - model: "typecheck", - instructions: p`You are a multi-file TypeScript summarizer. - -Discovered TypeScript files (excluding node_modules): -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*'")} - -For each file path, delegate to the fileSummarizer subagent, passing the file path as input. -Aggregate all results into a record keyed by file path.`, - agents: { fileSummarizer }, - output: s.record(s.object({ - summary: s.string, - lineCount: s.int, - hasExports: s.boolean, - })), -}); - -export default multiFileGlobSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts deleted file mode 100644 index 4b132f6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-git-remote-inspector.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const parseRemoteLine = defineTool("parseRemoteLine", { - description: "Parse a git remote -v output line into name, url, type, and protocol", - parameters: s.object({ line: s.string }), - handler({ line }) { - const parts = line.split(/\s+/); - const name = parts[0] ?? ""; - const url = parts[1] ?? ""; - const raw = parts[2] ?? ""; - const type: "fetch" | "push" = raw.includes("push") ? "push" : "fetch"; - let protocol: "https" | "ssh" | "git" | "unknown" = "unknown"; - if (url.startsWith("https://")) protocol = "https"; - else if (url.startsWith("git@") || url.startsWith("ssh://")) protocol = "ssh"; - else if (url.startsWith("git://")) protocol = "git"; - return { name, url, type, protocol }; - }, -}); - -// Agent role: inspect git remotes and report their URLs, protocols, and remote branch count. -const gitRemoteInspector = agent({ - model: "typecheck", - instructions: p`You are a git remote inspector. - -Git remotes: -${p.bash("git remote -v")} - -Remote branch count (origin): -${p.bash("git ls-remote --heads origin 2>/dev/null | wc -l")} - -For each non-empty line in the remote output, use the parseRemoteLine tool. -Deduplicate entries that share the same name. -Report whether a remote named "origin" exists and the total remote branch count.`, - tools: [parseRemoteLine], - addons: [repair()], - output: s.object({ - remotes: s.array(s.object({ - name: s.string, - url: s.url, - type: s.enum("fetch", "push"), - protocol: s.enum("https", "ssh", "git", "unknown"), - })), - remoteBranchCount: s.int, - hasOrigin: s.boolean, - }), -}); - -export default gitRemoteInspector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts deleted file mode 100644 index 4a645d2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/196-http-endpoint-health-checker.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const checkEndpoint = defineTool("checkEndpoint", { - description: "Probe an HTTP endpoint and return the status code and latency", - parameters: s.object({ url: s.url }), - async handler({ url }) { - const { execSync } = await import("node:child_process"); - const start = Date.now(); - try { - const code = execSync( - `curl -o /dev/null -s -w '%{http_code}' --max-time 5 "${url}"`, - { encoding: "utf8" }, - ).trim(); - return { statusCode: parseInt(code, 10), latencyMs: Date.now() - start }; - } catch { - return { statusCode: 0, latencyMs: Date.now() - start }; - } - }, -}); - -// Agent role: probe each supplied HTTP endpoint and classify its health status. -const httpEndpointHealthChecker = agent({ - model: "typecheck", - input: s.object({ endpoints: s.array(s.url) }), - instructions: p`For each URL in ${p.inputField("endpoints")}, call checkEndpoint to get the HTTP status code. Classify: ok (2xx), redirect (3xx), client-error (4xx), server-error (5xx), timeout (0 with latency >= 5000), unreachable (0 with low latency).`, - output: s.object({ - results: s.array(s.object({ - url: s.url, - statusCode: s.int, - status: s.enum("ok", "redirect", "client-error", "server-error", "timeout", "unreachable"), - latencyMs: s.optional(s.int), - })), - healthyCount: s.int, - totalCount: s.int, - allHealthy: s.boolean, - }), - tools: [checkEndpoint], - maxTurns: 5, - addons: repair(), -}); - -export default httpEndpointHealthChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts deleted file mode 100644 index d924fcd..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-git-blame-ownership.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const parseBlameOutput = defineTool("parseBlameOutput", { - description: "Parse git blame --line-porcelain output to compute per-author line counts", - parameters: s.object({ blameText: s.string }), - handler({ blameText }) { - const authorCounts: Record = {}; - let totalLines = 0; - for (const match of blameText.matchAll(/^author (.+)$/gm)) { - const author = match[1].trim(); - authorCounts[author] = (authorCounts[author] ?? 0) + 1; - totalLines++; - } - return { authorCounts, totalLines }; - }, -}); - -// Agent role: analyze git blame for a file to report per-author line ownership. -const gitBlameOwnership = agent({ - model: "typecheck", - input: s.object({ filePath: s.path }), - instructions: p`Run git blame on the file: ${p.bash("git blame --line-porcelain HEAD -- . 2>/dev/null | head -500 || echo ''")}. Use parseBlameOutput on the porcelain output. Compute per-author percentage from line counts. Identify the top author.`, - output: s.object({ - authors: s.record(s.object({ - lineCount: s.int, - percentage: s.number, - firstLine: s.optional(s.int), - lastLine: s.optional(s.int), - })), - topAuthor: s.string, - totalLines: s.int, - }), - tools: [parseBlameOutput], - addons: steering({ message: "Ensure percentages sum to 100 and totalLines matches the sum of all line counts." }), -}); - -export default gitBlameOwnership; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts deleted file mode 100644 index ee0629e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/197-ts-enum-extractor.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; -import { readFile } from "node:fs/promises"; - -const extractEnumValues = defineTool("extractEnumValues", { - description: "Extract all member names and values from a TypeScript enum in a source file", - parameters: s.object({ filePath: s.string, enumName: s.string }), - async handler({ filePath, enumName }) { - const source = await readFile(filePath, "utf8"); - const constMatch = new RegExp(`(const\\s+)?enum\\s+${enumName}\\s*\\{([^}]*)\\}`, "s").exec(source); - if (!constMatch) return { members: [], isConst: false, memberCount: 0 }; - const isConst = Boolean(constMatch[1]); - const body = constMatch[2]; - const members = [...body.matchAll(/(\w+)\s*(?:=\s*([^,\n]+))?/g)].map((m) => ({ - name: m[1], - value: m[2]?.trim() ?? undefined, - })); - return { members, isConst, memberCount: members.length }; - }, -}); - -// Agent role: find all TypeScript enum declarations and extract their members and values. -const tsEnumExtractor = agent({ - model: "typecheck", - instructions: p`You are a TypeScript enum extractor. - -Find TypeScript files with enum declarations: -${p.bash("grep -rn 'enum ' --include='*.ts' . 2>/dev/null | grep -v node_modules || true")} - -For each unique (file, enumName) pair found, use the extractEnumValues tool. -Aggregate results into a record keyed by enum name (append "@filepath" if the same name appears in multiple files).`, - tools: [extractEnumValues], - addons: [steering({ message: "Ensure every file from the grep output is scanned before finalizing." })], - output: s.record(s.object({ - members: s.array(s.object({ name: s.string, value: s.optional(s.string) })), - isConst: s.boolean, - memberCount: s.int, - })), -}); - -export default tsEnumExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts deleted file mode 100644 index f3c7210..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-json-config-merger.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const readJsonFile = defineTool("readJsonFile", { - description: "Read and parse a JSON file from the given path", - parameters: s.object({ path: s.string }), - async handler({ path }) { - const text = await readFile(path, "utf8"); - return JSON.parse(text); - }, -}); - -const mergeObjects = defineTool("mergeObjects", { - description: "Shallow-merge an override object into a base object", - parameters: s.object({ base: s.unknown, override: s.unknown }), - handler({ base, override }) { - const b = base as Record; - const o = override as Record; - let keysAdded = 0; - let keysOverridden = 0; - const result = { ...b }; - for (const [k, v] of Object.entries(o)) { - if (k in result) keysOverridden++; - else keysAdded++; - result[k] = v; - } - return { merged: JSON.stringify(result, null, 2), keysAdded, keysOverridden, totalKeys: Object.keys(result).length }; - }, -}); - -// Agent role: merge two JSON config files and write the combined result to an output path. -const jsonConfigMerger = agent({ - model: "typecheck", - input: s.object({ - baseConfig: s.path, - overrideConfig: s.path, - outputPath: s.path, - }), - instructions: p`You are a JSON config merger. - -Base config file contents: -${p.readInput("baseConfig")} - -Use the readJsonFile tool to read the override config at input.overrideConfig. -Use the mergeObjects tool to merge the override into the base. -The merged field from the tool result is already a JSON string — use it as the output "merged" value. -${p.writeInput("outputPath", "merged")}`, - tools: [readJsonFile, mergeObjects], - addons: [repair()], - output: s.object({ - merged: s.string, - keysAdded: s.int, - keysOverridden: s.int, - totalKeys: s.int, - }), -}); - -export default jsonConfigMerger; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts deleted file mode 100644 index aba320e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/198-ts-generic-type-extractor.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const extractGenerics = defineTool("extractGenerics", { - description: "Extract TypeScript generic type parameters from a source file", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - const content = await readFile(filePath, "utf8").catch(() => ""); - const matches = content.match(/<[A-Z][A-Za-z]*(?:,\s*[A-Z][A-Za-z]*)*>/g) ?? []; - return { generics: [...new Set(matches)], count: matches.length }; - }, -}); - -// Agent role: scan TypeScript files for generic type parameters and classify complexity. -const tsGenericTypeExtractor = agent({ - model: "typecheck", - instructions: p`Find all TypeScript files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' 2>/dev/null | head -50")}. For each file, use extractGenerics to find generic type parameters. Classify complexity: none (0 generics), simple (1–2), moderate (3–5), complex (6+).`, - output: s.record(s.object({ - generics: s.array(s.string), - count: s.int, - complexity: s.enum("none", "simple", "moderate", "complex"), - })), - tools: [extractGenerics], - maxTurns: 5, - addons: repair(), -}); - -export default tsGenericTypeExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts deleted file mode 100644 index 14aeb4d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-shell-script-validator.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const validateScript = defineTool("validateScript", { - description: "Validate a shell script for safety flags and structure", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - const content = await readFile(filePath, "utf8").catch(() => ""); - const lines = content.split("\n"); - const hasShebang = lines[0]?.startsWith("#!"); - const hasSafeFlags = /set\s+-[^#]*e/.test(content) && /set\s+-[^#]*u/.test(content); - const hasEval = /\beval\b/.test(content); - const functionCount = (content.match(/^\s*(function\s+\w+|\w+\s*\(\s*\))/gm) ?? []).length; - return { hasShebang, hasSafeFlags, hasEval, functionCount }; - }, -}); - -// Agent role: validate shell scripts for safety flags and classify quality. -const shellScriptValidator = agent({ - model: "typecheck", - instructions: p`Find all shell scripts: ${p.bash("find . -name '*.sh' -not -path '*/node_modules/*' 2>/dev/null | head -30")}. Use validateScript on each file. Classify quality: excellent (shebang + safe flags + no eval), good (shebang + safe flags), fair (shebang only), poor (no shebang).`, - output: s.record(s.object({ - hasShebang: s.boolean, - hasSafeFlags: s.boolean, - hasEval: s.boolean, - functionCount: s.int, - quality: s.enum("excellent", "good", "fair", "poor"), - })), - tools: [validateScript], - addons: steering({ message: "Classify every found script. If no scripts are found, return an empty record." }), -}); - -export default shellScriptValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts deleted file mode 100644 index 2ec1ed6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/199-source-complexity-heatmap.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; - -const classifyComplexity = defineTool("classifyComplexity", { - description: "Classify a file's complexity tier based on its line count", - parameters: s.object({ lineCount: s.int }), - handler({ lineCount }) { - if (lineCount < 50) return { tier: "trivial" as const }; - if (lineCount < 150) return { tier: "small" as const }; - if (lineCount < 300) return { tier: "medium" as const }; - if (lineCount < 600) return { tier: "large" as const }; - return { tier: "huge" as const }; - }, -}); - -// Agent role: analyze TypeScript source files by line count and classify their complexity. -const sourceComplexityHeatmap = agent({ - model: "typecheck", - instructions: p`You are a source complexity heatmap generator. - -TypeScript source file line counts (sorted descending): -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | xargs wc -l 2>/dev/null | sort -rn | grep -v total || true")} - -For each file (skip the "total" summary line), use the classifyComplexity tool to assign a tier. -Build a record keyed by file path with lineCount and tier. -List hotspot files (tier "large" or "huge") as an array. -Sum all line counts for totalLines and name the single largest file as largestFile.`, - tools: [classifyComplexity], - addons: [steering({ message: "Ensure every file in the wc output is represented before finalizing." })], - output: s.object({ - files: s.record(s.object({ - lineCount: s.int, - tier: s.enum("trivial", "small", "medium", "large", "huge"), - })), - hotspots: s.array(s.path), - totalLines: s.int, - largestFile: s.path, - }), -}); - -export default sourceComplexityHeatmap; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts deleted file mode 100644 index 0cc6746..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/20-issue-reproducer.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, p, s } from "rig"; -const Diagnosis = s.object({ rootCause: s.string, confidence: s.number }); -// Agent role: diagnose the failing test output. -const diagnose = agent({ model: "typecheck", output: Diagnosis, instructions: "Diagnose the failing test output." }); -// Agent role: write the smallest safe patch for the diagnosis. -const fix = agent({ model: "typecheck", input: s.object({ diagnosis: Diagnosis }), instructions: "Write the smallest safe patch." }); -// Agent role: reproduce and fix the bug using the provided specialists when helpful. -const issueReproducer = agent({ - model: "typecheck", - instructions: p`Reproduce the failing test from ${p.bash("npm test")} and use the specialists when helpful.`, - output: s.object({ diagnosis: Diagnosis, fixSummary: s.string, approved: s.boolean }), - agents: { diagnose, fix }, -}); -export default issueReproducer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts deleted file mode 100644 index 8458982..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/200-npm-audit-simplifier.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: run npm audit and produce a simplified grouped vulnerability report with remediation advice. -const npmAuditSimplifierV2 = agent({ - model: "typecheck", - instructions: p`Run ${p.bash("npm audit --json 2>/dev/null || echo '{}'")} to get the vulnerability report. Parse the JSON output: extract each vulnerability's package name and severity (critical, high, moderate, low, info). Group package names by severity level into the vulnerabilitiesByLevel map. Count all vulnerabilities for totalCount. Write a one-sentence recommendation.`, - output: s.object({ - vulnerabilitiesByLevel: s.record(s.array(s.string)), - totalCount: s.number, - recommendation: s.string, - }), - maxTurns: 5, - addons: repair(), -}); - -export default npmAuditSimplifierV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts deleted file mode 100644 index ec415bb..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/201-git-stash-inventory.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: inventory all git stashes, listing changed files and estimating staleness. -const gitStashInventoryV2 = agent({ - model: "typecheck", - instructions: p`List all stashes with timestamps: ${p.bash("git stash list --format='%gd|%ci|%s' 2>/dev/null || echo 'no stashes'")}. For the first three stashes show changed files: ${p.bash("git stash show --name-only stash@{0} 2>/dev/null || true")} ${p.bash("git stash show --name-only stash@{1} 2>/dev/null || true")} ${p.bash("git stash show --name-only stash@{2} 2>/dev/null || true")}. Classify staleness by commit date: fresh (< 1 week), aging (1–4 weeks), stale (1–3 months), ancient (> 3 months).`, - output: s.array(s.object({ - stashRef: s.string, - description: s.string, - changedFiles: s.array(s.string), - staleness: s.enum("fresh", "aging", "stale", "ancient"), - })), - maxTurns: 5, - addons: repair(), -}); - -export default gitStashInventoryV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts deleted file mode 100644 index fd3fb92..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/202-ts-interface-conflict-checker.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const scanInterfaces = defineTool("scanInterfaces", { - description: "Scan a TypeScript file for exported interface names using grep", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { execSync } = await import("node:child_process"); - try { - const result = execSync( - `grep -n "^export interface\\|^interface " "${filePath}" 2>/dev/null || true`, - { encoding: "utf8" } - ); - const names = result - .split("\n") - .filter(Boolean) - .map((line) => { - const m = line.match(/interface\s+(\w+)/); - return m ? m[1] : null; - }) - .filter(Boolean) as string[]; - return { filePath, names }; - } catch { - return { filePath, names: [] }; - } - }, -}); - -// Agent role: find duplicate TypeScript interface names across all source files. -const tsInterfaceConflictCheckerV2 = agent({ - model: "typecheck", - instructions: p`Discover TypeScript source files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -80")}. Use the scanInterfaces tool on each file to collect interface names. Identify interface names declared in more than one file. Classify each conflict as error when names are likely to clash at runtime, warning otherwise. Set hasConflicts to true if any conflicts exist.`, - output: s.object({ - conflicts: s.array(s.object({ - interfaceName: s.string, - files: s.array(s.string), - severity: s.enum("warning", "error"), - })), - hasConflicts: s.boolean, - }), - tools: [scanInterfaces], - maxTurns: 6, - addons: repair(), -}); - -export default tsInterfaceConflictCheckerV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts deleted file mode 100644 index c214063..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/203-git-worktree-mapper.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parseWorktreePorcelain = defineTool("parseWorktreePorcelain", { - description: "Parse the porcelain output of git worktree list into structured entries", - parameters: s.object({ output: s.string }), - handler({ output }) { - const entries: Array<{ path: string; branch?: string; state: string }> = []; - const blocks = output.trim().split("\n\n"); - for (const block of blocks) { - const lines = block.split("\n"); - const pathLine = lines.find((l) => l.startsWith("worktree ")); - const branchLine = lines.find((l) => l.startsWith("branch ")); - const isLocked = lines.some((l) => l.startsWith("locked")); - const isBare = lines.some((l) => l.startsWith("bare")); - const entry: { path: string; branch?: string; state: string } = { - path: pathLine ? pathLine.replace("worktree ", "") : "", - state: isLocked ? "locked" : isBare ? "bare" : "clean", - }; - if (branchLine) entry.branch = branchLine.replace("branch refs/heads/", ""); - if (entry.path) entries.push(entry); - } - return entries; - }, -}); - -// Agent role: map all git worktrees and summarize active vs total count. -const gitWorktreeMapperV2 = agent({ - model: "typecheck", - instructions: p`Get all git worktrees: ${p.bash("git worktree list --porcelain 2>/dev/null || echo ''")}. Use the parseWorktreePorcelain tool to parse the output into structured entries. For each worktree check if there are uncommitted changes (set state to dirty). Count all worktrees for totalCount and non-bare ones for activeCount.`, - output: s.object({ - worktrees: s.array(s.object({ - path: s.string, - branch: s.optional(s.string), - state: s.enum("locked", "bare", "clean", "dirty"), - })), - summary: s.object({ - totalCount: s.int, - activeCount: s.int, - }), - }), - tools: [parseWorktreePorcelain], -}); - -export default gitWorktreeMapperV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts deleted file mode 100644 index d3d7e5b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/204-test-naming-enforcer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: audit test file naming conventions and report files that violate the standard pattern. -const testNamingEnforcerV2 = agent({ - model: "typecheck", - instructions: p`Find all test files: ${p.bash("find . \\( -name '*.test.ts' -o -name '*.spec.ts' -o -name '*.test.js' -o -name '*.spec.js' -o -name '*.test.tsx' -o -name '*.spec.tsx' \\) -not -path '*/node_modules/*' | head -80")}. For each file classify the naming convention: correct if the filename follows .test. or .spec., wrong-prefix if the prefix before the dot is unusual, wrong-suffix if the extension or suffix is non-standard, missing-spec if the file appears to be a test but lacks a .test. or .spec. marker. Provide suggestedName only when a correction is needed. Set allConform to true only when every file is classified as correct.`, - output: s.object({ - files: s.record(s.object({ - convention: s.enum("correct", "wrong-prefix", "wrong-suffix", "missing-spec"), - suggestedName: s.optional(s.string), - })), - allConform: s.boolean, - }), - maxTurns: 5, - addons: steering({ message: "Ensure every discovered test file has an entry and allConform reflects all entries." }), -}); - -export default testNamingEnforcerV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts deleted file mode 100644 index de992a3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/205-pkg-dependency-graph.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyDependency = defineTool("classifyDependency", { - description: "Classify a dependency as runtime, dev, or peer based on presence in package.json sections", - parameters: s.object({ - name: s.string, - inDependencies: s.boolean, - inDevDependencies: s.boolean, - inPeerDependencies: s.boolean, - }), - handler({ inDependencies, inDevDependencies, inPeerDependencies }) { - if (inPeerDependencies) return "peer"; - if (inDevDependencies) return "dev"; - if (inDependencies) return "runtime"; - return "dev"; - }, -}); - -// Agent role: extract and classify direct dependencies from package.json and describe the dependency tree shape. -const pkgDependencyGraphV2 = agent({ - model: "typecheck", - instructions: p`Read the project manifest: ${p.read("package.json")}. Get the resolved dependency tree: ${p.bash("npm ls --json --depth=1 2>/dev/null || echo '{}'")}. Use the classifyDependency tool for each direct dependency. List all devDependency names. Classify treeShape as flat (< 5 total deps), shallow (5–20), or deep (> 20). Set depthScore to the total direct dependency count.`, - output: s.object({ - directDeps: s.array(s.object({ - name: s.string, - version: s.string, - type: s.enum("runtime", "dev", "peer"), - })), - devDeps: s.array(s.string), - treeShape: s.enum("flat", "shallow", "deep"), - depthScore: s.number, - }), - tools: [classifyDependency], -}); - -export default pkgDependencyGraphV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts deleted file mode 100644 index 634fc89..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/206-ci-flake-triager.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: triage the most recent CI test failure and classify its root cause. -const ciFlakeTriager = agent({ - model: "typecheck", - instructions: p`Inspect available CI logs: ${p.bash("cat .github/test-results.log 2>/dev/null || cat test-results.log 2>/dev/null || echo 'no test log found'")}. Also read the CI workflow configuration: ${p.readOptional(".github/workflows/ci.yml", "no ci workflow found")}. Classify the failure type: infrastructure (runner issue, network, timeout on setup), assertion (test logic failed), timeout (test exceeded time limit), or unknown. Estimate confidence. List the names of affected tests if identifiable. Provide a concrete one-sentence retry advice.`, - output: s.object({ - failureClass: s.enum("infrastructure", "assertion", "timeout", "unknown"), - confidence: s.enum("high", "medium", "low"), - retryAdvice: s.string, - affectedTests: s.array(s.string), - }), - maxTurns: 4, - addons: repair(), -}); - -export default ciFlakeTriager; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts deleted file mode 100644 index d7648c4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/207-config-drift-reconciler.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: compare two config files, identify drifted settings, and write a corrected patch. -const configDriftReconciler = agent({ - model: "typecheck", - instructions: p`Read the baseline ESLint config: ${p.readOptional(".eslintrc.json", "{}")}. Read the active config: ${p.readOptional(".eslintrc.js", "module.exports = {}")}. Also check for any local overrides: ${p.bash("find . -maxdepth 2 -name '.eslintrc*' -not -path '*/node_modules/*' 2>/dev/null || true")}. Identify keys that differ between the baseline and active configs. Write a normalized patch to ${p.write("config-patch.json", "PATCH_CONTENT")} showing the corrected settings. Report each drifted key with its baseline and actual value. Set normalized to true if you were able to resolve all differences.`, - output: s.object({ - changedKeys: s.record(s.object({ - baseline: s.unknown, - actual: s.unknown, - })), - summary: s.object({ - totalDrifted: s.int, - totalChecked: s.int, - normalized: s.boolean, - }), - }), -}); - -export default configDriftReconciler; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts deleted file mode 100644 index 9df61e3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/208-release-note-enricher.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s, defineTool, repair, steering } from "rig"; - -const lookupTicketMetadata = defineTool("lookupTicketMetadata", { - description: "Extract ticket references like #123 or PROJ-456 from text", - parameters: s.object({ text: s.string }), - handler({ text }) { - const githubRefs = [...text.matchAll(/#(\d+)/g)].map((m) => `#${m[1]}`); - const jiraRefs = [...text.matchAll(/\b([A-Z]+-\d+)\b/g)].map((m) => m[1]); - return { githubRefs, jiraRefs, all: [...githubRefs, ...jiraRefs] }; - }, -}); - -// Agent role: enrich raw release notes with structured sections, a risk label, and missing reference warnings. -const releaseNoteEnricher = agent({ - model: "typecheck", - input: s.object({ - rawNotes: s.string, - }), - instructions: p`You have raw release notes in the input. Use the lookupTicketMetadata tool to extract any ticket references from the text. Group the notes into logical sections (e.g., Features, Bug Fixes, Breaking Changes, Chores). Assign a riskLabel of low, medium, high, or critical based on whether there are breaking changes or critical fixes. List any ticket references that appear in the notes but could not be resolved or verified.`, - output: s.object({ - sections: s.array(s.object({ - heading: s.string, - items: s.array(s.string), - })), - riskLabel: s.enum("low", "medium", "high", "critical"), - missingReferences: s.array(s.string), - }), - tools: [lookupTicketMetadata], - maxTurns: 5, - addons: [steering(), repair()], -}); - -export default releaseNoteEnricher; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts deleted file mode 100644 index 03860c0..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/209-docs-refactor-coordinator.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: extract API names mentioned in the documentation. -const apiExtractor = agent({ - name: "apiExtractor", - model: "typecheck", - instructions: p`Read the documentation: ${p.read("README.md")}. Extract every API name, function signature, and method reference mentioned in the document. Return a flat list of unique API identifiers.`, - output: s.array(s.string), -}); - -// Agent role: rewrite documentation prose for clarity and conciseness. -const proseCleanup = agent({ - name: "proseCleanup", - model: "typecheck", - instructions: p`Read the documentation: ${p.read("README.md")}. Rewrite the prose to be clearer, more concise, and better structured. Return only the improved text.`, - output: s.string, -}); - -// Agent role: coordinate docs refactoring by extracting APIs and cleaning prose, then writing the result. -const docsRefactorCoordinator = agent({ - model: "typecheck", - instructions: p`Delegate API extraction and prose cleanup to the named subagents. Merge their results: the apiExtractor returns the list of API names, and proseCleanup returns rewritten prose. Combine into a final output and write the refactored content to ${p.write("docs/refactored.md", "REFACTORED_CONTENT")}. Count the changes made to the prose.`, - output: s.object({ - extractedApis: s.array(s.string), - changesApplied: s.int, - outputPath: s.path, - }), - agents: { apiExtractor, proseCleanup }, -}); - -export default docsRefactorCoordinator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts deleted file mode 100644 index b1c373f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/21-ci-log-diagnosis.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: extract a clear reproduction from the issue. -const reproducer = agent({ - model: "typecheck", - output: s.object({ - steps: s.array(s.string), - expected: s.string, - actual: s.string, - missingInfo: s.array(s.string) - }), - instructions: `Extract a clear reproduction from the issue.`, -}); - -export default reproducer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts deleted file mode 100644 index f7f8f69..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/210-test-file-naming-enforcer.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const classifyFile = defineTool("classifyFile", { - description: "Classify a test filename against project naming conventions", - parameters: s.object({ - filename: s.string, - }), - handler({ filename }) { - const base = filename.split("/").pop() ?? filename; - if (/\.(test|spec)\.(ts|js|tsx|jsx)$/.test(base)) { - return { convention: "correct" as const, suggestedName: null }; - } - if (/\.(ts|js|tsx|jsx)$/.test(base) && /test|spec/i.test(base)) { - return { convention: "wrong-suffix" as const, suggestedName: base.replace(/test|spec/i, "") + ".test." + base.split(".").pop() }; - } - if (/Test\.(ts|js|tsx|jsx)$/.test(base)) { - return { convention: "wrong-suffix" as const, suggestedName: base.replace(/Test\./, ".test.") }; - } - return { convention: "missing-spec" as const, suggestedName: base.replace(/\.(ts|js|tsx|jsx)$/, ".test.$1") }; - }, -}); - -// Agent role: scan test files and report which follow the .test.ts / .spec.ts naming convention. -const testFileNamingEnforcer = agent({ - model: "typecheck", - instructions: p`Find all test files: ${p.bash("find . \\( -name '*.test.ts' -o -name '*.spec.ts' -o -name '*.test.js' -o -name '*.spec.js' -o -name '*Test.ts' -o -name '*Test.js' \\) -not -path '*/node_modules/*' | head -60")}. Use the classifyFile tool for each file path. Build a record keyed by file path with the convention classification and optional suggestedName. Set allConform to true only when every entry is classified as correct.`, - output: s.object({ - files: s.record(s.object({ - convention: s.enum("correct", "wrong-prefix", "wrong-suffix", "missing-spec"), - suggestedName: s.optional(s.string), - })), - allConform: s.boolean, - }), - tools: [classifyFile], - maxTurns: 5, - addons: repair(), -}); - -export default testFileNamingEnforcer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts deleted file mode 100644 index 40698dc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/211-pkg-dependency-graph-extractor.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyDependency = defineTool("classifyDependency", { - description: "Classify a dependency as runtime, dev, or peer given its presence in package.json sections", - parameters: s.object({ - name: s.string, - inDependencies: s.boolean, - inDevDependencies: s.boolean, - inPeerDependencies: s.boolean, - }), - handler({ inDependencies, inDevDependencies, inPeerDependencies }) { - if (inPeerDependencies) return "peer"; - if (inDevDependencies) return "dev"; - if (inDependencies) return "runtime"; - return "dev"; - }, -}); - -// Agent role: extract and classify direct dependencies from package.json and describe the dependency tree shape. -const pkgDependencyGraphExtractor = agent({ - model: "typecheck", - instructions: p`Read the project manifest: ${p.read("package.json")}. Get the resolved dependency tree: ${p.bash("npm ls --json --depth=1 2>/dev/null || echo '{}'")}. Use the classifyDependency tool for each direct dependency found in the manifest. List all devDependency names as plain strings. Classify treeShape as flat (fewer than 5 total direct deps), shallow (5–20), or deep (more than 20). Set depthScore to the total direct dependency count across all sections.`, - output: s.object({ - directDeps: s.array(s.object({ - name: s.string, - version: s.string, - type: s.enum("runtime", "dev", "peer"), - })), - devDeps: s.array(s.string), - treeShape: s.enum("flat", "shallow", "deep"), - depthScore: s.number, - }), - tools: [classifyDependency], -}); - -export default pkgDependencyGraphExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts deleted file mode 100644 index b924842..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/212-ts-export-usage-counter.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const countUsages = defineTool("countUsages", { - description: "Count how many times a symbol appears in TypeScript source files", - parameters: s.object({ symbolName: s.string }), - async handler({ symbolName }) { - const { execSync } = await import("node:child_process"); - try { - const escaped = symbolName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - const out = execSync( - `grep -rn "${escaped}" --include="*.ts" . | grep -v node_modules | grep -v ".d.ts" | wc -l`, - { encoding: "utf8" } - ); - const count = parseInt(out.trim(), 10); - const lastFile = execSync( - `grep -rln "${escaped}" --include="*.ts" . | grep -v node_modules | tail -1`, - { encoding: "utf8" } - ).trim() || null; - return { count, lastFile }; - } catch { - return { count: 0, lastFile: null }; - } - }, -}); - -// Agent role: scan TypeScript exports and measure how often each exported symbol is imported or used. -const tsExportUsageCounter = agent({ - model: "typecheck", - instructions: p`Find exported TypeScript symbols: ${p.bash("grep -rn 'export ' --include='*.ts' . | grep -v node_modules | grep -v '.d.ts' | grep -E 'export (const|function|class|type|interface|enum) ' | head -60")}. For each exported symbol name, use the countUsages tool to get how many times it appears in the codebase. Assign coverageLevel: none (0 usages), low (1–2), medium (3–9), or high (≥10). Return a record keyed by symbol name.`, - output: s.record(s.object({ - usageCount: s.int, - coverageLevel: s.enum("none", "low", "medium", "high"), - lastFile: s.optional(s.string), - })), - tools: [countUsages], - maxTurns: 6, - addons: repair(), -}); - -export default tsExportUsageCounter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts deleted file mode 100644 index 599beb7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/213-git-rename-tracker.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: track file renames in git history and produce a structured rename log. -const gitRenameTracker = agent({ - model: "typecheck", - instructions: p`Retrieve git file rename history: ${p.bash("git log --diff-filter=R --summary --pretty=format:'%H %ci' 2>/dev/null | head -80 || echo 'no renames'")}. Parse each rename entry — lines starting with "rename from/to" — and associate each pair with the commit hash and ISO date from the preceding format line. Return an array sorted newest first, with at most 20 entries.`, - output: s.array(s.object({ - hash: s.string, - date: s.string, - oldPath: s.string, - newPath: s.string, - })), - maxTurns: 2, - addons: repair(), -}); - -export default gitRenameTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts deleted file mode 100644 index d13b394..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/214-yaml-lint-checker.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const validateYaml = defineTool("validateYaml", { - description: "Validate a YAML file for structural issues, especially GitHub Actions required keys", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const text = await readFile(filePath, "utf8"); - const lines = text.split("\n"); - const lineCount = lines.length; - const issues: string[] = []; - const topKeys = lines.filter((l: string) => /^[a-zA-Z]/.test(l)).map((l: string) => l.split(":")[0].trim()); - const isGhAction = topKeys.includes("on") || topKeys.includes("jobs"); - if (isGhAction) { - if (!topKeys.includes("name")) issues.push("missing top-level 'name' key"); - if (!topKeys.includes("on")) issues.push("missing top-level 'on' trigger"); - if (!topKeys.includes("jobs")) issues.push("missing top-level 'jobs' key"); - } - const status = issues.length === 0 ? "pass" : issues.length <= 1 ? "warn" : "fail"; - return { issues, lineCount, status }; - } catch (e) { - return { issues: [`read error: ${e}`], lineCount: 0, status: "fail" }; - } - }, -}); - -// Agent role: find YAML files in the workspace and validate each for structural correctness. -const yamlLintChecker = agent({ - model: "typecheck", - instructions: p`Find all YAML files in this project: ${p.bash("find . \\( -name '*.yml' -o -name '*.yaml' \\) -not -path '*/node_modules/*' | head -30")}. Use the validateYaml tool on each file path. Return a record keyed by filename with issues, lineCount, and status for each file.`, - output: s.record(s.object({ - issues: s.array(s.string), - lineCount: s.int, - status: s.enum("pass", "warn", "fail"), - })), - tools: [validateYaml], - maxTurns: 5, -}); - -export default yamlLintChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts deleted file mode 100644 index 7c816a9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/215-two-phase-complexity-review.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: extract TypeScript function names and approximate line counts from source files. -const extractor = agent({ - name: "extractor", - model: "typecheck", - instructions: p`Scan TypeScript files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.d.ts' | head -20")}. For each file, find function and arrow-function definitions: ${p.bash("grep -rn --include='*.ts' -E '^(export )?(async )?function |const [a-zA-Z]+ = (async )?(\\([^)]*\\)|[a-zA-Z]+) =>' . | grep -v node_modules | head -80")}. Estimate line count per function from surrounding context. Return a record mapping functionName to approximate lineCount.`, - output: s.record(s.int), -}); - -// Agent role: rate each TypeScript function for complexity and produce an aggregate summary. -const twoPhaseComplexityReview = agent({ - name: "twoPhaseComplexityReview", - model: "typecheck", - instructions: p`Delegate to the extractor subagent to get a record of function names and line counts. Classify each function: simple (<10 lines), moderate (10–29 lines), complex (30–59 lines), or critical (≥60 lines). Count functions rated complex or critical for summary.complexCount.`, - output: s.object({ - functions: s.record(s.object({ - lineCount: s.int, - complexity: s.enum("simple", "moderate", "complex", "critical"), - })), - summary: s.object({ - totalFunctions: s.int, - complexCount: s.int, - }), - }), - agents: { extractor }, - maxTurns: 6, -}); - -export default twoPhaseComplexityReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts deleted file mode 100644 index c335730..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/216-dockerfile-layer-analyzer.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseLayer = defineTool("parseLayer", { - description: "Classify a Dockerfile instruction for cache-friendliness and weight", - parameters: s.object({ - instruction: s.string, - args: s.string, - }), - handler({ instruction, args }) { - const inst = instruction.toUpperCase(); - const isPackageFile = /package\.json|requirements\.txt|Pipfile|go\.mod|Cargo\.toml/.test(args); - const isHeavy = (inst === "RUN") && /apt-get|npm install|pip install|yarn|apk add/.test(args); - const cacheable = (inst === "COPY" || inst === "ADD") && isPackageFile; - let tip: string | null = null; - if (inst === "RUN" && isHeavy) tip = "Combine adjacent RUN commands to reduce layers"; - if (inst === "COPY" && !cacheable) tip = "Copy only dependency manifests first to improve cache"; - return { instruction: inst, cacheable, isHeavy, tip }; - }, -}); - -// Agent role: analyze Dockerfile layers for cache efficiency and suggest optimizations. -const dockerfileLayerAnalyzer = agent({ - model: "typecheck", - instructions: p`Read the Dockerfile: ${p.readOptional("Dockerfile", "# no Dockerfile found")}. Parse each instruction line (FROM, RUN, COPY, ADD, ENV, EXPOSE, CMD, ENTRYPOINT, etc.). Use the parseLayer tool for each instruction with its arguments. Count total layers. Set optimizable to true if any layer has isHeavy or a non-null tip. Collect all non-null tips into suggestions.`, - output: s.object({ - layers: s.array(s.object({ - instruction: s.string, - args: s.string, - cacheable: s.boolean, - isHeavy: s.boolean, - tip: s.optional(s.string), - })), - totalLayers: s.int, - optimizable: s.boolean, - suggestions: s.array(s.string), - }), - tools: [parseLayer], - addons: repair(), -}); - -export default dockerfileLayerAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts deleted file mode 100644 index ed3ee3c..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/217-git-worktree-status.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const classifyWorktree = defineTool("classifyWorktree", { - description: "Classify a git worktree's status based on its path, branch, and state flags", - parameters: s.object({ - path: s.string, - branch: s.optional(s.string), - isBare: s.boolean, - isDetached: s.boolean, - }), - handler({ branch, isBare, isDetached }) { - if (isBare) return "bare"; - if (isDetached) return "detached"; - if (!branch) return "detached"; - return "clean"; - }, -}); - -// Agent role: inventory git worktrees and report their cleanliness status. -const gitWorktreeStatus = agent({ - model: "typecheck", - instructions: p`List all git worktrees: ${p.bash("git worktree list --porcelain 2>/dev/null || echo 'worktree .\nHEAD unknown\nbranch refs/heads/main'")}. Also check working tree status: ${p.bash("git status --short 2>/dev/null | head -20")}. Use the classifyWorktree tool for each worktree entry. If the current worktree has modified files, override its status to dirty. Set isMain: true for the first (primary) worktree. Set allClean to true only when every worktree has status clean.`, - output: s.object({ - worktrees: s.array(s.object({ - path: s.path, - branch: s.optional(s.string), - status: s.enum("clean", "dirty", "bare", "detached"), - isMain: s.boolean, - })), - totalWorktrees: s.int, - allClean: s.boolean, - }), - tools: [classifyWorktree], - maxTurns: 4, - addons: repair(), -}); - -export default gitWorktreeStatus; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts deleted file mode 100644 index bd069db..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/218-ts-interface-conflict-checker.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, p, s, defineTool, steering, repair } from "rig"; - -const extractInterface = defineTool("extractInterface", { - description: "Extract field names from a TypeScript interface declaration in a file", - parameters: s.object({ - filePath: s.string, - interfaceName: s.string, - }), - async handler({ filePath, interfaceName }) { - const { readFile } = await import("node:fs/promises"); - try { - const text = await readFile(filePath, "utf8"); - const pattern = new RegExp(`interface\\s+${interfaceName}\\s*\\{([^}]*)\\}`, "s"); - const match = text.match(pattern); - if (!match) return { fields: [] }; - const body = match[1]; - const fields = body - .split("\n") - .map((l: string) => l.trim()) - .filter((l: string) => l && !l.startsWith("//") && !l.startsWith("*")) - .map((l: string) => l.split(":")[0].replace(/[?;]/g, "").trim()) - .filter(Boolean); - return { fields }; - } catch { - return { fields: [] }; - } - }, -}); - -// Agent role: detect TypeScript interfaces with the same name across multiple source files. -const tsInterfaceConflictChecker = agent({ - model: "typecheck", - instructions: p`Find TypeScript interface declarations: ${p.bash("grep -rn 'interface ' --include='*.ts' . | grep -v node_modules | grep -v '.d.ts' | head -60")}. Use the extractInterface tool to get fields for each interface found. Detect interface names that appear in more than one file — those are conflicts. Report them with their file list and conflicting field names. Set conflictCount to the number of conflicting interface names.`, - output: s.object({ - interfaces: s.record(s.object({ - fields: s.array(s.string), - file: s.path, - hasConflict: s.boolean, - })), - conflicts: s.array(s.object({ - name: s.string, - files: s.array(s.path), - conflictingFields: s.array(s.string), - })), - conflictCount: s.int, - }), - tools: [extractInterface], - maxTurns: 6, - addons: [steering(), repair()], -}); - -export default tsInterfaceConflictChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts deleted file mode 100644 index 466dea2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/219-npm-audit-simplifier.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const classifyVuln = defineTool("classifyVuln", { - description: "Classify a vulnerability as direct or transitive and produce a remediation recommendation", - parameters: s.object({ - name: s.string, - severity: s.string, - isDirect: s.boolean, - }), - handler({ name, severity, isDirect }) { - const rec = isDirect - ? `Update ${name} directly in package.json` - : `Update the top-level package that depends on ${name}`; - return { recommendation: rec + (severity === "critical" || severity === "high" ? " immediately" : " when convenient") }; - }, -}); - -// Agent role: run npm audit and produce a simplified, actionable vulnerability report. -const npmAuditSimplifier = agent({ - model: "typecheck", - instructions: p`Run npm audit and capture results: ${p.bash("npm audit --json 2>/dev/null || echo '{\"vulnerabilities\":{}}'") }. Parse the JSON output. For each vulnerability entry, extract name and severity, determine if it is direct (no via chain or via is the package itself), and use the classifyVuln tool to get a recommendation. Count criticalCount and highCount separately. Write a one-sentence summary. Set action to urgent if criticalCount > 0, scheduled if highCount > 0, monitor if there are any other vulns, or none if clean.`, - output: s.object({ - vulnerabilities: s.array(s.object({ - name: s.string, - severity: s.enum("critical", "high", "moderate", "low", "info"), - isDirect: s.boolean, - recommendation: s.string, - })), - criticalCount: s.int, - highCount: s.int, - summary: s.string, - action: s.enum("urgent", "scheduled", "monitor", "none"), - }), - tools: [classifyVuln], - maxTurns: 5, - addons: repair(), -}); - -export default npmAuditSimplifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts deleted file mode 100644 index 8ebb4c3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/22-config-normalizer.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: diagnose the CI log. Prefer the first real failure over cascading errors. -const ciDiagnosis = agent({ - model: "typecheck", - output: s.object({ - failure: s.string, - likelyCause: s.string, - commandsToTry: s.array(s.string) - }), - instructions: `Diagnose the CI log. Prefer the first real failure over cascading errors.`, -}); -export default ciDiagnosis; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts deleted file mode 100644 index 9a885d5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/220-git-rename-tracker-v2.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: track file renames in git history and produce a structured rename log. -const gitRenameTrackerV2 = agent({ - model: "typecheck", - instructions: p`Retrieve git file rename history: ${p.bash("git log --diff-filter=R --summary --pretty=format:'%h %ai' | head -60 2>/dev/null || echo 'No renames found'")}. Parse each rename entry (lines matching "rename ... => ...") and associate it with the nearest commit hash and date. Return all renames sorted newest first, the total count, and the path that appears most often as either old or new.`, - output: s.object({ - renames: s.array(s.object({ - hash: s.string, - date: s.string, - oldPath: s.path, - newPath: s.path, - })), - totalRenames: s.int, - mostRenamedFile: s.optional(s.path), - }), - maxTurns: 4, - addons: repair(), -}); - -export default gitRenameTrackerV2; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts deleted file mode 100644 index e2640c1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/221-yaml-workflow-linter.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { readFileSync } from "node:fs"; - -const validateYaml = defineTool("validateYaml", { - description: "Validate a YAML file for structural issues and required top-level keys", - parameters: s.object({ filePath: s.path }), - handler({ filePath }) { - let content: string; - try { - content = readFileSync(filePath, "utf-8"); - } catch { - return { issues: ["File not readable"], lineCount: 0, status: "fail" as const }; - } - const issues: string[] = []; - const lines = content.split("\n"); - const lineCount = lines.length; - const isWorkflow = filePath.includes(".github/workflows"); - if (isWorkflow) { - if (!content.includes("name:")) issues.push("Missing 'name' key"); - if (!content.includes("on:") && !content.includes('"on":')) issues.push("Missing 'on' trigger"); - if (!content.includes("jobs:")) issues.push("Missing 'jobs' key"); - } - if (content.includes("\t")) issues.push("Contains tab characters (use spaces in YAML)"); - const status = issues.length === 0 ? "pass" : issues.some((i: string) => i.startsWith("Missing")) ? "fail" : "warn"; - return { issues, lineCount, status } as { issues: string[]; lineCount: number; status: "pass" | "warn" | "fail" }; - }, -}); - -// Agent role: lint YAML files and report structural issues per file. -const yamlWorkflowLinter = agent({ - model: "typecheck", - instructions: p`Find YAML files: ${p.bash("find . \\( -name '*.yml' -o -name '*.yaml' \\) | grep -v node_modules | grep -v .git | head -20")}. For each file path, call validateYaml and collect the result. Return a record keyed by file path.`, - output: s.record(s.object({ - issues: s.array(s.string), - lineCount: s.int, - status: s.enum("pass", "warn", "fail"), - })), - tools: [validateYaml], -}); - -export default yamlWorkflowLinter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts deleted file mode 100644 index 3d5e13f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/222-two-phase-complexity-review-v2.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: extract TypeScript function names and approximate line counts from source files. -const extractor = agent({ - name: "extractor", - model: "typecheck", - instructions: p`Scan TypeScript source files for function definitions: ${p.bash("grep -rn --include='*.ts' 'function \\|=> {\\|async ' . | grep -v node_modules | grep -v '.test.' | head -60 2>/dev/null || echo 'no ts files'")}. For each distinct function name found, estimate its line count from context. Return an array of objects with functionName, lineCount, and file.`, - output: s.array(s.object({ - functionName: s.string, - lineCount: s.int, - file: s.path, - })), -}); - -// Agent role: rate each extracted function for complexity and produce a summary. -const reviewer = agent({ - name: "reviewer", - model: "typecheck", - instructions: p`You will receive a list of functions with their line counts. Classify each as: simple (<10 lines), moderate (10-29), complex (30-59), or critical (≥60). Return one rating object per function plus a summary with total and complex+critical count.`, - output: s.object({ - analysis: s.record(s.object({ - lineCount: s.int, - complexity: s.enum("simple", "moderate", "complex", "critical"), - })), - summary: s.object({ - totalFunctions: s.int, - complexCount: s.int, - }), - }), - agents: { extractor }, -}); - -export default reviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts deleted file mode 100644 index e53146d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/223-barrel-file-generator-v2.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const detectExports = defineTool("detectExports", { - description: "Detect export declarations in a TypeScript source file", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf-8"); - const exports = (content.match(/^export\s+(default\s+)?(function|class|const|let|var|type|interface|enum)\s+\w+/gm) ?? []); - return { filePath, exports, exportCount: exports.length }; - } catch { - return { filePath, exports: [], exportCount: 0 }; - } - }, -}); - -// Agent role: generate barrel index.ts content for TypeScript source directories. -const barrelFileGenerator = agent({ - model: "typecheck", - instructions: p`Find TypeScript source files: ${p.bash("find src -name '*.ts' ! -name 'index.ts' ! -name '*.test.ts' ! -name '*.spec.ts' 2>/dev/null | head -30 || find . -name '*.ts' ! -name 'index.ts' ! -name '*.test.ts' ! -path '*/node_modules/*' | head -20")}. Use detectExports for each file. Tally filesScanned, barrelFilesWritten (directories that have at least one export), exportCount (total exports found), and directories (unique directory paths). Return only the declared output.`, - tools: [detectExports], - output: s.object({ - filesScanned: s.int, - barrelFilesWritten: s.int, - exportCount: s.int, - directories: s.array(s.string), - }), -}); - -export default barrelFileGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts deleted file mode 100644 index 3f41ce4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/224-git-hook-inventory-v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const classifyHook = defineTool("classifyHook", { - description: "Classify a git hook by inspecting its content", - parameters: s.object({ name: s.string, content: s.string }), - handler({ content }) { - if (!content || content.trim() === "missing") { - return { status: "missing" as const, isAsync: false, summary: "Hook file not present" }; - } - const isSample = content.includes("sample") || content.trim() === "#!/bin/sh" || content.trim() === "#!/bin/bash"; - const isAsync = content.includes(" &") || content.includes("async "); - const status = isSample ? "stub" : "active"; - const summary = isSample ? "Sample/placeholder hook — not active" : `Active hook (${content.split("\n").length} lines)`; - return { status, isAsync, summary } as { status: "active" | "stub" | "missing"; isAsync: boolean; summary: string }; - }, -}); - -// Agent role: inventory git hooks and classify each as active, stub, or missing. -const gitHookInventory = agent({ - model: "typecheck", - instructions: p`List and inspect git hooks: ${p.bash("ls .git/hooks/ 2>/dev/null || echo 'no hooks directory'")}. ${p.bash("for f in pre-commit commit-msg pre-push post-commit prepare-commit-msg pre-rebase; do echo \"=== $f ===\"; cat \".git/hooks/$f\" 2>/dev/null || echo 'missing'; done")}. Use classifyHook for each hook name with its content. Return a record keyed by hook name.`, - tools: [classifyHook], - output: s.record(s.object({ - summary: s.string, - status: s.enum("active", "stub", "missing"), - isAsync: s.boolean, - })), -}); - -export default gitHookInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts deleted file mode 100644 index 4dca604..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/225-pr-review-checklist-v2.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: generate a PR review checklist from the current git diff. -const prReviewChecklist = agent({ - model: "typecheck", - maxTurns: 6, - addons: repair(), - instructions: p`Generate a PR review checklist based on these changes. - -Changed files: -${p.bash("git diff --stat HEAD~1 2>/dev/null || git diff --stat HEAD 2>/dev/null || echo 'no diff available'")} - -Diff: -${p.bash("git diff HEAD~1 -- . 2>/dev/null | head -300 || git diff HEAD -- . 2>/dev/null | head -300 || echo 'no diff'")} - -For each concern, produce a checklist item with a clear description, category (security/performance/correctness/style/testing), and priority (must/should/nice-to-have). List changed files and indicate if the PR is ready for review.`, - output: s.object({ - checklist: s.array(s.object({ - item: s.string, - category: s.enum("security", "performance", "correctness", "style", "testing"), - priority: s.enum("must", "should", "nice-to-have"), - })), - changedFiles: s.array(s.path), - ready: s.boolean, - }), -}); - -export default prReviewChecklist; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts deleted file mode 100644 index ae1ec1e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/226-js-ast-node-counter.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const countAstNodes = defineTool("countAstNodes", { - description: "Count syntax node patterns in a JavaScript/TypeScript file using regex heuristics", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf-8"); - const functionCount = (content.match(/\bfunction\s+\w+\s*\(/g) ?? []).length; - const arrowFunctionCount = (content.match(/=>\s*[{(]/g) ?? []).length; - const classCount = (content.match(/\bclass\s+\w+/g) ?? []).length; - const importCount = (content.match(/^\s*import\s+/gm) ?? []).length; - const exportCount = (content.match(/^\s*export\s+/gm) ?? []).length; - return { filePath, functionCount, arrowFunctionCount, classCount, importCount, exportCount }; - } catch { - return { filePath, functionCount: 0, arrowFunctionCount: 0, classCount: 0, importCount: 0, exportCount: 0 }; - } - }, -}); - -// Agent role: count AST-like syntax node patterns in JavaScript files. -const jsAstNodeCounter = agent({ - model: "typecheck", - instructions: p`Find JavaScript files: ${p.bash("find . -name '*.js' ! -path '*/node_modules/*' ! -path '*/.git/*' | head -10 2>/dev/null || echo 'no js files found'")}. For each file, call countAstNodes and collect results. Tally totalFunctions across all files and identify mostComplexFile (highest combined function + arrowFunction count). Return only the declared output.`, - tools: [countAstNodes], - output: s.object({ - files: s.record(s.object({ - functionCount: s.int, - arrowFunctionCount: s.int, - classCount: s.int, - importCount: s.int, - exportCount: s.int, - })), - totalFunctions: s.int, - mostComplexFile: s.optional(s.path), - }), -}); - -export default jsAstNodeCounter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts deleted file mode 100644 index 8d3476e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/227-git-tag-date-mapper.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; - -const classifyTagAge = defineTool("classifyTagAge", { - description: "Classify a tag's age based on its ISO date string", - parameters: s.object({ dateStr: s.string }), - handler({ dateStr }) { - const date = new Date(dateStr); - const now = new Date(); - const daysDiff = (now.getTime() - date.getTime()) / (1000 * 60 * 60 * 24); - let ageClass: "recent" | "stable" | "old" | "ancient"; - if (daysDiff < 30) ageClass = "recent"; - else if (daysDiff < 180) ageClass = "stable"; - else if (daysDiff < 730) ageClass = "old"; - else ageClass = "ancient"; - return { ageClass }; - }, -}); - -// Agent role: map git tags to their commit dates and classify their age. -const gitTagDateMapper = agent({ - model: "typecheck", - addons: steering(), - instructions: p`Inspect git tags and their dates. - -Tags: -${p.bash("git tag -l --sort=-version:refname | head -20 2>/dev/null || echo 'no tags'")} - -Tag log: -${p.bash("git log --tags --simplify-by-decoration --pretty='%D|%ai|%s' | head -30 2>/dev/null || echo 'no tag log'")} - -For each tag, extract its ISO date and call classifyTagAge. Return a record keyed by tag name with date, subject, and ageClass. Include totalTags and latestTag.`, - tools: [classifyTagAge], - output: s.object({ - tags: s.record(s.object({ - date: s.string, - subject: s.string, - ageClass: s.enum("recent", "stable", "old", "ancient"), - })), - totalTags: s.int, - latestTag: s.optional(s.string), - }), -}); - -export default gitTagDateMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts deleted file mode 100644 index 7fdf086..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/228-circular-import-detector.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; - -const buildImportGraph = defineTool("buildImportGraph", { - description: "Build an import graph from TypeScript files in a directory by parsing relative import statements", - parameters: s.object({ directory: s.path }), - async handler({ directory }) { - const { readdir, readFile } = await import("node:fs/promises"); - const { join } = await import("node:path"); - const graph: Record = {}; - try { - const entries = await readdir(directory, { recursive: true, encoding: "utf-8" }); - const tsFiles = entries.filter((f: string) => f.endsWith(".ts") && !f.endsWith(".test.ts") && !f.endsWith(".d.ts")); - for (const file of tsFiles.slice(0, 20)) { - const fullPath = join(directory, file); - try { - const content = await readFile(fullPath, "utf-8"); - const imports = [...content.matchAll(/from\s+['"](\.[^'"]+)['"]/g)].map((m: RegExpMatchArray) => m[1]); - graph[file] = imports; - } catch { - graph[file] = []; - } - } - } catch { - // directory not found - } - return { graph }; - }, -}); - -// Agent role: detect circular imports in TypeScript source files. -const circularImportDetector = agent({ - model: "typecheck", - addons: steering(), - instructions: p`Detect circular imports in TypeScript files. - -Import overview: -${p.bash("grep -rn \"from '\\./\\|from \\\"\\./\" src/ --include='*.ts' 2>/dev/null | head -40 || grep -rn \"from '\\./\" . --include='*.ts' | grep -v node_modules | head -40 || echo 'no relative imports found'")} - -Call buildImportGraph on the source directory (try "src" first, then "."). Analyse the graph to find cycles (A imports B imports A, etc.). Return cycles as arrays of file paths, hasCycles, totalFiles, and cycleCount.`, - tools: [buildImportGraph], - output: s.object({ - cycles: s.array(s.array(s.string)), - hasCycles: s.boolean, - totalFiles: s.int, - cycleCount: s.int, - }), -}); - -export default circularImportDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts deleted file mode 100644 index 4395414..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/229-package-json-scorer.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const scoreField = defineTool("scoreField", { - description: "Score a package.json field for presence, completeness, and quality", - parameters: s.object({ - fieldName: s.string, - value: s.unknown, - importance: s.enum("required", "recommended", "optional"), - }), - handler({ fieldName, value, importance }) { - const present = value !== undefined && value !== null && value !== ""; - const nonEmpty = present && (typeof value !== "object" || Object.keys(value as object).length > 0); - const score = !present ? 0 : !nonEmpty ? 30 : importance === "required" ? 100 : importance === "recommended" ? 80 : 60; - const note = !present - ? `Missing ${importance} field` - : !nonEmpty - ? `Field '${fieldName}' is empty` - : `Field '${fieldName}' is present`; - return { present, score, note }; - }, -}); - -// Agent role: score a package.json manifest for completeness and produce a grade. -const packageJsonScorer = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Score this package.json for completeness: ${p.read("package.json")}. Use scoreField for each of these fields: -- required: name, version, description, main -- recommended: license, author, repository, keywords, bugs, homepage -- optional: engines, files, exports -Compute an overall score (0-100) as weighted average and assign a grade: A(90+), B(75+), C(60+), D(40+), F(<40). List missingRequired and missingRecommended fields.`, - tools: [scoreField], - output: s.object({ - score: s.int, - grade: s.enum("A", "B", "C", "D", "F"), - missingRequired: s.array(s.string), - missingRecommended: s.array(s.string), - details: s.record(s.object({ - present: s.boolean, - score: s.int, - note: s.string, - })), - }), -}); - -export default packageJsonScorer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts deleted file mode 100644 index ce396d5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/23-schema-inference.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: normalize the config into a JSON-compatible object. -const normalize = agent({ - model: "typecheck", - output: s.object({ - normalized: s.unknown, - warnings: s.array(s.string) - }), - instructions: `Normalize the config into a JSON-compatible object.`, -}); -export default normalize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts deleted file mode 100644 index 83677d1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/230-git-rename-tracker-v3.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: track file renames in recent git history and return a structured report. -const gitRenameTracker = agent({ - model: "typecheck", - instructions: p`Analyze the following git log output for file renames: - -${p.bash("git log --diff-filter=R --summary --oneline -50")} - -Parse each rename line (format: "rename old/path => new/path (similarity%)"). -Extract the commit hash from the preceding commit line, and the old and new paths. -Return the structured list of renames with totals.`, - output: s.object({ - renames: s.array(s.object({ - hash: s.string, - oldPath: s.path, - newPath: s.path, - })), - totalRenames: s.int, - mostRenamed: s.optional(s.path), - }), - addons: [repair()], -}); - -export default gitRenameTracker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts deleted file mode 100644 index a3712e6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/231-yaml-workflow-linter-v2.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const validateWorkflow = defineTool("validateWorkflow", { - description: "Validate a GitHub Actions workflow YAML file for required top-level keys.", - parameters: { filePath: s.path }, - handler: async ({ filePath }) => { - const content = await readFile(filePath, "utf8"); - const hasName = /^name:/m.test(content); - const hasOn = /^on:/m.test(content); - const hasJobs = /^jobs:/m.test(content); - const issues: string[] = []; - if (!hasName) issues.push("Missing 'name' key"); - if (!hasOn) issues.push("Missing 'on' key"); - if (!hasJobs) issues.push("Missing 'jobs' key"); - const status = issues.length === 0 ? "pass" : issues.length < 2 ? "warn" : "fail"; - return { hasName, hasOn, hasJobs, status, issues }; - }, -}); - -// Agent role: lint GitHub Actions workflow YAML files for required top-level keys. -const yamlWorkflowLinter = agent({ - model: "typecheck", - instructions: p`Validate each GitHub Actions workflow file found in the workspace. - -Workflow files: ${p.glob(".github/workflows/**/*.yml")} - -For each file path listed above, call the validateWorkflow tool to check for required keys. -Return a record keyed by filename with validation results.`, - output: s.record(s.object({ - hasName: s.boolean, - hasOn: s.boolean, - hasJobs: s.boolean, - status: s.enum("pass", "warn", "fail"), - issues: s.array(s.string), - })), - tools: [validateWorkflow], - addons: [repair()], -}); - -export default yamlWorkflowLinter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts deleted file mode 100644 index 64d5490..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/232-two-phase-complexity-review-v3.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: extract TypeScript files with line counts from the workspace. -const extractor = agent({ - name: "extractor", - model: "typecheck", - instructions: p`List TypeScript source files and their line counts. - -Files found: ${p.glob("**/*.ts")} -Line counts: ${p.bash("wc -l $(find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -20) 2>/dev/null | tail -21")} - -Return a list of files with their line counts. Exclude totals and node_modules.`, - output: s.array(s.object({ - file: s.path, - lines: s.int, - })), -}); - -// Agent role: classify TypeScript files by complexity tier based on line counts. -const reviewer = agent({ - name: "reviewer", - model: "typecheck", - instructions: p`You will receive a JSON list of TypeScript files with line counts. -Classify each file's complexity: -- trivial: 0-20 lines -- small: 21-100 lines -- medium: 101-300 lines -- large: 301-600 lines -- huge: 600+ lines - -Return the classified list plus a summary.`, - input: s.array(s.object({ file: s.path, lines: s.int })), - output: s.object({ - files: s.array(s.object({ - file: s.path, - lines: s.int, - complexity: s.enum("trivial", "small", "medium", "large", "huge"), - })), - summary: s.object({ - totalFiles: s.int, - largestFile: s.optional(s.path), - mostComplex: s.optional(s.path), - }), - }), -}); - -// Agent role: coordinate two-phase TypeScript complexity analysis. -const coordinator = agent({ - model: "typecheck", - instructions: p`Perform a two-phase TypeScript file complexity analysis: -1. Use the extractor subagent to get a list of TypeScript files with line counts. -2. Pass the extractor's output as input to the reviewer subagent for complexity classification. -3. Return the reviewer's output as your final result.`, - output: s.object({ - files: s.array(s.object({ - file: s.path, - lines: s.int, - complexity: s.enum("trivial", "small", "medium", "large", "huge"), - })), - summary: s.object({ - totalFiles: s.int, - largestFile: s.optional(s.path), - mostComplex: s.optional(s.path), - }), - }), - agents: { extractor, reviewer }, -}); - -export default coordinator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts deleted file mode 100644 index 66e9d7c..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/233-barrel-file-generator-v3.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const detectExports = defineTool("detectExports", { - description: "Detect exported symbols from a TypeScript source file.", - parameters: { filePath: s.path }, - handler: async ({ filePath }) => { - const content = await readFile(filePath, "utf8"); - const exportMatches = content.match(/^export\s+(?:default\s+)?(?:const|function|class|type|interface|enum)\s+(\w+)/gm) ?? []; - const symbols = exportMatches.map((m: string) => { - const match = m.match(/(\w+)\s*$/); - return match ? match[1] : ""; - }).filter(Boolean); - return { filePath, symbols, count: symbols.length }; - }, -}); - -// Agent role: scan TypeScript source files and generate a barrel index.ts with all exports. -const barrelFileGenerator = agent({ - model: "typecheck", - instructions: p`Generate a TypeScript barrel file (index.ts) that re-exports all symbols from source files. - -Source files: ${p.glob("src/**/*.ts")} - -For each file path above, call the detectExports tool to find exported symbols. -Then generate the barrel file content as a series of export statements. -Write it to ${p.writeOutput("barrelContent", "src/index.ts")}. -Return the file count, export count, barrel content, and output path.`, - output: s.object({ - filesScanned: s.int, - exportCount: s.int, - barrelContent: s.string, - outputPath: s.path, - }), - tools: [detectExports], - addons: [repair()], -}); - -export default barrelFileGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts deleted file mode 100644 index 5274d42..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/234-git-hook-inventory-v3.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { readFile, access, constants } from "node:fs/promises"; - -const classifyHook = defineTool("classifyHook", { - description: "Classify a git hook as active, stub, or missing based on its content.", - parameters: { hookName: s.string }, - handler: async ({ hookName }) => { - const hookPath = `.git/hooks/${hookName}`; - try { - await access(hookPath, constants.F_OK); - const content = await readFile(hookPath, "utf8"); - const isSample = content.includes("sample") || hookPath.endsWith(".sample"); - const isAsync = content.includes("&") || content.includes("nohup"); - const summary = isSample - ? `Sample/stub hook at ${hookPath}` - : `Active hook: ${content.split("\n")[1]?.trim() ?? ""}`; - return { status: isSample ? "stub" : "active", isAsync, summary }; - } catch { - return { status: "missing", isAsync: false, summary: `No hook at ${hookPath}` }; - } - }, -}); - -// Agent role: inventory and classify all standard git hooks in this repository. -const gitHookInventory = agent({ - model: "typecheck", - instructions: p`Inspect all standard git hooks and classify each one. - -Hook directory listing: ${p.bash("ls -la .git/hooks/ 2>/dev/null || echo 'No .git/hooks directory'")} - -Standard hooks to check: pre-commit, pre-push, commit-msg, post-commit, post-merge, -pre-rebase, post-checkout, prepare-commit-msg, pre-receive, post-receive. - -For each hook name, call the classifyHook tool to determine its status. -Return a record keyed by hook name with status, isAsync, and summary.`, - output: s.record(s.object({ - status: s.enum("active", "stub", "missing"), - isAsync: s.boolean, - summary: s.string, - })), - tools: [classifyHook], -}); - -export default gitHookInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts deleted file mode 100644 index 95293bf..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/235-pr-review-checklist-v3.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: generate a structured PR review checklist from the current git diff. -const prReviewChecklist = agent({ - model: "typecheck", - instructions: p`Generate a structured PR review checklist based on the git diff below. - -Changed files summary: -${p.bash("git diff HEAD~1 --stat 2>/dev/null || git diff --stat 2>/dev/null || echo 'No diff available'")} - -Diff content (first 200 lines): -${p.bash("git diff HEAD~1 -- . 2>/dev/null | head -200 || git diff -- . | head -200 || echo 'No diff available'")} - -Analyze the diff and produce: -1. A checklist of specific review items, each categorized and prioritized. -2. The list of changed file paths. -3. Whether the PR appears ready to merge (ready: true if no high-priority issues).`, - output: s.object({ - checklist: s.array(s.object({ - item: s.string, - category: s.enum("security", "performance", "correctness", "style", "docs", "tests"), - priority: s.enum("high", "medium", "low"), - })), - changedFiles: s.array(s.path), - ready: s.boolean, - }), - addons: [repair()], -}); - -export default prReviewChecklist; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts deleted file mode 100644 index 2611cce..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/236-vitest-coverage-parser.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { readFile } from "node:fs/promises"; - -const parseCoverageSummary = defineTool("parseCoverageSummary", { - description: "Parse a vitest coverage-summary.json file to extract per-file coverage metrics.", - parameters: { filePath: s.path }, - handler: async ({ filePath }) => { - const raw = await readFile(filePath, "utf8"); - const json = JSON.parse(raw) as Record; - const files: Record = {}; - let totalLines = 0, totalBranches = 0, totalFunctions = 0, count = 0; - for (const [file, data] of Object.entries(json)) { - if (file === "total") continue; - const lines = data.lines?.pct ?? 0; - const branches = data.branches?.pct ?? 0; - const functions = data.functions?.pct ?? 0; - const avg = (lines + branches + functions) / 3; - const status = avg >= 80 ? "covered" : avg >= 40 ? "partial" : "uncovered"; - files[file] = { lines, branches, functions, status }; - totalLines += lines; totalBranches += branches; totalFunctions += functions; count++; - } - const n = count || 1; - return { - files, - overall: { lines: totalLines / n, branches: totalBranches / n, functions: totalFunctions / n }, - totalFiles: count, - }; - }, -}); - -// Agent role: parse vitest coverage output and return a per-file coverage report. -const vitestCoverageParser = agent({ - model: "typecheck", - instructions: p`Parse the vitest coverage report for this project. - -Coverage summary file: ${p.readOptional("coverage/coverage-summary.json")} - -If the coverage summary file is available, call parseCoverageSummary with path "coverage/coverage-summary.json". -Otherwise, report all counts as 0 and status as "uncovered". - -Count files with lines coverage >= 80% as "well covered". -Return the per-file metrics, overall averages, total file count, and well-covered count.`, - output: s.object({ - files: s.record(s.object({ - lines: s.number, - branches: s.number, - functions: s.number, - status: s.enum("covered", "partial", "uncovered"), - })), - overall: s.object({ - lines: s.number, - branches: s.number, - functions: s.number, - }), - totalFiles: s.int, - wellCoveredCount: s.int, - }), - tools: [parseCoverageSummary], -}); - -export default vitestCoverageParser; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts deleted file mode 100644 index 6e14193..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/237-git-log-stats-aggregator.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const aggregateStats = defineTool("aggregateStats", { - description: "Aggregate git log lines into per-author and per-day-of-week commit counts.", - parameters: { logLines: s.string }, - handler: ({ logLines }) => { - const perAuthor: Record = {}; - const perDayOfWeek: Record = {}; - const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - let totalCommits = 0; - for (const line of logLines.split("\n")) { - if (!line.trim()) continue; - const parts = line.split("|"); - if (parts.length < 4) continue; - const author = parts[1].trim(); - const dateStr = parts[3].trim(); - perAuthor[author] = (perAuthor[author] ?? 0) + 1; - const day = days[new Date(dateStr).getDay()]; - if (day) perDayOfWeek[day] = (perDayOfWeek[day] ?? 0) + 1; - totalCommits++; - } - const mostActiveAuthor = Object.entries(perAuthor).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null; - const mostActiveDay = Object.entries(perDayOfWeek).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null; - return { perAuthor, perDayOfWeek, totalCommits, mostActiveAuthor, mostActiveDay }; - }, -}); - -// Agent role: aggregate git log statistics into per-author and per-day-of-week commit counts. -const gitLogStatsAggregator = agent({ - model: "typecheck", - instructions: p`Aggregate git commit statistics from the following log: - -${p.bash("git log --format='%H|%an|%ae|%ad|%s' --date=short -100 2>/dev/null || echo ''")} - -Call aggregateStats with the full log text above as logLines. -Return the result including perAuthor counts, perDayOfWeek counts, totalCommits, -mostActiveAuthor, and mostActiveDay.`, - output: s.object({ - perAuthor: s.record(s.int), - perDayOfWeek: s.record(s.int), - totalCommits: s.int, - mostActiveAuthor: s.optional(s.string), - mostActiveDay: s.optional(s.string), - }), - tools: [aggregateStats], -}); - -export default gitLogStatsAggregator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts deleted file mode 100644 index 66920ac..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/238-ts-import-depth-analyzer.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const analyzeImportDepth = defineTool("analyzeImportDepth", { - description: "Analyze relative import depth in a TypeScript file by counting '../' occurrences.", - parameters: { filePath: s.path }, - handler: async ({ filePath }) => { - const content = await readFile(filePath, "utf8"); - const importRegex = /from\s+['"]([^'"]+)['"]/g; - const imports: string[] = []; - let match: RegExpExecArray | null; - while ((match = importRegex.exec(content)) !== null) { - imports.push(match[1]); - } - const relativeImports = imports.filter((i: string) => i.startsWith(".")); - const depths = relativeImports.map((i: string) => (i.match(/\.\.\//g) ?? []).length); - const maxDepth = depths.length > 0 ? Math.max(...depths) : 0; - const deepImports = relativeImports.filter((i: string) => (i.match(/\.\.\//g) ?? []).length >= 2); - return { maxDepth, deepImports, importCount: imports.length }; - }, -}); - -// Agent role: analyze relative import depth across TypeScript files to find overly deep imports. -const tsImportDepthAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze TypeScript import depth across all source files. - -Source files to analyze: ${p.glob("**/*.ts")} - -For each .ts file (excluding node_modules), call analyzeImportDepth to get maxDepth, deepImports, and importCount. -Calculate the average depth across all files. -Identify the file with the highest maxDepth as deepestFile. -Return the full per-file record plus summary stats.`, - output: s.object({ - files: s.record(s.object({ - maxDepth: s.int, - deepImports: s.array(s.string), - importCount: s.int, - })), - deepestFile: s.optional(s.path), - averageDepth: s.number, - totalFiles: s.int, - }), - tools: [analyzeImportDepth], - addons: [repair()], -}); - -export default tsImportDepthAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts deleted file mode 100644 index e718791..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/239-env-file-completeness-checker.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseEnvKeys = defineTool("parseEnvKeys", { - description: "Parse an env file string and return the list of key names.", - parameters: { content: s.string }, - handler: ({ content }) => { - return content - .split("\n") - .map((line: string) => line.trim()) - .filter((line: string) => line && !line.startsWith("#")) - .map((line: string) => line.split("=")[0].trim()) - .filter(Boolean); - }, -}); - -// Agent role: compare .env.example with .env to check completeness of environment configuration. -const envFileCompletenessChecker = agent({ - model: "typecheck", - instructions: p`Compare .env.example with .env to check that all required keys are set. - -.env.example content: ${p.readOptional(".env.example")} - -.env content: ${p.readOptional(".env")} - -Steps: -1. Call parseEnvKeys with the .env.example content to get exampleKeys. -2. Call parseEnvKeys with the .env content to get presentKeys. -3. Compute missingKeys (in exampleKeys but not presentKeys) and extraKeys (in presentKeys but not exampleKeys). -4. Compute completeness as (exampleKeys.length - missingKeys.length) / exampleKeys.length (or 1.0 if example is empty). -5. Set status: - - "missing-example" if .env.example is empty/missing - - "missing-env" if .env is empty/missing - - "complete" if missingKeys is empty - - "partial" otherwise`, - output: s.object({ - exampleKeys: s.array(s.string), - presentKeys: s.array(s.string), - missingKeys: s.array(s.string), - extraKeys: s.array(s.string), - completeness: s.number, - status: s.enum("complete", "partial", "missing-example", "missing-env"), - }), - tools: [parseEnvKeys], - addons: [repair()], -}); - -export default envFileCompletenessChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts deleted file mode 100644 index 6676a2e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/24-error-message-improver.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: infer a practical runtime-visible schema from the samples. -const inferShape = agent({ - model: "typecheck", - output: s.object({ - fields: s.array(s.object({ - name: s.string, - type: s.string, - optional: s.boolean - })), - example: s.unknown - }), - instructions: `Infer a practical runtime-visible schema from the samples.`, -}); -export default inferShape; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts deleted file mode 100644 index e9dd934..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/240-git-commit-annotator.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: annotate each of the last 20 git commits with a category and impact level. -const commitSummarizer = agent({ - name: "commitSummarizer", - model: "typecheck", - instructions: p`Classify the following git commit line into a category and impact level. -Commit: ${p.readInput("commit")}`, - input: s.object({ commit: s.string }), - output: s.object({ - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - impact: s.enum("low", "medium", "high"), - }), -}); - -// Agent role: fetch the last 20 git commits and annotate each with category and impact using the commitSummarizer subagent. -const gitCommitAnnotator = agent({ - model: "typecheck", - instructions: p`You are a git commit annotator. Here are the last 20 commits: -${p.bash("git log --oneline -20")} - -For each commit line, call the commitSummarizer subagent with the full commit line. -Then assemble the annotations array and a short prose report summarizing the distribution of categories and impacts.`, - output: s.object({ - annotations: s.array(s.object({ - hash: s.string, - message: s.string, - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - impact: s.enum("low", "medium", "high"), - })), - report: s.string, - }), - agents: { commitSummarizer }, -}); - -export default gitCommitAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts deleted file mode 100644 index 604f33f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/241-npm-script-dep-mapper.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseScriptDeps = defineTool("parseScriptDeps", { - description: "Parse npm scripts JSON and extract per-script dependency metadata.", - parameters: { scriptsJson: s.string }, - handler: ({ scriptsJson }: { scriptsJson: string }) => { - const scripts: Record = JSON.parse(scriptsJson); - const result: Record = {}; - for (const [name, command] of Object.entries(scripts)) { - const refs = [...command.matchAll(/npm run ([a-z0-9:_-]+)/gi)].map((m: RegExpMatchArray) => m[1]); - const hasPreHook = (`pre${name}`) in scripts; - const hasPostHook = (`post${name}`) in scripts; - let category = "util"; - if (/build|compile|bundle/.test(name)) category = "build"; - else if (/test|spec|coverage/.test(name)) category = "test"; - else if (/lint|format|check/.test(name)) category = "lint"; - else if (/dev|start|watch/.test(name)) category = "dev"; - else if (/deploy|publish|release/.test(name)) category = "deploy"; - else if (/^pre|^post/.test(name)) category = "hook"; - result[name] = { command, dependsOn: refs, category, hasPreHook, hasPostHook }; - } - return result; - }, -}); - -// Agent role: map npm script dependencies in the workspace package.json. -const npmScriptDepMapper = agent({ - model: "typecheck", - instructions: p`Analyze the npm scripts in the workspace package.json. -package.json content: ${p.read("package.json")} - -Steps: -1. Extract the "scripts" field from the package.json content as a JSON string. -2. Call parseScriptDeps with that JSON string. -3. Return the result directly as the output record.`, - output: s.record(s.object({ - command: s.string, - dependsOn: s.array(s.string), - category: s.enum("build", "test", "lint", "dev", "deploy", "util", "hook", "other"), - hasPreHook: s.boolean, - hasPostHook: s.boolean, - })), - tools: [parseScriptDeps], - maxTurns: 6, - addons: [repair()], -}); - -export default npmScriptDepMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts deleted file mode 100644 index 74d6e15..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/242-markdown-link-checker.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { exec } from "node:child_process"; -import { promisify } from "node:util"; - -const execAsync = promisify(exec); - -const checkUrl = defineTool("checkUrl", { - description: "Check an HTTP URL with curl and return its status.", - parameters: { url: s.string }, - handler: async ({ url }: { url: string }) => { - try { - const { stdout } = await execAsync( - `curl -s -o /dev/null -w "%{http_code}" --max-time 5 --location "${url}"`, - ); - const code = parseInt(stdout.trim(), 10); - let status: string; - if (code >= 200 && code < 300) status = "ok"; - else if (code >= 300 && code < 400) status = "redirect"; - else if (code === 0) status = "timeout"; - else status = "broken"; - return { httpCode: code, status }; - } catch { - return { httpCode: 0, status: "timeout" }; - } - }, -}); - -// Agent role: check all HTTP/HTTPS links found in markdown files in the workspace. -const markdownLinkChecker = agent({ - model: "typecheck", - instructions: p`Check all HTTP/HTTPS links found in markdown files. - -Markdown files: ${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -30")} -Extracted URLs: ${p.bash("grep -rh 'https\\?://[^ )>\"]*' --include='*.md' --no-filename . 2>/dev/null | grep -oE 'https?://[^ )>\"]+' | sort -u | head -50")} - -Steps: -1. For each unique URL extracted, call checkUrl. -2. Build the links array with url, status, httpCode, and foundInFile (leave as null if not determinable). -3. Count brokenCount (status = "broken" or "timeout"). -4. Set allValid to true only if brokenCount is 0.`, - output: s.object({ - links: s.array(s.object({ - url: s.string, - status: s.enum("ok", "broken", "redirect", "timeout", "skipped"), - httpCode: s.optional(s.number), - foundInFile: s.optional(s.string), - })), - brokenCount: s.number, - allValid: s.boolean, - }), - tools: [checkUrl], - maxTurns: 8, -}); - -export default markdownLinkChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts deleted file mode 100644 index a363ad0..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/243-package-version-drift.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: report package version drift by comparing package.json with npm outdated results. -const packageVersionDrift = agent({ - model: "typecheck", - instructions: p`Analyze package version drift for this workspace. - -package.json: ${p.read("package.json")} -npm outdated (JSON, may be empty if all current): ${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} - -Steps: -1. Parse the npm outdated JSON — each key is a package name with current/wanted/latest fields. -2. For each outdated package determine driftLevel: - - "ok" if current === latest - - "patch" if only patch differs - - "minor" if minor version differs - - "major" if major version differs -3. Write a markdown drift report to drift-report.md summarizing the table. -4. Set reportWritten to true after writing.`, - output: s.object({ - packages: s.array(s.object({ - name: s.string, - current: s.string, - latest: s.string, - driftLevel: s.enum("ok", "patch", "minor", "major"), - })), - reportWritten: s.boolean, - }), -}); - -export default packageVersionDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts deleted file mode 100644 index 0642913..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/244-git-author-stats.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: aggregate git author statistics including commit counts and first/last commit dates. -const gitAuthorStats = agent({ - model: "typecheck", - instructions: p`Aggregate git commit statistics by author. - -Commit counts per author: ${p.bash("git shortlog -sne --all 2>/dev/null || echo ''")} -Per-commit author and date: ${p.bash("git log --format='%ae|%ai' --all 2>/dev/null | head -500")} - -Steps: -1. Parse the shortlog output to extract each author email and commit count. -2. From the per-commit log, compute firstCommit (earliest date) and lastCommit (latest date) per author email. -3. Build the authors record keyed by email with commitCount, firstCommit, lastCommit. -4. Set topAuthor to the email with the highest commitCount. -5. Set totalCommits to the sum of all commitCounts.`, - output: s.object({ - authors: s.record(s.object({ - commitCount: s.number, - firstCommit: s.string, - lastCommit: s.string, - })), - topAuthor: s.string, - totalCommits: s.number, - }), -}); - -export default gitAuthorStats; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts deleted file mode 100644 index 32a35c0..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/245-ts-path-alias-validator.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { existsSync } from "node:fs"; - -const checkAlias = defineTool("checkAlias", { - description: "Check whether a TypeScript path alias target directory exists on disk.", - parameters: { alias: s.string, target: s.string }, - handler: ({ target }: { alias: string; target: string }) => { - const resolved = target.replace(/\/\*$/, ""); - return existsSync(resolved) ? "valid" : "broken"; - }, -}); - -// Agent role: validate all TypeScript path aliases defined in tsconfig.json against the workspace. -const tsPathAliasValidator = agent({ - model: "typecheck", - instructions: p`Validate TypeScript path aliases defined in tsconfig.json. - -tsconfig.json: ${p.read("tsconfig.json")} -Import statements in .ts files: ${p.bash("grep -rh --include='*.ts' 'from \"' . 2>/dev/null | grep -v node_modules | sort -u | head -100")} - -Steps: -1. Parse the compilerOptions.paths from tsconfig.json — each key is an alias pattern, values are target arrays. -2. For each alias, call checkAlias with the alias key and its first target path. -3. Check whether each alias is actually used in the import statements. -4. Set status: "broken" if target doesn't exist, "unused" if never imported, "valid" otherwise. -5. Count brokenCount as the number of broken aliases.`, - output: s.object({ - aliases: s.record(s.object({ - target: s.string, - status: s.enum("valid", "broken", "unused"), - })), - totalAliases: s.number, - brokenCount: s.number, - }), - tools: [checkAlias], - maxTurns: 6, -}); - -export default tsPathAliasValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts deleted file mode 100644 index 2a55a3f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/246-stale-branch-detector.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyBranchAge = defineTool("classifyBranchAge", { - description: "Classify a branch as fresh, stale, or dead based on its last commit date.", - parameters: { branchName: s.string, lastCommitDate: s.string }, - handler: ({ lastCommitDate }: { branchName: string; lastCommitDate: string }) => { - const ageMs = Date.now() - new Date(lastCommitDate).getTime(); - const ageDays = ageMs / (1000 * 60 * 60 * 24); - if (ageDays < 30) return "fresh"; - if (ageDays < 90) return "stale"; - return "dead"; - }, -}); - -// Agent role: detect stale and dead local git branches and recommend candidates for deletion. -const staleBranchDetector = agent({ - model: "typecheck", - instructions: p`Detect stale and dead local git branches. - -Branch list with last commit dates: -${p.bash("git for-each-ref --format='%(refname:short)|%(committerdate:iso8601)' refs/heads 2>/dev/null || echo ''")} - -Steps: -1. Parse each line as branchName|lastCommitDate. -2. For each branch, call classifyBranchAge to get its age category. -3. Build the branches array with name, lastCommit, and age. -4. Count staleCount (age = "stale") and deadCount (age = "dead"). -5. Set recommendedForDeletion to branch names where age is "dead".`, - output: s.object({ - branches: s.array(s.object({ - name: s.string, - lastCommit: s.string, - age: s.enum("fresh", "stale", "dead"), - })), - staleCount: s.number, - deadCount: s.number, - recommendedForDeletion: s.array(s.string), - }), - tools: [classifyBranchAge], - maxTurns: 6, -}); - -export default staleBranchDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts deleted file mode 100644 index 27c4e2f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/247-license-header-checker.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const checkLicenseHeader = defineTool("checkLicenseHeader", { - description: "Check whether a TypeScript file starts with the expected license header.", - parameters: { filePath: s.string, expectedHeader: s.string }, - handler: async ({ filePath, expectedHeader }: { filePath: string; expectedHeader: string }) => { - try { - const content = await readFile(filePath, "utf-8"); - const lines = content.split("\n"); - const headerLines = expectedHeader.split("\n"); - const fileStart = lines.slice(0, headerLines.length).join("\n"); - if (fileStart === expectedHeader) return "ok"; - if (content.includes(expectedHeader.split("\n")[0])) return "wrong"; - return "missing"; - } catch { - return "missing"; - } - }, -}); - -// Agent role: check that all TypeScript source files contain the expected license header. -const licenseHeaderChecker = agent({ - model: "typecheck", - input: s.object({ expectedHeader: s.string }), - instructions: p`Check each TypeScript file for the expected license header. - -TypeScript files in the workspace: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' | head -60")} - -Steps: -1. Read expectedHeader from the input. -2. For each file path, call checkLicenseHeader with the filePath and expectedHeader. -3. Build a files record keyed by file path with hasHeader and status. -4. Count missingCount (status = "missing" or "wrong"). -5. Set allCompliant to true only if missingCount is 0.`, - output: s.object({ - files: s.record(s.object({ - hasHeader: s.boolean, - status: s.enum("ok", "missing", "wrong"), - })), - missingCount: s.number, - allCompliant: s.boolean, - }), - tools: [checkLicenseHeader], - maxTurns: 8, - addons: [repair()], -}); - -export default licenseHeaderChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts deleted file mode 100644 index 0aa8bbe..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/248-yaml-config-diff.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const extractYamlKeys = defineTool("extractYamlKeys", { - description: "Extract top-level keys from a YAML string.", - parameters: { content: s.string }, - handler: ({ content }: { content: string }) => { - const keys: string[] = []; - for (const line of content.split("\n")) { - const m = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):/); - if (m) keys.push(m[1]); - } - return keys; - }, -}); - -const diffKeys = defineTool("diffKeys", { - description: "Compute added and removed keys between two key arrays.", - parameters: { baseKeys: s.array(s.string), targetKeys: s.array(s.string) }, - handler: ({ baseKeys, targetKeys }: { baseKeys: string[]; targetKeys: string[] }) => { - const addedKeys = targetKeys.filter((k: string) => !baseKeys.includes(k)); - const removedKeys = baseKeys.filter((k: string) => !targetKeys.includes(k)); - return { addedKeys, removedKeys }; - }, -}); - -// Agent role: diff top-level keys between two YAML config files and detect breaking changes. -const yamlConfigDiff = agent({ - model: "typecheck", - input: s.object({ baseFile: s.string, targetFile: s.string }), - instructions: p`Diff top-level YAML keys between two config files. - -Base file content: ${p.readInput("baseFile")} -Target file content: ${p.readInput("targetFile")} - -Steps: -1. Call extractYamlKeys on the base file content to get baseKeys. -2. Call extractYamlKeys on the target file content to get targetKeys. -3. Call diffKeys with baseKeys and targetKeys to get addedKeys and removedKeys. -4. changedKeys are keys present in both where values differ (estimate from context if possible, else leave empty). -5. totalChanges = addedKeys.length + removedKeys.length + changedKeys.length. -6. hasBreakingChanges = removedKeys.length > 0.`, - output: s.object({ - addedKeys: s.array(s.string), - removedKeys: s.array(s.string), - changedKeys: s.array(s.string), - totalChanges: s.number, - hasBreakingChanges: s.boolean, - }), - tools: [extractYamlKeys, diffKeys], - maxTurns: 6, -}); - -export default yamlConfigDiff; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts deleted file mode 100644 index 6acbb5e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/249-monorepo-workspace-lister.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; -import { readFile } from "node:fs/promises"; - -const extractPackageInfo = defineTool("extractPackageInfo", { - description: "Read a nested package.json and extract name, version, and dependency names.", - parameters: { filePath: s.string }, - handler: async ({ filePath }: { filePath: string }) => { - try { - const content = await readFile(filePath, "utf-8"); - const pkg = JSON.parse(content); - const deps = [ - ...Object.keys(pkg.dependencies ?? {}), - ...Object.keys(pkg.devDependencies ?? {}), - ]; - return { - name: pkg.name ?? "(unnamed)", - version: pkg.version ?? "0.0.0", - dependencies: deps, - hasPrivate: pkg.private === true, - }; - } catch { - return { name: "(error)", version: "0.0.0", dependencies: [], hasPrivate: false }; - } - }, -}); - -// Agent role: discover all workspace packages in a monorepo and list their metadata. -const monorepoWorkspaceLister = agent({ - model: "typecheck", - instructions: p`Discover all nested package.json files in this monorepo and extract package metadata. - -Nested package.json files (excluding node_modules): -${p.bash("find . -name 'package.json' -not -path '*/node_modules/*' -mindepth 2 -maxdepth 4 2>/dev/null")} - -Steps: -1. For each file path in the list above, call extractPackageInfo to get its metadata. -2. Assemble the packages array with name, version, dependencies, and hasPrivate for each. -3. Set totalPackages to the length of the packages array.`, - output: s.object({ - packages: s.array(s.object({ - name: s.string, - version: s.string, - dependencies: s.array(s.string), - hasPrivate: s.boolean, - })), - totalPackages: s.number, - }), - tools: [extractPackageInfo], - maxTurns: 8, - addons: [steering()], -}); - -export default monorepoWorkspaceLister; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts deleted file mode 100644 index 964d9f4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/25-migration-guide.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: rewrite the error to be actionable and precise. -const improve = agent({ - model: "typecheck", - output: s.object({ - message: s.string, - explanation: s.string - }), - instructions: `Rewrite the following error to be actionable and precise:\n\nTypeError: Cannot read properties of undefined (reading 'map') at Array.forEach ()\n at processItems (src/processor.ts:23:18)`, -}); - -export default improve; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts deleted file mode 100644 index 43cc742..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/250-git-commit-annotator.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize a single git commit line into a category and impact rating -const commitSummarizer = agent({ - name: "commitSummarizer", - model: "typecheck", - instructions: p`Analyze the git commit message provided in the input and classify it. - -Commit info: ${p.inputField("commitLine")} - -Classify into category (feat, fix, chore, docs, refactor, test, perf) and rate impact (low, medium, high).`, - input: s.object({ commitLine: s.string }), - output: s.object({ - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - impact: s.enum("low", "medium", "high"), - }), -}); - -// Agent role: annotate recent git commits with category and impact via subagent delegation, writing a markdown report -const gitCommitAnnotator = agent({ - name: "gitCommitAnnotator", - model: "typecheck", - agents: { commitSummarizer }, - instructions: p`Annotate recent git commits using the commitSummarizer subagent. - -Recent commits (hash + message): -${p.bash("git log --oneline -20")} - -For each commit line, delegate to commitSummarizer with the full commit line as commitLine. -Collect the category and impact for every commit. -Build a markdown report table with columns: hash, message, category, impact. -Write the report to commit-annotations.md. -${p.writeOutput("report", "commit-annotations.md")}`, - output: s.object({ - annotations: s.array( - s.object({ - hash: s.string, - message: s.string, - category: s.enum("feat", "fix", "chore", "docs", "refactor", "test", "perf"), - impact: s.enum("low", "medium", "high"), - }) - ), - report: s.string, - }), -}); - -export default gitCommitAnnotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts deleted file mode 100644 index 1e4916b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/251-npm-script-dep-mapper.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseScriptDeps = defineTool("parseScriptDeps", { - description: "Extract npm run references and detect pre/post hooks for a script", - parameters: s.object({ - scriptName: s.string, - scriptBody: s.string, - allScriptNames: s.array(s.string), - }), - handler: ({ scriptName, scriptBody, allScriptNames }) => { - const deps: string[] = []; - const runRefs = scriptBody.match(/npm run ([\w:.-]+)/g) ?? []; - runRefs.forEach((ref: string) => deps.push(ref.replace("npm run ", ""))); - const hasPreHook = allScriptNames.includes("pre" + scriptName); - const hasPostHook = allScriptNames.includes("post" + scriptName); - return JSON.stringify({ deps, hasPreHook, hasPostHook }); - }, -}); - -// Agent role: map npm script dependencies and classify each script by category -const npmScriptDepMapper = agent({ - name: "npmScriptDepMapper", - model: "typecheck", - maxTurns: 2, - addons: repair(), - tools: [parseScriptDeps], - instructions: p`Analyze npm scripts from package.json and map their dependencies. - -package.json: ${p.read("package.json")} - -For each script, call parseScriptDeps with the scriptName, scriptBody, and list of all script names. -Classify each script's category: build, test, lint, dev, deploy, util, hook, or other. -A script is a hook category if its name starts with pre or post. -Set hasPreHook and hasPostHook based on tool output. -Return a record keyed by script name.`, - output: s.record( - s.object({ - command: s.string, - dependsOn: s.array(s.string), - category: s.enum("build", "test", "lint", "dev", "deploy", "util", "hook", "other"), - hasPreHook: s.boolean, - hasPostHook: s.boolean, - }) - ), -}); - -export default npmScriptDepMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts deleted file mode 100644 index 6cadfbb..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/252-markdown-link-checker.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const checkUrl = defineTool("checkUrl", { - description: "Check the HTTP status of a URL using curl", - parameters: s.object({ url: s.string }), - handler: async ({ url }) => { - const { execSync } = await import("node:child_process"); - try { - const code = execSync( - `curl --head --silent --max-time 5 -o /dev/null -w "%{http_code}" "${url}" 2>/dev/null`, - { encoding: "utf8", timeout: 8000 } - ).trim(); - return code; - } catch { - return "timeout"; - } - }, -}); - -// Agent role: locate markdown files, extract HTTP links, and check each link's HTTP status -const markdownLinkChecker = agent({ - name: "markdownLinkChecker", - model: "typecheck", - addons: repair(), - tools: [checkUrl], - instructions: p`Check HTTP links found across all markdown files in this workspace. - -Markdown files found: -${p.bash("find . -name '*.md' -not -path '*/node_modules/*' | head -20")} - -Unique URLs extracted: -${p.bash("grep -roh 'https\\?://[^)\"\\s]*' . --include='*.md' 2>/dev/null | sort -u | head -50")} - -For each URL, call checkUrl and classify the result: -- ok: HTTP 200-299 -- redirect: HTTP 301, 302, 307, 308 -- broken: HTTP 400-599 -- timeout: curl timed out or failed -- skipped: malformed or non-http URL - -Set allValid to true only if brokenCount is 0.`, - output: s.object({ - links: s.array( - s.object({ - url: s.url, - status: s.enum("ok", "broken", "redirect", "timeout", "skipped"), - httpCode: s.optional(s.int), - foundInFile: s.optional(s.path), - }) - ), - brokenCount: s.int, - allValid: s.boolean, - }), -}); - -export default markdownLinkChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts deleted file mode 100644 index 70231b1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/253-package-version-drift.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: compare installed npm package versions against the latest published versions and classify drift -const pkgVersionDrift = agent({ - name: "pkgVersionDrift", - model: "typecheck", - instructions: p`Report npm package version drift for this project. - -Package manifest: ${p.read("package.json")} - -Outdated packages (JSON): ${p.bash("npm outdated --json 2>/dev/null || echo '{}'")} - -For each dependency, classify driftLevel: -- ok: current matches latest -- patch: only patch version behind -- minor: minor version behind -- major: major version behind - -Write a markdown drift summary report. -${p.writeOutput("report", "version-drift-report.md")}`, - output: s.object({ - packages: s.array( - s.object({ - name: s.string, - current: s.string, - latest: s.string, - driftLevel: s.enum("ok", "patch", "minor", "major"), - }) - ), - report: s.string, - reportWritten: s.boolean, - }), -}); - -export default pkgVersionDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts deleted file mode 100644 index baad490..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/254-git-author-stats.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: aggregate git commit statistics per author including commit counts and date ranges -const gitAuthorStats = agent({ - name: "gitAuthorStats", - model: "typecheck", - instructions: p`Aggregate git commit statistics per author. - -Author commit counts: ${p.bash("git shortlog -sne --all 2>/dev/null | head -40")} - -Commit log with author emails and dates: ${p.bash("git log --format='%ae|%ad' --date=short 2>/dev/null | head -200")} - -For each unique author email, compute: -- commitCount: total number of commits -- firstCommit: earliest commit date (YYYY-MM-DD) -- lastCommit: most recent commit date (YYYY-MM-DD) - -Identify topAuthor with the most commits. -Compute totalCommits across all authors.`, - output: s.object({ - authors: s.record( - s.object({ - commitCount: s.int, - firstCommit: s.string, - lastCommit: s.string, - }) - ), - topAuthor: s.string, - totalCommits: s.int, - }), -}); - -export default gitAuthorStats; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts deleted file mode 100644 index 0c9c9b0..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/255-ts-path-alias-validator.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; -import { existsSync } from "node:fs"; - -const checkAlias = defineTool("checkAlias", { - description: "Check whether a TypeScript path alias target exists on the filesystem", - parameters: s.object({ alias: s.string, target: s.string }), - handler: ({ alias, target }) => { - const resolved = target.replace(/\/\*$/, ""); - const exists = existsSync(resolved); - return JSON.stringify({ alias, target, exists }); - }, -}); - -// Agent role: validate TypeScript path alias targets from tsconfig.json against the filesystem -const tsPathAliasValidator = agent({ - name: "tsPathAliasValidator", - model: "typecheck", - tools: [checkAlias], - instructions: p`Validate TypeScript path aliases defined in tsconfig.json. - -tsconfig.json: ${p.read("tsconfig.json")} - -Import alias usage in source: ${p.bash("grep -r --include='*.ts' -h 'from [\"\\x27]' . 2>/dev/null | grep -v node_modules | grep -v '\\./' | grep -v '\\.\\./' | head -40")} - -For each entry in compilerOptions.paths, call checkAlias with the alias pattern and its first target path. -Classify each alias: -- valid: target exists on disk and alias is used in imports -- broken: target path does not exist -- unused: target exists but alias not found in any imports - -Report totalAliases and brokenCount.`, - output: s.object({ - aliases: s.record( - s.object({ - target: s.string, - status: s.enum("valid", "broken", "unused"), - }) - ), - totalAliases: s.int, - brokenCount: s.int, - }), -}); - -export default tsPathAliasValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts deleted file mode 100644 index ec6d074..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/256-gh-actions-timing-analyzer.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseWorkflowSteps = defineTool("parseWorkflowSteps", { - description: "Parse a GitHub Actions workflow YAML to extract job names, step counts, and detect optimization patterns", - parameters: s.object({ content: s.string, filename: s.string }), - handler: ({ content, filename }) => { - const jobMatches = content.match(/^\s{2}[\w-]+:/gm) ?? []; - const stepMatches = content.match(/^\s+-\s+(?:name:|uses:|run:)/gm) ?? []; - const hasCache = /uses:\s+actions\/cache/.test(content) || /cache:/.test(content); - const hasMatrix = /matrix:/.test(content); - const hasInstall = /npm (ci|install)|yarn install|pnpm install/.test(content); - const missingCache = hasInstall && !hasCache; - const suggestions: string[] = []; - if (missingCache) suggestions.push("Add actions/cache after install step to speed up builds"); - if (hasMatrix && jobMatches.length === 1) suggestions.push("Matrix found but only one job — consider parallel jobs for different test suites"); - if (stepMatches.length > 15) suggestions.push("Workflow has many steps — consider splitting into reusable workflows"); - return JSON.stringify({ filename, jobs: jobMatches.length, steps: stepMatches.length, hasCache, hasMatrix, suggestions }); - }, -}); - -// Agent role: analyze GitHub Actions workflow files for timing and performance optimization opportunities -const ghActionsTimingAnalyzer = agent({ - name: "ghActionsTimingAnalyzer", - model: "typecheck", - addons: repair(), - tools: [parseWorkflowSteps], - instructions: p`Analyze GitHub Actions workflow files for performance optimization opportunities. - -Workflow files: ${p.glob(".github/workflows/*.yml")} - -Workflow contents: ${p.bash("find .github/workflows -name '*.yml' 2>/dev/null | head -10 | xargs cat 2>/dev/null || echo 'No workflows found'")} - -For each workflow file, call parseWorkflowSteps with the file content and filename. -Collect results and determine if any workflows are optimizable (have suggestions). -Set optimizable to true if any workflow has suggestions.`, - output: s.object({ - workflows: s.array( - s.object({ - file: s.path, - jobs: s.int, - steps: s.int, - hasCache: s.boolean, - hasMatrix: s.boolean, - suggestions: s.array(s.string), - }) - ), - totalWorkflows: s.int, - optimizable: s.boolean, - }), -}); - -export default ghActionsTimingAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts deleted file mode 100644 index 7159b5a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/257-binary-file-detector.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const detectBinary = defineTool("detectBinary", { - description: "Detect whether a file is binary by sampling its first 8KB for null bytes", - parameters: s.object({ filePath: s.string }), - handler: async ({ filePath }) => { - const { readFile, stat } = await import("node:fs/promises"); - try { - const stats = await stat(filePath); - const sizeBytes = stats.size; - const buf = await readFile(filePath); - const sample = buf.slice(0, 8192); - let nullBytes = 0; - for (let i = 0; i < sample.length; i++) { - if (sample[i] === 0) nullBytes++; - } - const nullRatio = sample.length > 0 ? nullBytes / sample.length : 0; - const type = nullRatio > 0.01 ? "binary" : "text"; - return JSON.stringify({ type, sizeBytes }); - } catch { - return JSON.stringify({ type: "unknown", sizeBytes: 0 }); - } - }, -}); - -// Agent role: detect binary files committed to the git repository by sampling file contents -const binaryFileDetector = agent({ - name: "binaryFileDetector", - model: "typecheck", - addons: steering(), - tools: [detectBinary], - instructions: p`Detect binary files in the git repository. - -All tracked files: ${p.bash("git ls-files 2>/dev/null | head -200")} - -For each tracked file, call detectBinary to classify it as text, binary, or unknown. -Count binaryCount and textCount across all files. -Set hasBinaryFiles to true if binaryCount > 0. -Return a record keyed by file path.`, - output: s.object({ - files: s.record( - s.object({ - type: s.enum("text", "binary", "unknown"), - sizeBytes: s.optional(s.int), - }) - ), - binaryCount: s.int, - textCount: s.int, - hasBinaryFiles: s.boolean, - }), -}); - -export default binaryFileDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts deleted file mode 100644 index 7f43790..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/258-ts-interface-inheritance-graph.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const extractInterfaceExtends = defineTool("extractInterfaceExtends", { - description: "Extract TypeScript interface declarations and their extends relationships from file content", - parameters: s.object({ content: s.string }), - handler: ({ content }) => { - const results: Array<{ name: string; extends: string[] }> = []; - const re = /interface\s+(\w+)(?:<[^>]+>)?\s*(?:extends\s+([\w<>, ]+))?\s*\{/g; - let m: RegExpExecArray | null; - while ((m = re.exec(content)) !== null) { - const name = m[1]; - const extendsClause = m[2] ?? ""; - const parents = extendsClause - ? extendsClause.split(",").map((p: string) => p.trim().replace(/<.*>/, "").trim()).filter(Boolean) - : []; - results.push({ name, extends: parents }); - } - return JSON.stringify(results); - }, -}); - -// Agent role: build a TypeScript interface inheritance graph from source files -const tsInterfaceInheritanceGraph = agent({ - name: "tsInterfaceInheritanceGraph", - model: "typecheck", - addons: repair(), - tools: [extractInterfaceExtends], - instructions: p`Build a TypeScript interface inheritance graph. - -TypeScript source files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.d.ts' | head -30")} - -Interface declarations from source: ${p.bash("grep -rh 'interface ' . --include='*.ts' 2>/dev/null | grep -v node_modules | head -100")} - -For each source file group, call extractInterfaceExtends with the combined content. -Build a graph where each interface node lists its parent interfaces. -Classify each interface's depth: root (no parents), derived (has parents), or leaf (no children). -Compute totalInterfaces and maxDepth (longest inheritance chain).`, - output: s.object({ - interfaces: s.record( - s.object({ - parents: s.array(s.string), - depth: s.enum("root", "derived", "leaf"), - }) - ), - totalInterfaces: s.int, - maxDepth: s.int, - }), -}); - -export default tsInterfaceInheritanceGraph; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts deleted file mode 100644 index c574a99..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/259-dep-license-matrix.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const extractLicense = defineTool("extractLicense", { - description: "Extract the SPDX license identifier from a package's license field or LICENSE file content", - parameters: s.object({ packageName: s.string, licenseField: s.string }), - handler: ({ packageName, licenseField }) => { - const permissive = ["MIT", "ISC", "BSD-2-Clause", "BSD-3-Clause", "Apache-2.0", "Unlicense", "CC0-1.0", "0BSD"]; - const copyleft = ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0", "AGPL-3.0", "MPL-2.0"]; - const id = licenseField.trim().toUpperCase(); - let compatibility: string; - if (permissive.some((l: string) => id.includes(l.toUpperCase()))) { - compatibility = "permissive"; - } else if (copyleft.some((l: string) => id.includes(l.toUpperCase()))) { - compatibility = "copyleft"; - } else if (id === "UNLICENSED" || id === "") { - compatibility = "proprietary"; - } else { - compatibility = "unknown"; - } - return JSON.stringify({ packageName, spdxId: licenseField, compatibility }); - }, -}); - -// Agent role: audit npm dependency licenses and build a compatibility matrix -const depLicenseMatrix = agent({ - name: "depLicenseMatrix", - model: "typecheck", - addons: repair(), - tools: [extractLicense], - instructions: p`Audit npm dependency licenses and classify compatibility. - -package.json: ${p.read("package.json")} - -Installed package licenses: ${p.bash("cat node_modules/*/package.json 2>/dev/null | grep -E '\"name\"|\"license\"' | paste - - | head -60 || echo 'Run npm install first'")} - -For each direct dependency, call extractLicense with the package name and its license field value. -Classify compatibility: -- permissive: MIT, ISC, BSD, Apache-2.0, etc. -- copyleft: GPL, LGPL, AGPL, MPL, etc. -- proprietary: UNLICENSED or empty -- unknown: unrecognized SPDX identifier - -Compute copyleftCount and unknownCount. -Set hasConflicts to true if any copyleft or proprietary licenses are present.`, - output: s.object({ - packages: s.record( - s.object({ - spdxId: s.string, - compatibility: s.enum("permissive", "copyleft", "proprietary", "unknown"), - }) - ), - copyleftCount: s.int, - unknownCount: s.int, - hasConflicts: s.boolean, - }), -}); - -export default depLicenseMatrix; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts deleted file mode 100644 index b00de2e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/26-design-review.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: write a concise migration guide. -const migration = agent({ - model: "typecheck", - output: s.object({ - title: s.string, - steps: s.array(s.string), - examples: s.array(s.object({ - before: s.string, - after: s.string - })) - }), - instructions: `Write a concise migration guide.`, -}); - -export default migration; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts deleted file mode 100644 index 03f3eaf..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/260-git-submodule-health.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parseSubmoduleStatus = defineTool("parseSubmoduleStatus", { - description: "Parse a git submodule status line into structured fields.", - parameters: s.object({ line: s.string }), - handler({ line }) { - const statusChar = line[0] ?? " "; - const rest = line.slice(1).trim(); - const parts = rest.split(/\s+/); - const sha = parts[0] ?? ""; - const path = parts[1] ?? ""; - let status: "clean" | "modified" | "uninitialized" | "conflict" = "clean"; - if (statusChar === "+") status = "modified"; - else if (statusChar === "-") status = "uninitialized"; - else if (statusChar === "U") status = "conflict"; - const describeMatch = rest.match(/\(([^)]+)\)$/); - return { path, sha, status, describe: describeMatch?.[1] }; - }, -}); - -// Agent role: Inventory git submodules and report their health status. -const gitSubmoduleHealth = agent({ - model: "typecheck", - instructions: p`Check the health of all git submodules. - -Submodule status: -${p.bash("git submodule status 2>/dev/null || echo '(no submodules)'")} - -Submodule config: -${p.readOptional(".gitmodules", "(no .gitmodules file)")} - -For each non-empty status line, call parseSubmoduleStatus to extract path, sha, status, and optional describe. -Return submodules array, allClean (true if every status is "clean"), and totalCount.`, - tools: [parseSubmoduleStatus], - output: s.object({ - submodules: s.array( - s.object({ - path: s.path, - sha: s.string, - status: s.enum("clean", "modified", "uninitialized", "conflict"), - describe: s.optional(s.string), - }) - ), - allClean: s.boolean, - totalCount: s.int, - }), -}); - -export default gitSubmoduleHealth; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts deleted file mode 100644 index 1a4a5fc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/261-ts-decorator-scanner.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyDecorator = defineTool("classifyDecorator", { - description: "Classify a TypeScript decorator by its name into a usage type.", - parameters: s.object({ name: s.string }), - handler({ name }) { - const lower = name.toLowerCase(); - if (/^(component|module|injectable|controller|service|directive|pipe)$/.test(lower)) - return { type: "class" }; - if (/^(get|post|put|delete|patch|route|httpcode|header|body|query|param)$/.test(lower)) - return { type: "method" }; - if (/^(column|primarycolumn|primarygeneratedcolumn|onetomany|manytoone|manyto)/.test(lower)) - return { type: "property" }; - if (/^(param|body|query|request|response|headers|ip|session|uploadedfile)$/.test(lower)) - return { type: "parameter" }; - return { type: "unknown" }; - }, -}); - -// Agent role: Scan TypeScript files for decorator usage and classify each decorator. -const tsDecoratorScanner = agent({ - model: "typecheck", - instructions: p`Scan for TypeScript decorator patterns in the repository. - -Decorator occurrences: -${p.bash("grep -rn '@[A-Z][A-Za-z]*' --include='*.ts' . 2>/dev/null | head -60 || echo 'none found'")} - -For each unique decorator name found, call classifyDecorator to get its type. -Build a record keyed by decorator name (without @) with count and type. -Set hasExperimental to true if any decorators from experimental frameworks (e.g., legacy Angular, old NestJS) are found. -Return decorators record, totalCount (sum of all counts), and hasExperimental.`, - tools: [classifyDecorator], - output: s.object({ - decorators: s.record( - s.object({ - count: s.int, - type: s.enum("class", "method", "property", "parameter", "unknown"), - }) - ), - totalCount: s.int, - hasExperimental: s.boolean, - }), -}); - -export default tsDecoratorScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts deleted file mode 100644 index 8ec1244..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/262-dotfile-inventory.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const categorizeDotfile = defineTool("categorizeDotfile", { - description: "Categorize a dotfile by its filename into a purpose category.", - parameters: s.object({ filename: s.string }), - handler({ filename }) { - const name = filename.replace(/^\./, "").toLowerCase(); - if (/^(bash|zsh|fish|profile|bashrc|zshrc|bash_profile|zprofile|inputrc)/.test(name)) - return { category: "shell" }; - if (/^(vimrc|vim|nvim|emacs|nano|editorconfig|prettierrc|eslintrc)/.test(name)) - return { category: "editor" }; - if (/^(gitconfig|gitignore|gitattributes|gitmessage|git)/.test(name)) - return { category: "git" }; - if (/^(ssh|known_hosts|authorized_keys)/.test(name)) - return { category: "ssh" }; - if (/^(npmrc|yarnrc|pnpmfile|curlrc|wgetrc|tmux|screenrc|docker)/.test(name)) - return { category: "tool" }; - return { category: "other" }; - }, -}); - -// Agent role: Inventory dotfiles in the home directory and categorize each one. -const dotfileInventory = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Inventory dotfiles in the home directory and categorize each. - -Dotfiles found: -${p.bash("find ~ -maxdepth 1 -name '.*' -type f 2>/dev/null | head -40 || echo '(none found)'")} - -For each dotfile found, call categorizeDotfile with its filename (basename). -Build a record keyed by filename with category and a short purpose description. -Also compute categorySummary as a record of category → count of dotfiles in that category. -Return dotfiles record, totalFound (integer count), and categorySummary.`, - tools: [categorizeDotfile], - output: s.object({ - dotfiles: s.record( - s.object({ - category: s.enum("shell", "editor", "git", "ssh", "tool", "other"), - purpose: s.string, - }) - ), - totalFound: s.int, - categorySummary: s.record(s.int), - }), -}); - -export default dotfileInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts deleted file mode 100644 index 10be773..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/263-regex-pattern-tester.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -// Agent role: Run regex patterns against test cases and report pass/fail results. -const regexPatternTester = agent({ - model: "typecheck", - addons: repair(), - input: s.object({ - patterns: s.array( - s.object({ - name: s.string, - regex: s.string, - testCases: s.array( - s.object({ - input: s.string, - shouldMatch: s.boolean, - }) - ), - }) - ), - }), - instructions: p`Run each regex pattern against its test cases and report results. - -Input patterns and test cases: -${p.json("input")} - -Use the runRegexTest tool for each pattern+testCase combination. -For each pattern, build a result with name, passed count, failed count, and allPassed. -Return results array, totalPatterns, passCount (patterns where allPassed=true), -failCount (patterns where allPassed=false), and overall allPassed.`, - tools: [ - defineTool("runRegexTest", { - description: "Test a regex pattern against an input string and return whether it matches.", - parameters: s.object({ regex: s.string, input: s.string }), - handler({ regex, input }) { - try { - return { matched: new RegExp(regex).test(input) }; - } catch (e) { - return { matched: false, error: String(e) }; - } - }, - }), - ], - output: s.object({ - results: s.array( - s.object({ - name: s.string, - passed: s.int, - failed: s.int, - allPassed: s.boolean, - }) - ), - totalPatterns: s.int, - passCount: s.int, - failCount: s.int, - allPassed: s.boolean, - }), -}); - -export default regexPatternTester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts deleted file mode 100644 index f4079bb..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/264-commit-churn-classifier.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: classify repository files by commit churn frequency and assign a risk level. -const commitChurnClassifier = agent({ - model: "typecheck", - addons: steering({ message: "Assign riskLevel based on churnCount: >20=critical, >10=volatile, >5=active, else stable. Only include files from the churn output." }), - instructions: p`Classify repository files by commit churn (how frequently they change). - -File churn counts from git history: -${p.bash("git log --name-only --format='' 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} - -For each file in the output, parse the churn count and assign a riskLevel: -- critical: churnCount > 20 -- volatile: churnCount > 10 -- active: churnCount > 5 -- stable: churnCount <= 5 - -Return a record keyed by file path with churnCount (integer) and riskLevel.`, - output: s.record( - s.object({ - churnCount: s.int, - riskLevel: s.enum("stable", "active", "volatile", "critical"), - }) - ), -}); - -export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts deleted file mode 100644 index 4611bf4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/265-npm-package-size.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -// Agent role: estimate npm package publish size and rate it with a recommendation. -const npmPackageSize = agent({ - model: "typecheck", - instructions: p`Estimate the npm package publish size and rate it. - -Files included in npm publish (dry run): -${p.bash("npm pack --dry-run 2>&1 | head -40")} - -Workspace size: -${p.bash("du -sh . 2>/dev/null | cut -f1")} - -Package metadata: -${p.readOptional("package.json", "{}")} - -Parse the npm pack output to extract individual file sizes. Use classifySize on the total. -List the top files by size. Provide a recommendation if the package is large. -Return estimatedSizeKb, topFiles (up to 5), sizeRating, and recommendation.`, - tools: [ - defineTool("classifySize", { - description: "Classify a package size in KB into a rating tier.", - parameters: s.object({ sizeKb: s.number }), - handler({ sizeKb }) { - if (sizeKb < 10) return { rating: "tiny" }; - if (sizeKb < 100) return { rating: "small" }; - if (sizeKb < 1000) return { rating: "medium" }; - if (sizeKb < 10000) return { rating: "large" }; - return { rating: "xlarge" }; - }, - }), - ], - output: s.object({ - estimatedSizeKb: s.number, - topFiles: s.array(s.object({ path: s.path, sizeKb: s.number })), - sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), - recommendation: s.string, - }), -}); - -export default npmPackageSize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts deleted file mode 100644 index a775f21..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/266-tsconfig-option-analyzer.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseTsConfigOption = defineTool("parseTsConfigOption", { - description: "Classify a tsconfig compilerOption by name and infer if it is recommended.", - parameters: s.object({ optionName: s.string }), - handler({ optionName }) { - const strictOptions = new Set(["strict", "noImplicitAny", "strictNullChecks", "strictFunctionTypes", "strictBindCallApply", "strictPropertyInitialization", "noImplicitThis", "alwaysStrict", "useUnknownInCatchVariables", "exactOptionalPropertyTypes", "noUncheckedIndexedAccess"]); - const perfOptions = new Set(["incremental", "composite", "tsBuildInfoFile", "isolatedModules", "skipLibCheck", "skipDefaultLibCheck"]); - const outputOptions = new Set(["outDir", "outFile", "rootDir", "declarationDir", "declaration", "declarationMap", "sourceMap", "inlineSources", "inlineSourceMap", "emitDeclarationOnly", "noEmit"]); - const pathOptions = new Set(["paths", "baseUrl", "rootDirs", "typeRoots", "types"]); - if (strictOptions.has(optionName)) return { category: "strict", recommended: true }; - if (perfOptions.has(optionName)) return { category: "perf", recommended: true }; - if (outputOptions.has(optionName)) return { category: "output", recommended: false }; - if (pathOptions.has(optionName)) return { category: "paths", recommended: false }; - return { category: "misc", recommended: false }; - }, -}); - -// Agent role: analyze tsconfig.json compiler options and classify each one. -const tsconfigOptionAnalyzer = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Analyze TypeScript compiler options from tsconfig files in this project. - -Main tsconfig.json: -${p.read("tsconfig.json")} - -Additional tsconfig files found: -${p.glob("tsconfig.*.json")} - -For each compilerOption key found in the tsconfig files, call parseTsConfigOption to get -its category and recommended status. -Build an options record keyed by option name with value (from config), category, and recommended. -Count strictCount (number of strict-category options enabled). -Set hasIsolatedModules to true if isolatedModules is set to true. -List all config file paths found in configFilesFound.`, - tools: [parseTsConfigOption], - output: s.object({ - options: s.record( - s.object({ - value: s.unknown, - category: s.enum("strict", "perf", "output", "paths", "misc"), - recommended: s.boolean, - }) - ), - strictCount: s.int, - hasIsolatedModules: s.boolean, - configFilesFound: s.array(s.string), - }), -}); - -export default tsconfigOptionAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts deleted file mode 100644 index dc31342..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/267-git-patch-summarizer.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const extractPatchMetadata = defineTool("extractPatchMetadata", { - description: "Extract metadata (author, subject, stats) from a git format-patch block.", - parameters: s.object({ patchBlock: s.string }), - handler({ patchBlock }) { - const authorMatch = patchBlock.match(/^From:\s*(.+)$/m); - const subjectMatch = patchBlock.match(/^Subject:\s*(?:\[PATCH[^\]]*\]\s*)?(.+)$/m); - const statsMatch = patchBlock.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/); - return { - author: authorMatch?.[1]?.trim() ?? "unknown", - subject: subjectMatch?.[1]?.trim() ?? "unknown", - filesChanged: statsMatch ? parseInt(statsMatch[1] ?? "0", 10) : 0, - insertions: statsMatch ? parseInt(statsMatch[2] ?? "0", 10) : 0, - deletions: statsMatch ? parseInt(statsMatch[3] ?? "0", 10) : 0, - }; - }, -}); - -// Agent role: summarize git patches from recent commits with author and diffstat info. -const gitPatchSummarizer = agent({ - model: "typecheck", - addons: steering({ message: "Split the patch output by 'From ' header lines to identify individual patch blocks before calling extractPatchMetadata." }), - instructions: p`Summarize the most recent git commits as formatted patches. - -Recent patches (last 5 commits): -${p.bash("git format-patch -5 --stdout 2>/dev/null | head -300 || echo '(no commits)'")} - -Split the output into individual patch blocks (each starts with a 'From ' line). -Call extractPatchMetadata for each block. -Return patches array with author, subject, filesChanged, insertions, deletions. -Set totalPatches to the number of patches found. -Set topContributor to the author with the most patches (omit if all are the same or none found).`, - tools: [extractPatchMetadata], - output: s.object({ - patches: s.array( - s.object({ - author: s.string, - subject: s.string, - filesChanged: s.int, - insertions: s.int, - deletions: s.int, - }) - ), - totalPatches: s.int, - topContributor: s.optional(s.string), - }), -}); - -export default gitPatchSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts deleted file mode 100644 index 8d018e2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/268-npm-lifecycle-analyzer.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyScript = defineTool("classifyScript", { - description: "Classify an npm script by name into a lifecycle category.", - parameters: s.object({ scriptName: s.string, command: s.string }), - handler({ scriptName }) { - const name = scriptName.toLowerCase(); - const isHook = /^(pre|post)/.test(name); - if (/build|compile|bundle|webpack|rollup|esbuild/.test(name)) return { category: "build", isHook }; - if (/test|jest|vitest|mocha|spec/.test(name)) return { category: "test", isHook }; - if (/lint|eslint|tslint|prettier|format/.test(name)) return { category: "lint", isHook }; - if (/release|publish|deploy|version|changelog/.test(name)) return { category: "release", isHook }; - if (isHook) return { category: "hook", isHook: true }; - return { category: "other", isHook: false }; - }, -}); - -// Agent role: analyze npm lifecycle scripts in package.json and classify each one. -const npmLifecycleAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze the npm lifecycle scripts defined in package.json. - -package.json contents: -${p.read("package.json")} - -For each entry in the "scripts" field, call classifyScript with the script name and command. -Build a scripts record keyed by script name with command, category, and isHook. -Count hookCount (scripts where isHook is true). -List missingRecommended: which of ["test", "build", "lint"] are absent from scripts. -Set hasTestScript and hasBuildScript based on whether those categories exist.`, - tools: [classifyScript], - output: s.object({ - scripts: s.record( - s.object({ - command: s.string, - category: s.enum("build", "test", "lint", "release", "hook", "other"), - isHook: s.boolean, - }) - ), - hookCount: s.int, - missingRecommended: s.array(s.string), - hasTestScript: s.boolean, - hasBuildScript: s.boolean, - }), -}); - -export default npmLifecycleAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts deleted file mode 100644 index 57d2703..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/269-ts-jsdoc-coverage.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const analyzeFunctionComments = defineTool("analyzeFunctionComments", { - description: "Count exported functions with and without JSDoc comments in a TypeScript file.", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - let content: string; - try { - content = await readFile(filePath, "utf8"); - } catch { - return { documentedCount: 0, undocumentedCount: 0, coverage: 0 }; - } - const lines = content.split("\n"); - let documentedCount = 0; - let undocumentedCount = 0; - for (let i = 0; i < lines.length; i++) { - const line = lines[i] ?? ""; - if (/^\s*export\s+(async\s+)?function\s+\w+|^\s*export\s+const\s+\w+\s*=\s*(async\s*)?\(/.test(line)) { - const prevLine = lines[i - 1] ?? ""; - const prevPrevLine = lines[i - 2] ?? ""; - if (/\*\//.test(prevLine) || /\*\//.test(prevPrevLine)) { - documentedCount++; - } else { - undocumentedCount++; - } - } - } - const total = documentedCount + undocumentedCount; - return { - documentedCount, - undocumentedCount, - coverage: total > 0 ? Math.round((documentedCount / total) * 100) / 100 : 1, - }; - }, -}); - -// Agent role: measure JSDoc comment coverage for exported functions across TypeScript files. -const tsJsdocCoverage = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Measure JSDoc coverage for exported functions in TypeScript source files. - -TypeScript files in this project: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -20")} - -For each file path listed, call analyzeFunctionComments to get documentedCount, -undocumentedCount, and coverage (0–1 ratio). -Build the files record keyed by file path. -Compute overall totals: totalFunctions, documentedFunctions, coveragePercent (0–100). -List wellDocumentedFiles: file paths where coverage >= 0.8.`, - tools: [analyzeFunctionComments], - output: s.object({ - files: s.record( - s.object({ - documentedCount: s.int, - undocumentedCount: s.int, - coverage: s.number, - }) - ), - overall: s.object({ - totalFunctions: s.int, - documentedFunctions: s.int, - coveragePercent: s.number, - }), - wellDocumentedFiles: s.array(s.path), - }), -}); - -export default tsJsdocCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts deleted file mode 100644 index b9f45ea..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/27-dependency-upgrade-plan.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: review the design proposal for simplicity and maintainability. -const designReview = agent({ - model: "typecheck", - output: s.object({ - decision: s.enum("approve", "revise", "reject"), - strengths: s.array(s.string), - concerns: s.array(s.string), - requiredChanges: s.array(s.string) - }), - instructions: `Review the design proposal for simplicity and maintainability.`, -}); - -export default designReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts deleted file mode 100644 index 3f0b595..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/270-dotfile-inventory-mapper.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const categorizeDotfile = defineTool("categorizeDotfile", { - description: "Categorize a dotfile by its filename into a purpose and category.", - parameters: s.object({ filename: s.string }), - handler({ filename }) { - const f = filename.toLowerCase(); - if (f.includes("bash") || f.includes("zsh") || f.includes("fish") || f.includes("profile") || f.includes("aliases")) { - return { purpose: "Shell configuration and aliases", category: "shell" as const }; - } - if (f.includes("vim") || f.includes("emacs") || f.includes("vscode") || f.includes("editorconfig") || f.includes("nvim")) { - return { purpose: "Editor settings and configuration", category: "editor" as const }; - } - if (f.includes("git") || f.includes("gitconfig") || f.includes("gitignore")) { - return { purpose: "Git version control configuration", category: "git" as const }; - } - if (f.includes("ssh") || f.includes("gnupg") || f.includes("gpg")) { - return { purpose: "SSH or GPG security configuration", category: "ssh" as const }; - } - if (f.includes("npm") || f.includes("yarn") || f.includes("pip") || f.includes("cargo") || f.includes("gem")) { - return { purpose: "Package manager settings", category: "package-manager" as const }; - } - return { purpose: "Miscellaneous dotfile configuration", category: "misc" as const }; - }, -}); - -// Agent role: inventory dotfiles in the home directory and categorize them by purpose. -const dotfileInventoryMapper = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Inventory dotfiles found in the home directory. - -Discovered dotfiles: -${p.bash("find ~ -maxdepth 2 -name '.*' -type f 2>/dev/null | head -50")} - -For each file path, call categorizeDotfile with just the filename (basename). -Build the dotfiles record keyed by filename with purpose and category. -Count totalFound (number of entries in dotfiles). -Build categorySummary as a record of category -> count of files in that category.`, - tools: [categorizeDotfile], - output: s.object({ - dotfiles: s.record( - s.object({ - purpose: s.string, - category: s.enum("shell", "editor", "git", "ssh", "package-manager", "misc"), - }) - ), - totalFound: s.int, - categorySummary: s.record(s.int), - }), -}); - -export default dotfileInventoryMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts deleted file mode 100644 index 7693222..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/271-regex-pattern-tester.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { agent, s, defineTool, repair } from "rig"; - -const runRegexTest = defineTool("runRegexTest", { - description: "Test a regex pattern against an input string and return whether it matches.", - parameters: s.object({ regex: s.string, input: s.string }), - handler({ regex, input }) { - try { - const matched = new RegExp(regex).test(input); - return { matched, error: undefined }; - } catch (e) { - return { matched: false, error: String(e) }; - } - }, -}); - -// Agent role: run all test cases for each regex pattern and report pass/fail results. -const regexPatternTester = agent({ - model: "typecheck", - addons: repair(), - input: s.object({ - patterns: s.array( - s.object({ - name: s.string, - regex: s.string, - testCases: s.array( - s.object({ input: s.string, shouldMatch: s.boolean }) - ), - }) - ), - }), - instructions: `For each pattern in the input, call runRegexTest for every test case. -A test case passes when the matched result equals shouldMatch. -Collect failedCases (input, expected, got) for each pattern. -A pattern passes when all test cases pass. -Count passCount (patterns where passed=true) and failCount. -allPassed is true when failCount === 0.`, - tools: [runRegexTest], - output: s.object({ - results: s.array( - s.object({ - name: s.string, - passed: s.boolean, - failedCases: s.array( - s.object({ input: s.string, expected: s.boolean, got: s.boolean }) - ), - }) - ), - passCount: s.int, - failCount: s.int, - allPassed: s.boolean, - }), -}); - -export default regexPatternTester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts deleted file mode 100644 index 1a3fec5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/272-commit-churn-classifier.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const classifyRisk = defineTool("classifyRisk", { - description: "Classify a file's churn risk level based on how many times it has changed.", - parameters: s.object({ churnCount: s.int }), - handler({ churnCount }) { - if (churnCount <= 3) return "stable" as const; - if (churnCount <= 10) return "active" as const; - if (churnCount <= 25) return "volatile" as const; - return "critical" as const; - }, -}); - -// Agent role: analyze git commit history to classify file churn risk. -const commitChurnClassifier = agent({ - model: "typecheck", - addons: steering(), - instructions: p`Analyze file churn from git commit history. - -File change frequency (count + filename): -${p.bash("git log --name-only --format='' | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} - -For each line, parse the count and file path. -Call classifyRisk with the churnCount to get the riskLevel. -Build a record keyed by file path with churnCount and riskLevel. -Include only files that appear in the output above.`, - tools: [classifyRisk], - output: s.record( - s.object({ - churnCount: s.int, - riskLevel: s.enum("stable", "active", "volatile", "critical"), - }) - ), -}); - -export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts deleted file mode 100644 index 4afc492..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/273-npm-package-size-estimator.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifySize = defineTool("classifySize", { - description: "Classify a package size into a tier based on kilobytes.", - parameters: s.object({ sizeKb: s.number }), - handler({ sizeKb }) { - if (sizeKb < 10) return "tiny" as const; - if (sizeKb < 100) return "small" as const; - if (sizeKb < 500) return "medium" as const; - if (sizeKb < 2000) return "large" as const; - return "xlarge" as const; - }, -}); - -// Agent role: estimate NPM package publish size and classify it. -const npmPackageSizeEstimator = agent({ - model: "typecheck", - instructions: p`Estimate the published NPM package size. - -npm pack dry-run output: -${p.bash("npm pack --dry-run 2>&1")} - -Parse the output to find: -1. The total package size in KB (look for "package size:" or "Tarball Details" lines). -2. The top individual files with their sizes. - -Call classifySize with the estimatedSizeKb to get the sizeRating. -List the top files (up to 10) as topFiles array with path and sizeKb. -Write a brief recommendation about the package size.`, - tools: [classifySize], - output: s.object({ - estimatedSizeKb: s.number, - topFiles: s.array(s.object({ path: s.string, sizeKb: s.number })), - sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), - recommendation: s.string, - }), -}); - -export default npmPackageSizeEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts deleted file mode 100644 index a59b557..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/274-ts-branch-coverage-analyzer.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze TypeScript file content to identify branches and their coverage. -const branchAnalyzer = agent({ - model: "typecheck", - instructions: `Given the TypeScript file content below, identify all branch points. -For each branch, extract: functionName (surrounding function or "module-level"), line number, -branchType (if/ternary/switch/logical/nullish), and covered (true if the branch has a test or always executes). -Return the branches array.`, - input: s.object({ fileContent: s.string, filePath: s.string }), - output: s.array( - s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "logical", "nullish"), - covered: s.boolean, - }) - ), -}); - -// Agent role: coordinate branch coverage analysis for a TypeScript file. -const tsBranchCoverageAnalyzer = agent({ - model: "typecheck", - input: s.object({ filePath: s.string }), - instructions: p`Analyze TypeScript branch coverage for the file at the path provided in input. - -Read the file content: -${p.readInput("filePath")} - -Delegate analysis to the branchAnalyzer subagent passing fileContent and filePath. -Aggregate the results: count totalBranches, coveredBranches, uncoveredBranches. -Compute coveragePercent as (coveredBranches / totalBranches * 100), 0 if no branches.`, - agents: { branchAnalyzer }, - output: s.object({ - branches: s.array( - s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "logical", "nullish"), - covered: s.boolean, - }) - ), - summary: s.object({ - totalBranches: s.int, - coveredBranches: s.int, - uncoveredBranches: s.int, - coveragePercent: s.number, - }), - }), -}); - -export default tsBranchCoverageAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts deleted file mode 100644 index c5848f4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/275-env-variable-type-inferrer.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const inferType = defineTool("inferType", { - description: "Infer the type of an environment variable value using regex patterns.", - parameters: s.object({ key: s.string, value: s.string }), - handler({ value }) { - if (/^\d+(\.\d+)?$/.test(value)) return "number" as const; - if (/^(true|false)$/i.test(value)) return "boolean" as const; - if (/^https?:\/\//.test(value)) return "url" as const; - if (/^[/~.]/.test(value)) return "path" as const; - if (value.length === 0) return "unknown" as const; - return "string" as const; - }, -}); - -// Agent role: read .env.example and infer the type of each variable. -const envVariableTypeInferrer = agent({ - model: "typecheck", - instructions: p`Infer types for environment variables from .env.example. - -File contents: -${p.readOptional(".env.example", "# no .env.example found")} - -For each non-comment, non-empty line, parse KEY=VALUE. -Call inferType with the key and value to determine the type. -Write a one-line description for each variable based on its key name and inferred type. -Build the variables record keyed by variable name. -Set allDocumented to true if all variables have non-empty descriptions.`, - tools: [inferType], - output: s.object({ - variables: s.record( - s.object({ - type: s.enum("string", "number", "boolean", "url", "path", "unknown"), - description: s.string, - }) - ), - allDocumented: s.boolean, - }), -}); - -export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts deleted file mode 100644 index 278d132..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/276-git-hook-installer.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const checkHooksDir = defineTool("checkHooksDir", { - description: "Check if the .git/hooks directory exists.", - parameters: s.object({}), - async handler() { - const { access } = await import("node:fs/promises"); - try { - await access(".git/hooks"); - return { exists: true }; - } catch { - return { exists: false }; - } - }, -}); - -// Agent role: install git hook scripts into .git/hooks for the current repository. -const gitHookInstaller = agent({ - model: "typecheck", - addons: repair(), - input: s.object({ - hooks: s.array( - s.object({ - name: s.string, - script: s.string, - description: s.string, - }) - ), - }), - instructions: p`Install git hook scripts into the .git/hooks directory. - -Existing hooks directory: -${p.bash("ls .git/hooks 2>/dev/null || echo 'no .git/hooks directory'")} - -First call checkHooksDir to verify the directory exists. -For each hook in input.hooks: -- If .git/hooks exists, write the script to .git/hooks/ using a write operation, then run chmod +x via bash. -- If .git/hooks does not exist, add the hook name to skippedHooks. -Track writtenHooks as array of { name, path } for each successfully written hook. -Set totalWritten and allWritten accordingly.`, - tools: [checkHooksDir], - output: s.object({ - writtenHooks: s.array(s.object({ name: s.string, path: s.string })), - skippedHooks: s.array(s.string), - totalWritten: s.int, - allWritten: s.boolean, - }), -}); - -export default gitHookInstaller; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts deleted file mode 100644 index 53284cd..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/277-ts-type-guard-generator.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const extractInterfaces = defineTool("extractInterfaces", { - description: "Extract interface names from a TypeScript source file.", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf8"); - const matches = [...content.matchAll(/interface\s+(\w+)/g)]; - return { interfaceNames: matches.map((m: RegExpMatchArray) => m[1] as string) }; - } catch { - return { interfaceNames: [] }; - } - }, -}); - -// Agent role: generate TypeScript type guard functions for each interface in a source file. -const tsTypeGuardGenerator = agent({ - model: "typecheck", - addons: repair(), - input: s.object({ sourceFile: s.path, outputFile: s.path }), - instructions: p`Generate TypeScript type guard functions for interfaces found in a source file. - -Source file content: -${p.readInput("sourceFile")} - -1. Call extractInterfaces with the sourceFile path to get all interface names. -2. For each interface, generate a type guard function: \`function is(val: unknown): val is \`. -3. Write the generated guard functions to the outputFile path. -4. Return generatedGuards listing interfaceName and guardFunctionName for each guard.`, - tools: [extractInterfaces], - output: s.object({ - generatedGuards: s.array( - s.object({ interfaceName: s.string, guardFunctionName: s.string }) - ), - outputFile: s.path, - totalGenerated: s.int, - }), -}); - -export default tsTypeGuardGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts deleted file mode 100644 index e9cb084..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/278-json-fixture-anonymizer.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const anonymizeValue = defineTool("anonymizeValue", { - description: "Return an anonymized replacement for a field value based on its name and type.", - parameters: s.object({ fieldName: s.string, value: s.unknown, fieldType: s.string }), - handler({ fieldName, fieldType }) { - const name = fieldName.toLowerCase(); - if (name.includes("email")) return "[email@example.com]"; - if (name.includes("phone") || name.includes("tel")) return "[000-000-0000]"; - if (name.includes("name") || name.includes("user")) return "[REDACTED_NAME]"; - if (name.includes("address") || name.includes("street")) return "[REDACTED_ADDRESS]"; - if (name.includes("ip")) return "0.0.0.0"; - if (fieldType === "number") return 0; - if (fieldType === "boolean") return false; - return "[REDACTED]"; - }, -}); - -// Agent role: anonymize sensitive fields in a JSON fixture file. -const jsonFixtureAnonymizer = agent({ - model: "typecheck", - input: s.object({ - inputFile: s.path, - outputFile: s.path, - fieldsToAnonymize: s.array(s.string), - }), - instructions: p`Anonymize sensitive fields in a JSON fixture file. - -Input file content: -${p.readInput("inputFile")} - -For each field name in input.fieldsToAnonymize, call anonymizeValue with the field name, -current value, and value type to get the replacement. -Replace all matching field values throughout the JSON structure. -Write the anonymized JSON to input.outputFile. -Count fieldsAnonymized (total replacements made) and totalRecords (array length or 1 for object).`, - tools: [anonymizeValue], - output: s.object({ - fieldsAnonymized: s.int, - totalRecords: s.int, - outputPath: s.path, - anonymizedFields: s.array(s.string), - }), -}); - -export default jsonFixtureAnonymizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts deleted file mode 100644 index 4aaa1a0..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/279-csv-to-markdown-table.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseCSVRow = defineTool("parseCSVRow", { - description: "Split a CSV line into trimmed cell values.", - parameters: s.object({ line: s.string, delimiter: s.string }), - handler({ line, delimiter }) { - return { cells: line.split(delimiter).map((cell: string) => cell.trim()) }; - }, -}); - -// Agent role: convert a CSV file to a Markdown table and write it to an output file. -const csvToMarkdownTable = agent({ - model: "typecheck", - addons: repair(), - input: s.object({ - csvFile: s.path, - outputFile: s.path, - includeStats: s.boolean, - }), - instructions: p`Convert a CSV file to a Markdown table. - -CSV file content: -${p.readInput("csvFile")} - -1. Call parseCSVRow for the first line with delimiter "," to get the headers. -2. Call parseCSVRow for each subsequent non-empty line to get row cells. -3. Build a Markdown table: header row, separator row (---), then data rows. -4. If input.includeStats is true, append a stats section with row/column counts. -5. Write the complete Markdown output to input.outputFile. -6. Return rowCount (data rows), columnCount, outputFile path, and headers array.`, - tools: [parseCSVRow], - output: s.object({ - rowCount: s.int, - columnCount: s.int, - outputFile: s.path, - headers: s.array(s.string), - }), -}); - -export default csvToMarkdownTable; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts deleted file mode 100644 index b7b73ed..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/28-license-check.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: plan safe dependency upgrades. -const upgradePlan = agent({ - model: "typecheck", - output: s.object({ - upgrades: s.array(s.object({ - package: s.string, - from: s.string, - to: s.string, - risk: s.string - })), - order: s.array(s.string) - }), - instructions: `Plan safe dependency upgrades.`, -}); -export default upgradePlan; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts deleted file mode 100644 index 2652e51..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/280-commit-churn-classifier.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: classify repository files by commit churn frequency and assign a risk level. -const commitChurnClassifier = agent({ - model: "typecheck", - addons: steering({ message: "Be precise: assign riskLevel based on churnCount: >20=critical, >10=volatile, >5=active, else stable." }), - instructions: p`Classify repository files by how frequently they are committed (churn). - -File churn counts from last 200 commits: -${p.bash("git log --name-only --format='' HEAD~200..HEAD 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -40")} - -For each file, parse the churn count and assign a riskLevel: -- critical: churnCount > 20 -- volatile: churnCount > 10 -- active: churnCount > 5 -- stable: churnCount <= 5 - -Return a record keyed by file path with churnCount (integer) and riskLevel.`, - output: s.record( - s.object({ - churnCount: s.int, - riskLevel: s.enum("stable", "active", "volatile", "critical"), - }) - ), -}); - -export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts deleted file mode 100644 index f63a55e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/281-npm-package-size-estimator.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const classifySize = defineTool("classifySize", { - description: "Classify a package size in KB into a tier rating.", - parameters: s.object({ sizeKb: s.number }), - handler({ sizeKb }: { sizeKb: number }) { - if (sizeKb < 10) return "tiny" as const; - if (sizeKb < 100) return "small" as const; - if (sizeKb < 500) return "medium" as const; - if (sizeKb < 2000) return "large" as const; - return "xlarge" as const; - }, -}); - -// Agent role: estimate the NPM package size and rate it by tier. -const npmPackageSizeEstimator = agent({ - model: "typecheck", - instructions: p`Estimate the NPM package size for this project. - -Pack dry-run output: -${p.bash("npm pack --dry-run 2>&1 | tail -20")} - -Directory size: -${p.bash("du -sh . 2>/dev/null | head -5")} - -Use classifySize tool with the estimated total size in KB to get the sizeRating. -List the top files by size and provide a brief recommendation.`, - tools: [classifySize], - output: s.object({ - estimatedSizeKb: s.number, - topFiles: s.array(s.object({ name: s.string, sizeKb: s.number })), - sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), - recommendation: s.string, - }), -}); - -export default npmPackageSizeEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts deleted file mode 100644 index 49e35fc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/282-ts-branch-coverage-analyzer.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, p, s } from "rig"; - -const branchItem = s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "nullish"), - covered: s.boolean, -}); - -// Agent role: extract all branch points from the provided TypeScript source code. -const branchAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze the TypeScript source code provided in the input and list every branch point (if/ternary/switch/nullish coalescing). For each branch, identify the enclosing function name, line number, branch type, and whether it appears covered (has a test or usage path). Return an array of branch objects.`, - input: s.object({ filePath: s.path }), - output: s.array(branchItem), -}); - -// Agent role: coordinate branch coverage analysis for a TypeScript file. -const tsBranchCoverageAnalyzer = agent({ - model: "typecheck", - input: s.object({ filePath: s.path }), - instructions: p`Perform branch coverage analysis on a TypeScript file. - -File content: -${p.readInput("filePath")} - -Delegate the analysis to the branchAnalyzer subagent, passing the filePath. -Collect its output (an array of branch objects), then compute a summary with totalBranches, coveredBranches, and uncoveredBranches counts.`, - output: s.object({ - branches: s.array(branchItem), - summary: s.object({ - totalBranches: s.int, - coveredBranches: s.int, - uncoveredBranches: s.int, - }), - }), - agents: { branchAnalyzer }, -}); - -export default tsBranchCoverageAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts deleted file mode 100644 index e0b74be..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/283-env-variable-type-inferrer.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const inferVarType = defineTool("inferVarType", { - description: "Infer the type of an environment variable value using regex heuristics.", - parameters: s.object({ value: s.string }), - handler({ value }: { value: string }) { - if (/^https?:\/\//i.test(value)) return "url" as const; - if (/^(true|false|yes|no|1|0)$/i.test(value)) return "boolean" as const; - if (/^\d+(\.\d+)?$/.test(value)) return "number" as const; - if (/^(\/|\.\/|~\/)/.test(value) || /\.(txt|json|yaml|yml|pem|key|crt)$/.test(value)) return "path" as const; - if (value === "") return "unknown" as const; - return "string" as const; - }, -}); - -// Agent role: infer types for all environment variables defined in .env.example. -const envVariableTypeInferrer = agent({ - model: "typecheck", - instructions: p`Infer the type of each environment variable defined in the .env.example file. - -.env.example contents: -${p.readOptional(".env.example", "(no .env.example found)")} - -For each KEY=VALUE line, call inferVarType with the value to get its type. Generate a short description of what each variable likely controls. Set allDocumented to true only if every variable has a non-empty value or inline comment hint.`, - tools: [inferVarType], - output: s.object({ - vars: s.record( - s.object({ - type: s.enum("string", "number", "boolean", "url", "path", "unknown"), - description: s.string, - }) - ), - allDocumented: s.boolean, - }), -}); - -export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts deleted file mode 100644 index fae0e4f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/284-makefile-target-extractor.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const parseTargets = defineTool("parseTargets", { - description: "Parse Makefile content to extract phony and real targets with descriptions.", - parameters: s.object({ content: s.string }), - handler({ content }: { content: string }) { - const lines = content.split("\n"); - const phonySet = new Set(); - const targets: Array<{ name: string; isPhony: boolean; hasHelp: boolean; description?: string }> = []; - - for (const line of lines) { - const phonyMatch = line.match(/^\.PHONY\s*:\s*(.+)/); - if (phonyMatch) { - for (const t of phonyMatch[1].split(/\s+/)) phonySet.add(t.trim()); - } - } - - const targetRe = /^([a-zA-Z0-9_\-./]+)\s*:/; - for (let i = 0; i < lines.length; i++) { - const m = lines[i].match(targetRe); - if (m && !m[1].startsWith(".")) { - const name = m[1]; - const helpLine = i > 0 ? lines[i - 1] : ""; - const hasHelp = /##/.test(helpLine) || /##/.test(lines[i]); - const description = helpLine.match(/##\s*(.+)/)?.[1]?.trim(); - targets.push({ name, isPhony: phonySet.has(name), hasHelp, ...(description ? { description } : {}) }); - } - } - return targets; - }, -}); - -// Agent role: extract and classify Makefile targets. -const makefileTargetExtractor = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Extract and classify targets from the project Makefile. - -Makefile contents: -${p.readOptional("Makefile", "(no Makefile found)")} - -Call parseTargets with the full Makefile content. Return the array of targets and include totalCount (all targets) and phonyCount (targets where isPhony is true).`, - tools: [parseTargets], - output: s.object({ - targets: s.array( - s.object({ - name: s.string, - isPhony: s.boolean, - hasHelp: s.boolean, - description: s.optional(s.string), - }) - ), - totalCount: s.int, - phonyCount: s.int, - }), -}); - -export default makefileTargetExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts deleted file mode 100644 index 0c59a98..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/285-test-fixture-generator.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze a function signature and return its parameters and return type. -const signatureAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze the TypeScript source provided in the input. Extract the signature details for the specified function: its parameters (name and type), return type, and any JSDoc description. Return structured signature details.`, - input: s.object({ sourceFile: s.path, functionName: s.string }), - output: s.object({ - functionName: s.string, - parameters: s.array(s.object({ name: s.string, type: s.string })), - returnType: s.string, - description: s.optional(s.string), - }), -}); - -// Agent role: generate a test fixture for a specific function in a TypeScript source file. -const testFixtureGenerator = agent({ - model: "typecheck", - input: s.object({ sourceFile: s.path, functionName: s.string }), - instructions: p`Generate a test fixture file for the specified function. - -Source file content: -${p.readInput("sourceFile")} - -1. Delegate to signatureAnalyzer to get the function signature for the function named in the input. -2. Using the signature, generate fixture code: example inputs, mock helpers, and a vitest describe block. -3. Write the fixture code to fixture.ts: ${p.writeOutput("fixtureCode", "fixture.ts")} -4. Return fixtureCode (the full fixture source), the required imports, and suggestedFileName.`, - output: s.object({ - fixtureCode: s.string, - imports: s.array(s.string), - suggestedFileName: s.path, - }), - agents: { signatureAnalyzer }, -}); - -export default testFixtureGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts deleted file mode 100644 index d3c02e6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/286-toml-config-analyzer.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const analyzeTomlFile = defineTool("analyzeTomlFile", { - description: "Read a TOML file and extract its top-level section headers and key count.", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }: { filePath: string }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf8"); - const sections = [...content.matchAll(/^\[([^\]]+)\]/gm)].map((m: RegExpMatchArray) => m[1] as string); - const keyCount = (content.match(/^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*=/gm) ?? []).length; - const hasRequired = sections.includes("package") || sections.includes("tool") || keyCount > 0; - return { sections, keyCount, hasRequired }; - } catch { - return { sections: [], keyCount: 0, hasRequired: false }; - } - }, -}); - -// Agent role: analyze all TOML config files in the workspace and summarize their sections. -const tomlConfigAnalyzer = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Analyze all TOML config files found in the workspace. - -TOML files found: -${p.glob("**/*.toml")} - -For each file path listed above, call analyzeTomlFile to extract its sections, keyCount, and hasRequired flag. Return a record keyed by file path.`, - tools: [analyzeTomlFile], - output: s.record( - s.object({ - sections: s.array(s.string), - keyCount: s.int, - hasRequired: s.boolean, - }) - ), -}); - -export default tomlConfigAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts deleted file mode 100644 index 38b8d91..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/287-git-checkpoint-summarizer.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const classifyCheckpoint = defineTool("classifyCheckpoint", { - description: "Classify a git checkpoint line as stash, commit, tag, or branch.", - parameters: s.object({ line: s.string }), - handler({ line }: { line: string }) { - if (line.startsWith("stash@{")) return "stash" as const; - if (/^refs\/tags\//.test(line)) return "tag" as const; - if (/^refs\/heads\//.test(line)) return "branch" as const; - return "commit" as const; - }, -}); - -// Agent role: summarize git checkpoints (stashes and recent commits) in the repository. -const gitCheckpointSummarizer = agent({ - model: "typecheck", - instructions: p`Summarize the git checkpoints (stashes and recent commits) for this repository. - -Stash list: -${p.bash("git stash list 2>/dev/null || echo '(no stashes)'")} - -Recent commits: -${p.bash("git log --oneline -20 2>/dev/null || echo '(no commits)'")} - -For each stash entry and each commit line, call classifyCheckpoint to determine its type. Build the checkpoints array with ref, type, and message fields. Set latestCheckpoint to the most recent commit hash or stash ref, and totalCount to the combined count.`, - tools: [classifyCheckpoint], - output: s.object({ - checkpoints: s.array( - s.object({ - ref: s.string, - type: s.enum("stash", "commit", "tag", "branch"), - message: s.string, - }) - ), - latestCheckpoint: s.optional(s.string), - totalCount: s.int, - }), -}); - -export default gitCheckpointSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts deleted file mode 100644 index df463d7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/288-ts-literal-union-extractor.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, defineTool, p, s, steering } from "rig"; - -const extractLiteralUnions = defineTool("extractLiteralUnions", { - description: "Extract string literal union type declarations from a TypeScript file.", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }: { filePath: string }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf8"); - const re = /type\s+(\w+)\s*=\s*((?:'[^']*'|"[^"]*")(?:\s*\|\s*(?:'[^']*'|"[^"]*"))+)/g; - const results: Record = {}; - for (const m of content.matchAll(re)) { - const name = m[1] as string; - const members = (m[2] as string).split("|").map((v: string) => v.trim().replace(/^['"]|['"]$/g, "")); - results[name] = { members, memberCount: members.length, isStringLiteral: true }; - } - return results; - } catch { - return {}; - } - }, -}); - -// Agent role: extract all string literal union type declarations from TypeScript files. -const tsLiteralUnionExtractor = agent({ - model: "typecheck", - addons: steering({ message: "Call extractLiteralUnions for each file path; merge results across all files." }), - instructions: p`Extract string literal union type declarations from all TypeScript source files. - -TypeScript files: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -40")} - -For each file path above, call extractLiteralUnions to get its literal union types. Merge all results into a single record keyed by type name with members, memberCount, and isStringLiteral.`, - tools: [extractLiteralUnions], - output: s.record( - s.object({ - members: s.array(s.string), - memberCount: s.int, - isStringLiteral: s.boolean, - }) - ), -}); - -export default tsLiteralUnionExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts deleted file mode 100644 index fe62e70..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/289-markdown-heading-validator.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const validateHeadings = defineTool("validateHeadings", { - description: "Parse heading structure from markdown content and validate level ordering.", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }: { filePath: string }) { - const { readFile } = await import("node:fs/promises"); - try { - const content = await readFile(filePath, "utf8"); - const headings: Array<{ level: number; text: string }> = []; - for (const m of content.matchAll(/^(#{1,6})\s+(.+)/gm)) { - headings.push({ level: (m[1] as string).length, text: (m[2] as string).trim() }); - } - const issues: string[] = []; - const h1Count = headings.filter((h: { level: number }) => h.level === 1).length; - if (h1Count > 1) issues.push(`Multiple H1 headings found (${h1Count})`); - if (h1Count === 0 && headings.length > 0) issues.push("No H1 heading found"); - for (let i = 1; i < headings.length; i++) { - if (headings[i].level - headings[i - 1].level > 1) { - issues.push(`Skipped heading level at "${headings[i].text}" (level ${headings[i].level} after level ${headings[i - 1].level})`); - } - } - const maxDepth = headings.reduce((max: number, h: { level: number }) => Math.max(max, h.level), 0); - return { headings, maxDepth, isValid: issues.length === 0, issues }; - } catch { - return { headings: [], maxDepth: 0, isValid: false, issues: ["Could not read file"] }; - } - }, -}); - -// Agent role: validate the heading structure of all markdown files in the workspace. -const markdownHeadingValidator = agent({ - model: "typecheck", - addons: repair(), - instructions: p`Validate the heading structure of all markdown files in the workspace. - -Markdown files: -${p.glob("**/*.md")} - -For each file path above, call validateHeadings to check its heading structure. Return a record keyed by file path with headings array, maxDepth, isValid, and any issues found.`, - tools: [validateHeadings], - output: s.record( - s.object({ - headings: s.array(s.object({ level: s.int, text: s.string })), - maxDepth: s.int, - isValid: s.boolean, - issues: s.array(s.string), - }) - ), -}); - -export default markdownHeadingValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts deleted file mode 100644 index 1a08ef4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/29-bug-report-draft.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: flag unknown or concerning dependency licenses. -const licenseCheck = agent({ - model: "typecheck", - output: s.object({ - compliant: s.boolean, - unknown: s.array(s.string), - concerning: s.array(s.object({ - package: s.string, - license: s.string, - reason: s.string - })) - }), - instructions: `Flag unknown or concerning dependency licenses.`, -}); -export default licenseCheck; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts deleted file mode 100644 index d2ee4b1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/290-commit-churn-classifier.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { agent, p, s, defineTool, steering, repair } from "rig"; - -const classifyRisk = defineTool("classifyRisk", { - description: "Classify churn risk level based on commit count", - parameters: s.object({ churnCount: s.int }), - handler: ({ churnCount }) => { - if (churnCount <= 2) return "stable" as const; - if (churnCount <= 5) return "active" as const; - if (churnCount <= 10) return "volatile" as const; - return "critical" as const; - }, -}); - -// Agent role: analyze git commit history to classify file churn and risk levels -const commitChurnClassifier = agent({ - model: "typecheck", - instructions: p`Analyze commit history from ${p.bash("git log --name-only --format='' | grep -v '^$' | sort | uniq -c | sort -rn | head -30")} and classify each file's churn risk using the classifyRisk tool. Return a record keyed by file path.`, - output: s.record(s.object({ - churnCount: s.int, - riskLevel: s.enum("stable", "active", "volatile", "critical"), - })), - tools: [classifyRisk], - addons: [steering(), repair()], -}); - -export default commitChurnClassifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts deleted file mode 100644 index b667b7e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/291-npm-package-size-estimator.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const classifySize = defineTool("classifySize", { - description: "Classify a package size in KB into a tier rating", - parameters: s.object({ sizeKb: s.number }), - handler: ({ sizeKb }) => { - if (sizeKb < 50) return "tiny" as const; - if (sizeKb < 200) return "small" as const; - if (sizeKb < 500) return "medium" as const; - if (sizeKb < 2000) return "large" as const; - return "xlarge" as const; - }, -}); - -// Agent role: estimate the npm package size and classify it into a tier rating -const npmPackageSizeEstimator = agent({ - model: "typecheck", - instructions: p`Estimate this package's size using: -- Pack dry-run: ${p.bash("npm pack --dry-run 2>&1 | head -40")} -- Directory size: ${p.bash("du -sh . 2>/dev/null | head -5")} - -Use the classifySize tool to determine the tier rating. Return estimatedSizeKb, topFiles (up to 5 files with their sizes), sizeRating, and a recommendation.`, - output: s.object({ - estimatedSizeKb: s.number, - topFiles: s.array(s.object({ name: s.string, sizeKb: s.number })), - sizeRating: s.enum("tiny", "small", "medium", "large", "xlarge"), - recommendation: s.string, - }), - tools: [classifySize], - addons: [repair()], -}); - -export default npmPackageSizeEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts deleted file mode 100644 index 9cfefad..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/292-ts-branch-coverage-analyzer.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze TypeScript source for branch coverage patterns -const branchAnalyzer = agent({ - name: "branchAnalyzer", - model: "typecheck", - instructions: p`Analyze the TypeScript source provided in the input and identify all branches (if/ternary/switch/logical). For each branch, determine the function name, line number, branch type, and whether it is likely covered based on test presence. Return a detailed array of branch objects.`, - input: s.object({ source: s.string }), - output: s.array(s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "logical"), - covered: s.boolean, - })), -}); - -// Agent role: coordinate branch coverage analysis for a TypeScript file -const tsBranchCoverageAnalyzer = agent({ - model: "typecheck", - instructions: p`Read the TypeScript file at the path in the input using the readInput intent and delegate branch analysis to the branchAnalyzer subagent. Compute totalBranches, coveredBranches, and uncoveredBranches from the results.`, - input: s.object({ filePath: s.path }), - output: s.object({ - branches: s.array(s.object({ - functionName: s.string, - line: s.int, - branchType: s.enum("if", "ternary", "switch", "logical"), - covered: s.boolean, - })), - summary: s.object({ - totalBranches: s.int, - coveredBranches: s.int, - uncoveredBranches: s.int, - }), - }), - agents: { branchAnalyzer }, -}); - -export default tsBranchCoverageAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts deleted file mode 100644 index af18b29..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/293-env-variable-type-inferrer.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const inferType = defineTool("inferType", { - description: "Infer the type of an environment variable value", - parameters: s.object({ key: s.string, value: s.string }), - handler: ({ value }) => { - if (value === "true" || value === "false") return "boolean" as const; - if (/^\d+(\.\d+)?$/.test(value)) return "number" as const; - if (/^https?:\/\//.test(value)) return "url" as const; - if (/^[./~]|^\$HOME/.test(value)) return "path" as const; - if (value.length === 0 || value.startsWith("<") || value.startsWith("#")) return "unknown" as const; - return "string" as const; - }, -}); - -// Agent role: infer types of environment variables from .env.example -const envVariableTypeInferrer = agent({ - model: "typecheck", - instructions: p`Analyze the environment variable definitions from ${p.readOptional(".env.example", "# no .env.example found")} and use the inferType tool for each variable. Produce a record of variable names to their inferred type and description, plus allDocumented indicating whether all variables have non-empty descriptions.`, - output: s.object({ - variables: s.record(s.object({ - type: s.enum("string", "number", "boolean", "url", "path", "unknown"), - description: s.string, - })), - allDocumented: s.boolean, - }), - tools: [inferType], - addons: [repair()], -}); - -export default envVariableTypeInferrer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts deleted file mode 100644 index a5f7833..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/294-makefile-target-extractor.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseTarget = defineTool("parseTarget", { - description: "Parse a Makefile target line and return its metadata", - parameters: s.object({ line: s.string, phonyTargets: s.string }), - handler: ({ line, phonyTargets }) => { - const match = line.match(/^([a-zA-Z0-9_.-]+)\s*:/); - if (!match) return null; - const name = match[1]; - const isPhony = phonyTargets.includes(name); - const hasHelp = line.includes("##"); - const descMatch = line.match(/##\s*(.+)/); - return { name, isPhony, hasHelp, description: descMatch ? descMatch[1].trim() : undefined }; - }, -}); - -// Agent role: extract and classify targets from a Makefile -const makefileTargetExtractor = agent({ - model: "typecheck", - instructions: p`Parse the Makefile content: ${p.readOptional("Makefile", "# no Makefile found")} - -Use the parseTarget tool for each target line. Collect all targets and their metadata, count phony vs real targets, and return the structured result.`, - output: s.object({ - targets: s.array(s.object({ - name: s.string, - isPhony: s.boolean, - hasHelp: s.boolean, - description: s.optional(s.string), - })), - totalCount: s.int, - phonyCount: s.int, - }), - tools: [parseTarget], - addons: [repair()], -}); - -export default makefileTargetExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts deleted file mode 100644 index aba9aa2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/295-test-fixture-generator.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: extract function signature from a TypeScript source file -const signatureAnalyzer = agent({ - name: "signatureAnalyzer", - model: "typecheck", - instructions: p`Given the TypeScript source in the input, extract the signature for the function named in functionName. Return the parameter types, return type, and any imports needed to use this function in a test.`, - input: s.object({ source: s.string, functionName: s.string }), - output: s.object({ - params: s.array(s.object({ name: s.string, type: s.string })), - returnType: s.string, - imports: s.array(s.string), - }), -}); - -// Agent role: generate test fixtures for a TypeScript function -const testFixtureGenerator = agent({ - model: "typecheck", - instructions: p`Generate a test fixture for the function specified in the input. - -Read the source file: ${p.readInput("sourceFile")} - -Delegate signature extraction to the signatureAnalyzer subagent for the function named in the input's functionName field. Then generate a complete test fixture file with sample inputs, expected outputs, and required imports. Write the fixture to the path in suggestedFileName.`, - input: s.object({ sourceFile: s.path, functionName: s.string }), - output: s.object({ - fixtureCode: s.string, - imports: s.array(s.string), - suggestedFileName: s.path, - }), - agents: { signatureAnalyzer }, -}); - -export default testFixtureGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts deleted file mode 100644 index 8f95557..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/296-git-file-ownership-mapper.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; -import { execSync } from "node:child_process"; - -const getFileOwner = defineTool("getFileOwner", { - description: "Get git ownership info for a file path", - parameters: s.object({ filePath: s.path }), - handler: async ({ filePath }) => { - try { - const output = execSync(`git log --format="%ae" -- "${filePath}" 2>/dev/null`, { encoding: "utf8" }); - const emails = output.trim().split("\n").filter((e: string) => e.length > 0); - const counts: Record = {}; - for (const email of emails) { - counts[email] = (counts[email] ?? 0) + 1; - } - const sorted = Object.entries(counts).sort((a: [string, number], b: [string, number]) => b[1] - a[1]); - const primaryOwner = sorted[0]?.[0] ?? "unknown"; - const commitCount = emails.length; - const contributors = sorted.map((e: [string, number]) => e[0]); - return { primaryOwner, commitCount, contributors }; - } catch { - return { primaryOwner: "unknown", commitCount: 0, contributors: [] }; - } - }, -}); - -// Agent role: map git file ownership by analyzing commit history for TypeScript files -const gitFileOwnershipMapper = agent({ - model: "typecheck", - instructions: p`Discover TypeScript source files: ${p.glob("src/**/*.ts")} - -Use the getFileOwner tool for each discovered file path to collect ownership data. Build a complete ownership record and identify the mostActiveContributor across all files.`, - output: s.object({ - ownership: s.record(s.object({ - primaryOwner: s.string, - commitCount: s.int, - contributors: s.array(s.string), - })), - mostActiveContributor: s.string, - }), - tools: [getFileOwner], - addons: [steering()], -}); - -export default gitFileOwnershipMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts deleted file mode 100644 index 4033d16..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/297-workflow-input-validator.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const validateWorkflowInputs = defineTool("validateWorkflowInputs", { - description: "Parse workflow_dispatch inputs from a GitHub Actions workflow YAML file", - parameters: s.object({ filePath: s.path }), - handler: async ({ filePath }) => { - const content = await readFile(filePath, "utf8"); - const inputSection = content.match(/workflow_dispatch:[\s\S]*?inputs:([\s\S]*?)(?=\n\S|\n\w+:|\n [a-z]+:(?!\s*\n\s+type:)|\Z)/)?.[1] ?? ""; - const inputMatches = [...inputSection.matchAll(/^\s{6}(\w[\w-]*):/gm)]; - const inputs = inputMatches.map((m: RegExpMatchArray) => { - const name = m[1]; - const block = inputSection.slice(m.index ?? 0, (m.index ?? 0) + 300); - const type = block.match(/type:\s*(\w+)/)?.[1] ?? "string"; - const required = /required:\s*true/.test(block); - const hasDefault = /default:/.test(block); - return { name, type, required, hasDefault }; - }); - return { - inputs, - inputCount: inputs.length, - hasRequiredWithoutDefault: inputs.some((i: { required: boolean; hasDefault: boolean }) => i.required && !i.hasDefault), - }; - }, -}); - -// Agent role: validate GitHub Actions workflow_dispatch inputs across all workflow files -const workflowInputValidator = agent({ - model: "typecheck", - instructions: p`Validate workflow_dispatch inputs in all workflow files discovered at ${p.glob(".github/workflows/*.yml")}. Use the validateWorkflowInputs tool for each file path. Return a record keyed by filename and the total workflow count.`, - output: s.object({ - workflows: s.record(s.object({ - inputs: s.array(s.object({ - name: s.string, - type: s.string, - required: s.boolean, - hasDefault: s.boolean, - })), - inputCount: s.int, - hasRequiredWithoutDefault: s.boolean, - })), - totalWorkflows: s.int, - }), - tools: [validateWorkflowInputs], - addons: [repair()], -}); - -export default workflowInputValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts deleted file mode 100644 index d43f6d7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/298-ts-dead-export-finder.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool, steering, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const findUnusedExports = defineTool("findUnusedExports", { - description: "Find exported symbols in a TypeScript file that are not imported elsewhere", - parameters: s.object({ filePath: s.path, allFiles: s.array(s.string) }), - handler: async ({ filePath, allFiles }) => { - const content = await readFile(filePath, "utf8"); - const exportMatches = [...content.matchAll(/export\s+(?:const|function|class|type|interface|enum)\s+(\w+)/g)]; - const exportedNames = exportMatches.map((m: RegExpMatchArray) => m[1]); - const unusedNames: string[] = []; - for (const name of exportedNames) { - let isImported = false; - for (const other of allFiles) { - if (other === filePath) continue; - try { - const otherContent = await readFile(other, "utf8"); - if (otherContent.includes(name)) { isImported = true; break; } - } catch { /* skip */ } - } - if (!isImported) unusedNames.push(name); - } - return unusedNames; - }, -}); - -// Agent role: find unused TypeScript exports across the src directory -const tsDeadExportFinder = agent({ - model: "typecheck", - instructions: p`Find potentially dead (unused) TypeScript exports. -Files with exports: ${p.bash("grep -rl 'export ' src/ --include='*.ts' 2>/dev/null | head -20 || echo 'none'")} -All TS files: ${p.glob("src/**/*.ts")} - -Use the findUnusedExports tool for each file that has exports, passing all discovered files. Build a record of unused exports keyed by file path, the total count, and whether dead code was found.`, - output: s.object({ - unusedExports: s.record(s.array(s.string)), - totalUnused: s.int, - hasDeadCode: s.boolean, - }), - tools: [findUnusedExports], - addons: [steering(), repair()], -}); - -export default tsDeadExportFinder; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts deleted file mode 100644 index 1898a4b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/299-package-json-scripts-documenter.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const inferScriptPurpose = defineTool("inferScriptPurpose", { - description: "Classify an npm script and suggest a one-line description of its purpose", - parameters: s.object({ name: s.string, command: s.string }), - handler: ({ name, command }: { name: string; command: string }) => { - const lname = name.toLowerCase(); - const lcmd = command.toLowerCase(); - let category: "build" | "test" | "lint" | "release" | "dev" | "other"; - if (lname.includes("build") || lcmd.includes("tsc") || lcmd.includes("webpack") || lcmd.includes("rollup") || lcmd.includes("vite build")) { - category = "build"; - } else if (lname.includes("test") || lcmd.includes("vitest") || lcmd.includes("jest") || lcmd.includes("mocha")) { - category = "test"; - } else if (lname.includes("lint") || lcmd.includes("eslint") || lcmd.includes("prettier")) { - category = "lint"; - } else if (lname.includes("release") || lname.includes("publish") || lname.includes("version")) { - category = "release"; - } else if (lname.includes("dev") || lname.includes("start") || lname.includes("watch")) { - category = "dev"; - } else { - category = "other"; - } - return { category }; - }, -}); - -// Agent role: document npm scripts from package.json and write a SCRIPTS.md file -const packageJsonScriptsDocumenter = agent({ - model: "typecheck", - instructions: p`Read the npm scripts from ${p.read("package.json")} and use the inferScriptPurpose tool for each script to classify it. Then write ${p.write("SCRIPTS.md", "scripts")} a well-structured markdown documentation file listing each script with its purpose, category, and command. Return the structured record of scripts, the count, and the output file path.`, - output: s.object({ - scripts: s.record(s.object({ - purpose: s.string, - category: s.enum("build", "test", "lint", "release", "dev", "other"), - command: s.string, - })), - documentedCount: s.int, - outputFile: s.path, - }), - tools: [inferScriptPurpose], - addons: [repair()], -}); - -export default packageJsonScriptsDocumenter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts deleted file mode 100644 index 53126b5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/30-github-action-review.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: draft a GitHub bug report from the failure details. -const bugReport = agent({ - model: "typecheck", - output: s.object({ - title: s.string, - body: s.string, - labels: s.array(s.string) - }), - instructions: `Draft a GitHub bug report from the failure details.`, -}); -export default bugReport; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts deleted file mode 100644 index 65b5122..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/300-server-uptime-log-parser.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { agent, p, s, defineTool, steering, repair } from "rig"; - -const parseUptimeEvent = defineTool("parseUptimeEvent", { - description: "Parse a log line to extract uptime lifecycle events", - parameters: s.object({ line: s.string }), - handler({ line }) { - const startedMatch = line.match(/(\S+\s+\S+\s+\S+).*\s(\S+(?:\[\d+\])?): .*[Ss]tarted/); - const stoppedMatch = line.match(/(\S+\s+\S+\s+\S+).*\s(\S+(?:\[\d+\])?): .*[Ss]topped/); - const crashMatch = line.match(/(\S+\s+\S+\s+\S+).*\s(\S+(?:\[\d+\])?): .*(?:[Cc]rash|[Kk]ill|exit.*code [^0])/); - if (crashMatch) return { timestamp: crashMatch[1] ?? "", service: crashMatch[2] ?? "", event: "crashed" as const }; - if (startedMatch) return { timestamp: startedMatch[1] ?? "", service: startedMatch[2] ?? "", event: "started" as const }; - if (stoppedMatch) return { timestamp: stoppedMatch[1] ?? "", service: stoppedMatch[2] ?? "", event: "stopped" as const }; - return { timestamp: "", service: "", event: "unknown" as const }; - }, -}); - -// Agent role: Parse system logs to identify service lifecycle events, crash counts, and uptime statistics. -const uptimeLogParser = agent({ - model: "typecheck", - instructions: p`Analyze the following system log lines to identify service lifecycle events. -Log lines: -${p.bash("journalctl -n 200 --no-pager 2>/dev/null || tail -n 200 /var/log/syslog 2>/dev/null || echo 'no logs'")} - -Use the parseUptimeEvent tool on relevant log lines that mention service starts, stops, or crashes. -Calculate totalUptimeHours as a rough estimate based on timestamps found. -Set hasCrashLoop to true if crashCount >= 3. -Return the structured output.`, - output: s.object({ - uptimeEvents: s.array(s.object({ - timestamp: s.string, - service: s.string, - event: s.enum("started", "stopped", "crashed", "unknown"), - })), - crashCount: s.int, - totalUptimeHours: s.number, - hasCrashLoop: s.boolean, - }), - tools: [parseUptimeEvent], - addons: [steering(), repair()], -}); - -export default uptimeLogParser; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts deleted file mode 100644 index 279d0dc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/301-css-variable-extractor.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agent, p, s, defineTool, steering, repair } from "rig"; - -const parseCssVar = defineTool("parseCssVar", { - description: "Parse a CSS line to extract custom property (CSS variable) declarations", - parameters: s.object({ line: s.string }), - handler({ line }) { - const match = line.match(/^\s*(--[\w-]+)\s*:\s*(.+?)\s*;?\s*$/); - if (!match) return { name: "", value: "", found: false }; - return { name: match[1] ?? "", value: match[2] ?? "", found: true }; - }, -}); - -// Agent role: Scan CSS files to extract CSS custom property declarations and detect unused variables. -const cssVariableExtractor = agent({ - model: "typecheck", - instructions: p`Scan CSS files and extract all custom property (CSS variable) declarations. - -CSS file content (declarations and usages): -${p.bash("find . -name '*.css' -not -path '*/node_modules/*' | head -20 | xargs grep -h -- '--' 2>/dev/null | head -100 || echo 'no css files'")} - -Use the parseCssVar tool on each line that may contain a CSS variable declaration (--variable: value). -For each variable found, count how many times it appears as a usage (var(--name)). -A variable is unused if it is declared but never used via var(). -Return the structured output.`, - output: s.object({ - variables: s.record(s.object({ - value: s.string, - usageCount: s.int, - })), - unusedVars: s.array(s.string), - totalVars: s.int, - }), - tools: [parseCssVar], - addons: [steering(), repair()], -}); - -export default cssVariableExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts deleted file mode 100644 index 951dcc6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/302-openapi-route-coverage.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const extractRoutes = defineTool("extractRoutes", { - description: "Extract HTTP route patterns from router handler code", - parameters: s.object({ content: s.string }), - handler({ content }) { - const routes: Array<{ path: string; method: string }> = []; - const pattern = /router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/gi; - let m: RegExpExecArray | null; - while ((m = pattern.exec(content)) !== null) { - routes.push({ method: (m[1] ?? "get").toUpperCase(), path: m[2] ?? "/" }); - } - return routes; - }, -}); - -// Agent role: Compare OpenAPI spec routes against implemented router handlers to measure coverage. -const openapiRouteCoverage = agent({ - model: "typecheck", - instructions: p`Compare OpenAPI spec routes against implemented router handlers to determine coverage. - -OpenAPI spec: -${p.readOptional("openapi.json", "{}")} - -Router handler code: -${p.bash("grep -rn 'router\\.' --include='*.ts' --include='*.js' . 2>/dev/null | head -50 || echo 'no routes'")} - -Use the extractRoutes tool on the router handler code to discover implemented routes. -Cross-reference with paths defined in the OpenAPI spec. -Return routes array showing which are defined (in spec) vs implemented (in code). -Calculate coveragePercent as (totalImplemented / totalDefined * 100) or 0 if no spec.`, - output: s.object({ - routes: s.array(s.object({ - path: s.string, - method: s.string, - defined: s.boolean, - implemented: s.boolean, - })), - coveragePercent: s.number, - totalDefined: s.int, - totalImplemented: s.int, - }), - tools: [extractRoutes], - addons: [repair()], -}); - -export default openapiRouteCoverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts deleted file mode 100644 index 36b1eb9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/303-import-style-checker.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const classifyStyle = defineTool("classifyStyle", { - description: "Classify a file's module style based on require vs import counts", - parameters: s.object({ file: s.string, requireCount: s.int, importCount: s.int }), - handler({ requireCount, importCount }) { - if (requireCount === 0 && importCount === 0) return "unknown" as const; - if (requireCount > 0 && importCount > 0) return "mixed" as const; - if (requireCount > 0) return "cjs" as const; - return "esm" as const; - }, -}); - -// Agent role: Classify each JavaScript file by its module system (ESM vs CJS) based on import/require usage. -const importStyleChecker = agent({ - model: "typecheck", - instructions: p`Analyze JavaScript files to classify their module system style. - -Files with require/import patterns: -${p.bash("find . -name '*.js' -not -path '*/node_modules/*' | head -10 | xargs grep -hn '^require\\|^import ' 2>/dev/null | head -80 || echo 'no imports'")} - -For each file found, count occurrences of require(...) and import statements. -Use the classifyStyle tool to determine the module style per file. -Return counts per file and summary totals.`, - output: s.object({ - files: s.record(s.object({ - style: s.enum("esm", "cjs", "mixed", "unknown"), - requireCount: s.int, - importCount: s.int, - })), - esmCount: s.int, - cjsCount: s.int, - mixedCount: s.int, - unknownCount: s.int, - }), - tools: [classifyStyle], - addons: [repair()], -}); - -export default importStyleChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts deleted file mode 100644 index a191403..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/304-git-tag-semver-validator.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const parseSemver = defineTool("parseSemver", { - description: "Parse a git tag to determine if it follows semver and extract components", - parameters: s.object({ tag: s.string }), - handler({ tag }) { - const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)/); - if (!match) return { valid: false }; - return { - valid: true, - major: parseInt(match[1] ?? "0", 10), - minor: parseInt(match[2] ?? "0", 10), - patch: parseInt(match[3] ?? "0", 10), - }; - }, -}); - -// Agent role: Validate git tags against semver format and identify the latest valid version. -const gitTagSemverValidator = agent({ - model: "typecheck", - instructions: p`Validate git tags to check semver compliance. - -Git tags: -${p.bash("git tag --list 2>/dev/null | head -30 || echo 'no tags'")} - -Use the parseSemver tool on each tag to validate format and extract major/minor/patch. -Identify invalidCount (tags that don't follow semver). -Set latestValid to the highest valid semver tag, or omit if none. -Return the structured output.`, - output: s.object({ - tags: s.array(s.object({ - name: s.string, - valid: s.boolean, - parsed: s.optional(s.object({ - major: s.int, - minor: s.int, - patch: s.int, - })), - })), - invalidCount: s.int, - latestValid: s.optional(s.string), - }), - tools: [parseSemver], - addons: [steering()], -}); - -export default gitTagSemverValidator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts deleted file mode 100644 index 122ff84..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/305-shell-script-safety-analyzer.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; -import { readFile } from "node:fs/promises"; - -const analyzeShellScript = defineTool("analyzeShellScript", { - description: "Analyze a shell script file for safety flags (set -e, set -u, set -o pipefail) and shebang", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8").catch(() => ""); - const lines = content.split("\n"); - const shebangLine = lines[0] ?? ""; - const shebang = shebangLine.startsWith("#!") ? shebangLine.slice(2).trim() : undefined; - const hasSetE = /\bset\b.*-[a-zA-Z]*e/.test(content) || /\bset\b.*-e/.test(content); - const hasSetU = /\bset\b.*-[a-zA-Z]*u/.test(content) || /\bset\b.*-u/.test(content); - const hasPipefail = /set\s+-o\s+pipefail/.test(content); - let safetyLevel: "strict" | "partial" | "unsafe"; - if (hasSetE && hasSetU && hasPipefail) safetyLevel = "strict"; - else if (hasSetE || hasSetU || hasPipefail) safetyLevel = "partial"; - else safetyLevel = "unsafe"; - return { shebang, hasSetE, hasSetU, hasPipefail, safetyLevel }; - }, -}); - -// Agent role: Scan shell scripts for safety flags and classify each by safety level. -const shellScriptSafetyAnalyzer = agent({ - model: "typecheck", - instructions: p`Find all shell scripts and analyze each for safety flags. - -Shell script files: -${p.bash("find . -name '*.sh' -not -path '*/node_modules/*' | head -20 2>/dev/null || echo 'no shell scripts'")} - -Use the analyzeShellScript tool on each .sh file path listed above. -Return a record keyed by file path with safety analysis for each script.`, - output: s.record(s.object({ - shebang: s.optional(s.string), - hasSetE: s.boolean, - hasSetU: s.boolean, - hasPipefail: s.boolean, - safetyLevel: s.enum("strict", "partial", "unsafe"), - })), - tools: [analyzeShellScript], - addons: [steering()], -}); - -export default shellScriptSafetyAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts deleted file mode 100644 index 6fec012..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/306-git-diff-stats-summarizer.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const classifyDiffEntry = defineTool("classifyDiffEntry", { - description: "Classify a diff entry based on addition/deletion counts", - parameters: s.object({ path: s.string, additions: s.int, deletions: s.int }), - handler({ additions, deletions }) { - if (additions > 0 && deletions === 0) return "added" as const; - if (additions === 0 && deletions > 0) return "deleted" as const; - if (additions > 0 && deletions > 0) return "modified" as const; - return "renamed" as const; - }, -}); - -// Agent role: Summarize git diff statistics between the last two commits, classifying each changed file. -const gitDiffStatsSummarizer = agent({ - model: "typecheck", - instructions: p`Analyze git diff statistics for the most recent commit. - -Diff numstat (additions deletions file): -${p.bash("git diff --numstat HEAD~1 HEAD 2>/dev/null | head -30 || echo 'no diff'")} - -Diff summary: -${p.bash("git diff --stat HEAD~1 HEAD 2>/dev/null | tail -5 || echo 'no stat'")} - -Parse the numstat output (format: additionsdeletionspath). -Use the classifyDiffEntry tool on each file entry. -Sum up totalAdditions and totalDeletions. -Set mostChangedFile to the file with the highest combined additions+deletions, or omit if empty. -Return the structured output.`, - output: s.object({ - files: s.array(s.object({ - path: s.string, - additions: s.int, - deletions: s.int, - change: s.enum("added", "modified", "deleted", "renamed"), - })), - totalAdditions: s.int, - totalDeletions: s.int, - mostChangedFile: s.optional(s.string), - }), - tools: [classifyDiffEntry], - addons: [repair()], -}); - -export default gitDiffStatsSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts deleted file mode 100644 index fefeaf8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/307-dotenv-template-generator.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -const extractEnvReferences = defineTool("extractEnvReferences", { - description: "Extract all process.env.VAR_NAME references from a TypeScript source file", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8").catch(() => ""); - const pattern = /process\.env\.([A-Z_][A-Z0-9_]*)/g; - const keys = new Set(); - let m: RegExpExecArray | null; - while ((m = pattern.exec(content)) !== null) { - if (m[1]) keys.add(m[1]); - } - return Array.from(keys); - }, -}); - -// Agent role: Generate a .env.template file by scanning source files for process.env references and comparing against existing .env keys. -const dotenvTemplateGenerator = agent({ - model: "typecheck", - instructions: p`Generate a .env.template file documenting all required environment variables. - -Existing .env file: -${p.readOptional(".env", "# no .env file found")} - -TypeScript source files to scan: -${p.glob("src/**/*.ts")} - -Use the extractEnvReferences tool on each source file to find process.env.VAR references. -Collect all unique env keys found across all files (envKeys). -Compare with keys present in .env — undocumentedKeys are those referenced in code but missing from .env. -Write a .env.template with each key as KEY=. -${p.write(".env.template", "# Generated .env.template\n# Replace with actual values\n")} -Return templatePath as ".env.template", envKeys array, undocumentedKeys array, and templateGenerated as true.`, - output: s.object({ - templatePath: s.path, - envKeys: s.array(s.string), - undocumentedKeys: s.array(s.string), - templateGenerated: s.boolean, - }), - tools: [extractEnvReferences], - addons: [repair()], -}); - -export default dotenvTemplateGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts deleted file mode 100644 index 7ce3ba7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/308-ts-class-hierarchy-extractor.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; -import { readFile } from "node:fs/promises"; - -const extractClassInfo = defineTool("extractClassInfo", { - description: "Extract class declarations, inheritance, and interface implementations from a TypeScript file", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8").catch(() => ""); - const pattern = /(?:(abstract)\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?/g; - const classes: Array<{ className: string; parent?: string; interfaces: string[]; isAbstract: boolean }> = []; - let m: RegExpExecArray | null; - while ((m = pattern.exec(content)) !== null) { - const interfaces = m[4] ? m[4].split(",").map((s: string) => s.trim()).filter(Boolean) : []; - classes.push({ - className: m[2] ?? "", - parent: m[3], - interfaces, - isAbstract: !!m[1], - }); - } - return classes; - }, -}); - -// Agent role: Build a class hierarchy map from TypeScript files showing inheritance and interface relationships. -const tsClassHierarchyExtractor = agent({ - model: "typecheck", - instructions: p`Extract and map TypeScript class hierarchy from all source files. - -TypeScript files: -${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -name '*.d.ts' | head -20 2>/dev/null || echo 'no ts files'")} - -Use the extractClassInfo tool on each file to get class declarations with inheritance info. -For each class, compute depth: root classes (no parent) have depth 0; derived classes add 1 per level. -Set maxDepth to the deepest class depth found. -rootClasses are class names with no parent. -Return the structured output.`, - output: s.object({ - classes: s.record(s.object({ - parent: s.optional(s.string), - interfaces: s.array(s.string), - isAbstract: s.boolean, - depth: s.int, - })), - maxDepth: s.int, - rootClasses: s.array(s.string), - }), - tools: [extractClassInfo], - addons: [steering()], -}); - -export default tsClassHierarchyExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts deleted file mode 100644 index c431a32..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/309-git-bisect-helper.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -const selectMidpoint = defineTool("selectMidpoint", { - description: "Select the midpoint commit from a list for binary search bisection", - parameters: s.object({ commits: s.array(s.string), currentBad: s.string, currentGood: s.string }), - handler({ commits }) { - if (commits.length === 0) return { midpoint: null, remaining: 0 }; - const mid = Math.floor(commits.length / 2); - return { midpoint: commits[mid] ?? null, remaining: commits.length }; - }, -}); - -// Agent role: Analyze recent git commit history to identify the most likely suspect commit for a regression using binary search logic. -const gitBisectHelper = agent({ - model: "typecheck", - maxTurns: 8, - instructions: p`Analyze recent git commits to identify a suspect regression commit using binary search logic. - -Recent commits (newest first): -${p.bash("git log --oneline -20 2>/dev/null | head -20 || echo 'no commits'")} - -Commit count in range: -${p.bash("git log --oneline HEAD~10..HEAD 2>/dev/null | wc -l || echo '0'")} - -Use the selectMidpoint tool to perform binary search steps over the commit list. -Assume HEAD is the bad commit and HEAD~10 is good. -Narrow down to the most likely suspect commit. -Set confidence based on how precisely the range was narrowed: - high = 1 commit identified, medium = 2-3 candidates, low = 4+ or unknown. -Return suspectCommit (the SHA/oneline of the suspect), stepsRun, commitRange of the final narrowed set.`, - output: s.object({ - suspectCommit: s.optional(s.string), - stepsRun: s.int, - commitRange: s.array(s.string), - confidence: s.enum("high", "medium", "low"), - }), - tools: [selectMidpoint], - addons: [steering()], -}); - -export default gitBisectHelper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts deleted file mode 100644 index c24f871..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/31-monorepo-package-map.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: review the workflow for reliability, caching, and least privilege. -const actionReview = agent({ - model: "typecheck", - output: s.object({ - summary: s.string, - problems: s.array(s.string), - improvements: s.array(s.string) - }), - instructions: `Review the workflow for reliability, caching, and least privilege.`, -}); -export default actionReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts deleted file mode 100644 index 6fe9897..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-lock-file-drift-detector.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -// Agent role: detect version drift between package.json dependencies and package-lock.json locked versions. -const lockFileDriftDetector = agent({ - model: "typecheck", - instructions: p`You are a lock file drift detector. - -Read the package files: -${p.bash("cat package.json 2>/dev/null || echo '{}'")} -${p.bash("cat package-lock.json 2>/dev/null || echo '{}'")} - -Use the checkVersionDrift tool to cross-check declared vs locked versions for each dependency. -Return the declared output.`, - tools: [ - defineTool("checkVersionDrift", { - description: "Parse package.json and package-lock.json content and return drifted packages", - parameters: s.object({ - packageJsonContent: s.string, - lockFileContent: s.string, - }), - handler({ packageJsonContent, lockFileContent }) { - let pkg: Record; - let lock: Record; - try { - pkg = JSON.parse(packageJsonContent) as Record; - } catch { - return { error: "Failed to parse package.json" }; - } - try { - lock = JSON.parse(lockFileContent) as Record; - } catch { - return { error: "Failed to parse package-lock.json" }; - } - const deps = { - ...((pkg["dependencies"] as Record) ?? {}), - ...((pkg["devDependencies"] as Record) ?? {}), - }; - const lockPackages = (lock["packages"] as Record) ?? {}; - const drifted: Array<{ name: string; declared: string; locked: string }> = []; - for (const [name, declared] of Object.entries(deps)) { - const lockKey = `node_modules/${name}`; - const lockedEntry = lockPackages[lockKey]; - const locked = lockedEntry?.version ?? "missing"; - const declaredClean = (declared as string).replace(/^[\^~>=<]/, ""); - if (locked !== declaredClean && locked !== "missing") continue; - if (locked === "missing") { - drifted.push({ name, declared: declared as string, locked }); - } - } - return { drifted }; - }, - }), - ], - output: s.object({ - driftedPackages: s.array(s.object({ - name: s.string, - declared: s.string, - locked: s.string, - })), - driftCount: s.int, - allInSync: s.boolean, - }), - addons: [repair()], -}); - -export default lockFileDriftDetector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts deleted file mode 100644 index d30b40f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/310-workflow-audit-verify.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { s, workflow } from "rig"; - -const finding = s.object({ title: s.string, file: s.path }); - -// Workflow role: audit source areas in parallel, then verify each finding. -const audit = workflow({ - meta: { - name: "audit", - description: "Find and verify repository issues", - phases: [{ title: "Find" }, { title: "Verify", detail: "one verifier per finding" }], - whenToUse: "Auditing several areas that each need independent verification.", - }, - body: async ({ call, parallel, phase, pipeline }) => { - phase("Find"); - const areas = ["skills", "src", "scripts"]; - const found = await parallel(areas.map((area) => () => - call.json(`Audit ${area}/ for risky patterns.`, s.object({ findings: s.array(finding) }), { label: area }))); - - phase("Verify"); - const verdicts = await pipeline( - found.flatMap((result) => result?.findings ?? []), - (item: { title: string; file: string }) => - call.json(`Verify "${item.title}" in ${item.file}.`, s.object({ real: s.boolean }), { phase: "Verify" }), - ); - return verdicts.filter((verdict) => verdict?.real).length; - }, -}); - -export default audit; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts deleted file mode 100644 index 34d0ccc..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/311-git-conflict-marker-scanner.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: scan tracked files for unresolved git conflict markers and report affected locations. -const gitConflictMarkerScanner = agent({ - model: "typecheck", - instructions: p`You are a git conflict marker scanner. - -Check for conflict markers in tracked files: -${p.bash("git ls-files | xargs grep -lrn '<<<<<<< ' 2>/dev/null || echo 'no conflicts found'")} - -For files with conflict markers, get the details: -${p.bash("git ls-files | xargs grep -n '^<<<<<<< \\|^=======$\\|^>>>>>>> ' 2>/dev/null || echo 'none'")} - -Analyze the results and return the declared output listing all conflict markers found.`, - output: s.object({ - conflicts: s.array(s.object({ - file: s.path, - line: s.int, - markerType: s.enum("start", "middle", "end"), - })), - affectedFiles: s.array(s.path), - conflictCount: s.int, - isClean: s.boolean, - }), - addons: [steering()], -}); - -export default gitConflictMarkerScanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts deleted file mode 100644 index 002d1d6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/312-proto-field-extractor.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -// Agent role: extract field definitions from protobuf message types in .proto files. -const protoFieldExtractor = agent({ - model: "typecheck", - instructions: p`You are a protobuf field extractor. - -Find .proto files in the workspace: -${p.bash("find . -name '*.proto' -not -path '*/node_modules/*' 2>/dev/null || echo 'no .proto files found'")} - -For each .proto file found, call extractProtoFields with its path to parse message definitions. -Return the declared output keyed by message name.`, - tools: [ - defineTool("extractProtoFields", { - description: "Read a .proto file and extract message field definitions", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8"); - const result: Record> = {}; - const messageRegex = /message\s+(\w+)\s*\{([^}]*)\}/gs; - const fieldRegex = /^\s*(repeated\s+)?(\w+)\s+(\w+)\s*=\s*(\d+)/gm; - for (const msgMatch of content.matchAll(messageRegex)) { - const messageName = msgMatch[1]; - const body = msgMatch[2]; - const fields: Array<{ fieldName: string; fieldType: string; fieldNumber: number; isRepeated: boolean }> = []; - for (const fldMatch of body.matchAll(fieldRegex)) { - fields.push({ - isRepeated: !!fldMatch[1], - fieldType: fldMatch[2], - fieldName: fldMatch[3], - fieldNumber: parseInt(fldMatch[4], 10), - }); - } - result[messageName] = fields; - } - return result; - }, - }), - ], - output: s.record(s.array(s.object({ - fieldName: s.string, - fieldType: s.string, - fieldNumber: s.int, - isRepeated: s.boolean, - }))), - addons: [repair()], -}); - -export default protoFieldExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts deleted file mode 100644 index ae68d22..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/313-git-remote-url-inspector.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -// Agent role: inspect git remote URLs and classify their protocol and type. -const gitRemoteUrlInspector = agent({ - model: "typecheck", - instructions: p`You are a git remote URL inspector. - -List all remotes and their URLs: -${p.bash("git remote -v 2>/dev/null || echo 'no remotes'")} - -Count remote branches on origin: -${p.bash("git ls-remote --heads origin 2>/dev/null | wc -l || echo '0'")} - -Use the parseRemoteLine tool for each remote line to extract protocol and type. -Return the declared output.`, - tools: [ - defineTool("parseRemoteLine", { - description: "Parse a git remote -v output line and extract name, url, protocol, and type", - parameters: s.object({ line: s.string }), - handler({ line }) { - const match = line.match(/^(\S+)\s+(\S+)\s+\((\w+)\)$/); - if (!match) return null; - const [, name, url, type] = match; - let protocol: "https" | "ssh" | "git" | "file"; - if (url.startsWith("https://")) protocol = "https" as const; - else if (url.startsWith("git@") || url.startsWith("ssh://")) protocol = "ssh" as const; - else if (url.startsWith("git://")) protocol = "git" as const; - else protocol = "file" as const; - return { name, url, type, protocol }; - }, - }), - ], - output: s.object({ - remotes: s.array(s.object({ - name: s.string, - url: s.string, - type: s.string, - protocol: s.enum("https", "ssh", "git", "file"), - })), - remoteBranchCount: s.int, - hasOrigin: s.boolean, - }), - addons: [repair()], -}); - -export default gitRemoteUrlInspector; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts deleted file mode 100644 index 12c1e9a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/314-ts-enum-value-extractor.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; -import { readFile } from "node:fs/promises"; - -// Agent role: extract TypeScript enum declarations and their members from source files. -const tsEnumValueExtractor = agent({ - model: "typecheck", - instructions: p`You are a TypeScript enum value extractor. - -Find TypeScript files with enum declarations: -${p.bash("grep -rln 'enum ' --include='*.ts' . 2>/dev/null | head -20 || echo 'no enums found'")} - -For each file found, call extractEnumValues with the file path to parse all enum declarations. -Return the declared output keyed by enum name.`, - tools: [ - defineTool("extractEnumValues", { - description: "Read a TypeScript file and extract all enum declarations with their members", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8"); - const result: Record = {}; - const enumRegex = /(const\s+)?enum\s+(\w+)\s*\{([^}]*)\}/gs; - for (const match of content.matchAll(enumRegex)) { - const isConst = !!match[1]; - const enumName = match[2]; - const body = match[3]; - const members = body - .split(",") - .map((m: string) => m.trim().split(/\s*=\s*/)[0].trim()) - .filter((m: string) => m.length > 0 && !m.startsWith("//")); - result[enumName] = { members, isConst, memberCount: members.length }; - } - return result; - }, - }), - ], - output: s.record(s.object({ - members: s.array(s.string), - isConst: s.boolean, - memberCount: s.int, - })), - addons: [steering()], -}); - -export default tsEnumValueExtractor; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts deleted file mode 100644 index 6c5a1e2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/315-json-config-merger.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -// Agent role: deeply merge two JSON config files and write the result to an output path. -const jsonConfigMerger = agent({ - model: "typecheck", - input: s.object({ - baseConfig: s.path, - overrideConfig: s.path, - outputPath: s.path, - }), - instructions: p`You are a JSON config merger. - -Base config contents: -${p.readInput("baseConfig")} - -Override config contents: -${p.readInput("overrideConfig")} - -Use the mergeJsonObjects tool to deeply merge the override config into the base config. -Then write the merged result to ${p.writeInput("outputPath", "mergedContent")}. -Return the declared output.`, - tools: [ - defineTool("mergeJsonObjects", { - description: "Deep merge two JSON strings, returning the merged JSON and counts of added/overridden keys", - parameters: s.object({ - baseJson: s.string, - overrideJson: s.string, - }), - handler({ baseJson, overrideJson }) { - const base = JSON.parse(baseJson) as Record; - const override = JSON.parse(overrideJson) as Record; - let keysAdded = 0; - let keysOverridden = 0; - function deepMerge( - target: Record, - source: Record - ): Record { - const result = { ...target }; - for (const [key, value] of Object.entries(source)) { - if (key in result) { - if ( - typeof result[key] === "object" && - result[key] !== null && - typeof value === "object" && - value !== null - ) { - result[key] = deepMerge( - result[key] as Record, - value as Record - ); - } else { - result[key] = value; - keysOverridden++; - } - } else { - result[key] = value; - keysAdded++; - } - } - return result; - } - const merged = deepMerge(base, override); - return { - mergedJson: JSON.stringify(merged, null, 2), - keysAdded, - keysOverridden, - totalKeys: Object.keys(merged).length, - }; - }, - }), - ], - output: s.object({ - keysAdded: s.int, - keysOverridden: s.int, - totalKeys: s.int, - outputPath: s.path, - }), - addons: [repair()], -}); - -export default jsonConfigMerger; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts deleted file mode 100644 index f84c7b9..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/316-markdown-toc-generator.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; - -// Agent role: generate a table of contents markdown file from all headings found in workspace .md files. -const markdownTocGenerator = agent({ - model: "typecheck", - instructions: p`You are a markdown table of contents generator. - -Find all markdown files in the workspace: -${p.glob("**/*.md")} - -For each file, call extractHeadings to parse its heading structure. -Then write the combined TOC to ${p.write("TOC.md", "tocContent")}. -Return the declared output.`, - tools: [ - defineTool("extractHeadings", { - description: "Read a markdown file and extract all headings with their levels and anchor text", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8"); - const headings: Array<{ level: number; text: string; anchor: string }> = []; - const headingRegex = /^(#{1,6})\s+(.+)$/gm; - for (const match of content.matchAll(headingRegex)) { - const level = match[1].length; - const text = match[2].trim(); - const anchor = text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-"); - headings.push({ level, text, anchor }); - } - return { filePath, headings }; - }, - }), - ], - output: s.object({ - processedFiles: s.array(s.path), - headingCount: s.int, - outputPath: s.path, - tocGenerated: s.boolean, - }), - addons: [repair()], -}); - -export default markdownTocGenerator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts deleted file mode 100644 index 09ee46a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/317-git-author-email-domains.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; - -// Agent role: aggregate git commit author email domains and count commits per domain. -const gitAuthorEmailDomains = agent({ - model: "typecheck", - instructions: p`You are a git author email domain aggregator. - -Collect all author emails from the git log: -${p.bash("git log --format=%ae 2>/dev/null | sort | uniq -c | sort -rn || echo 'no commits'")} - -For each unique email, call extractDomain to parse the domain. -Aggregate the results and return the declared output.`, - tools: [ - defineTool("extractDomain", { - description: "Extract the domain portion from an email address", - parameters: s.object({ email: s.string }), - handler({ email }) { - const atIdx = email.indexOf("@"); - if (atIdx === -1) return { domain: "unknown" }; - return { domain: email.slice(atIdx + 1).toLowerCase() }; - }, - }), - ], - output: s.object({ - domains: s.record(s.int), - totalAuthors: s.int, - uniqueEmails: s.int, - topDomain: s.string, - }), - addons: [steering()], -}); - -export default gitAuthorEmailDomains; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts deleted file mode 100644 index 470b9c4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/318-ts-barrel-re-exporter.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; -import { readFile } from "node:fs/promises"; -// Agent role: generate a barrel file for exported symbols in skills/rig/engines. -const tsBarrelReExporter = agent({ - model: "typecheck", - instructions: p`Generate a TypeScript barrel for skills/rig/engines from ${p.bash("find skills/rig/engines -name '*.ts' -not -name 'index.ts' -not -name '*.d.ts' | head -20")}. Use extractExportedSymbols for each file, set outputFile to /tmp/rig-barrel.ts, write barrelContent to ${p.writeOutput("barrelContent", "/tmp/rig-barrel.ts")}, and return the declared output.`, - tools: [defineTool("extractExportedSymbols", { - description: "Read a TypeScript file and extract top-level exported symbol names", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8"); - const symbols = [...content.matchAll(/^export\s+(?:(?:default\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)|(\{[^}]+\}))/gm)].flatMap((match) => match[1] ? [match[1]] : match[2]!.replace(/[{}]/g, "").split(",").map((name) => name.trim().split(/\s+as\s+/)[0].trim()).filter(Boolean)); - return { filePath, symbols }; - }, - })], - output: s.object({ barrelContent: s.string, exports: s.array(s.string), outputFile: s.path, totalExports: s.int, filesScanned: s.int }), - addons: [repair()], -}); -export default tsBarrelReExporter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts deleted file mode 100644 index a98673b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/319-workflow-step-duration-estimator.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { agent, p, s, defineTool, steering } from "rig"; -import { readFile } from "node:fs/promises"; - -// Agent role: estimate total runtime and identify bottleneck steps in GitHub Actions workflows. -const workflowStepDurationEstimator = agent({ - model: "typecheck", - instructions: p`You are a GitHub Actions workflow step duration estimator. - -Discover workflow files: -${p.glob(".github/workflows/*.yml")} - -Read each workflow file and use estimateStepDuration to classify each step's expected duration. -Return the declared output with per-workflow estimates.`, - tools: [ - defineTool("estimateStepDuration", { - description: "Classify a workflow step's expected duration based on its name and uses field", - parameters: s.object({ - stepName: s.string, - uses: s.optional(s.string), - run: s.optional(s.string), - }), - handler({ stepName, uses, run }) { - const slow = ["install", "build", "compile", "deploy", "push", "publish", "cache", "docker", "terraform"]; - const medium = ["test", "lint", "check", "validate", "setup", "configure", "upload", "download"]; - const fast = ["checkout", "echo", "env", "version", "tag", "label", "comment"]; - const text = `${stepName} ${uses ?? ""} ${run ?? ""}`.toLowerCase(); - let speed: "fast" | "medium" | "slow" | "unknown"; - let estimatedMinutes: number; - if (slow.some((k: string) => text.includes(k))) { - speed = "slow" as const; - estimatedMinutes = 5; - } else if (medium.some((k: string) => text.includes(k))) { - speed = "medium" as const; - estimatedMinutes = 2; - } else if (fast.some((k: string) => text.includes(k))) { - speed = "fast" as const; - estimatedMinutes = 0.5; - } else { - speed = "unknown" as const; - estimatedMinutes = 1; - } - return { speed, estimatedMinutes }; - }, - }), - defineTool("readWorkflowFile", { - description: "Read a workflow YAML file and return its content", - parameters: s.object({ filePath: s.path }), - async handler({ filePath }) { - const content = await readFile(filePath, "utf8"); - return { filePath, content }; - }, - }), - ], - output: s.object({ - workflows: s.record(s.object({ - estimatedMinutes: s.number, - bottleneck: s.string, - optimizable: s.boolean, - })), - totalWorkflows: s.int, - }), - addons: [steering()], -}); - -export default workflowStepDurationEstimator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts deleted file mode 100644 index f10f5f2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/32-command-planner.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: build a package map for a JavaScript monorepo. -const packageMap = agent({ - model: "typecheck", - output: s.object({ - packages: s.array(s.object({ - name: s.string, - path: s.string, - private: s.boolean - })), - relationships: s.array(s.object({ - from: s.string, - to: s.string, - kind: s.string - })) - }), - instructions: `Build a package map for a JavaScript monorepo.`, -}); -export default packageMap; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts deleted file mode 100644 index b9d2735..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/33-readonly-investigator.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: plan shell commands for the goal. Prefer readonly commands. -const commandPlanner = agent({ - model: "typecheck", - output: s.object({ - commands: s.array(s.object({ - command: s.string, - purpose: s.string, - readonly: s.boolean - })) - }), - instructions: `Plan shell commands for the goal. Prefer readonly commands.`, -}); - -export default commandPlanner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts deleted file mode 100644 index 066fa7b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/34-intent-options.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: investigate the project using only readonly evidence. -const investigator = agent({ - model: "typecheck", - output: s.object({ - observations: s.array(s.string), - likelyEntryPoints: s.array(s.string) - }), - instructions: `Investigate the project using only readonly evidence.`, -}); -export default investigator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts deleted file mode 100644 index 91b6a0d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/35-call-options.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: parse environment outputs. -const envReader = agent({ - model: "typecheck", - output: s.object({ - nodeMajor: s.number, - files: s.array(s.string) - }), - instructions: `Parse environment outputs.`, -}); -export default envReader; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts deleted file mode 100644 index ff71fa4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/36-subagent-delegation.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: extract the most important implementation details from the topic. -const researcher = agent({ - model: "typecheck", - output: s.object({ summary: s.string, risks: s.array(s.string) }), - instructions: "Extract the most important implementation details from the topic.", -}); -// Agent role: plan the next steps and use the researcher when helpful. -const planner = agent({ - model: "typecheck", - instructions: "Plan the next steps for explaining runtime-visible schemas in one paragraph. Use the researcher when helpful.", - output: s.object({ decision: s.string, nextSteps: s.array(s.string) }), - agents: { researcher }, -}); -export default planner; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts deleted file mode 100644 index cdf309f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/37-output-with-nullable.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: summarize the diff. -const summarizeDiff = agent({ - model: "typecheck", - output: s.object({ - summary: s.string, - files: s.array(s.string) - }), - instructions: `Summarize the diff.`, -}); -// Agent role: review the diff. You may use the provided subagent conceptually. -const reviewer = agent({ - model: "typecheck", - output: s.object({ - summary: s.string, - issues: s.array(s.string) - }), - agents: { summarizeDiff }, - instructions: `Review the diff. You may use the provided subagent conceptually.`, -}); - -export default reviewer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts deleted file mode 100644 index 42513ff..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/38-exact-literal-output.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: extract event metadata. Use undefined when deletedAt is absent. -const parseEvent = agent({ - model: "typecheck", - output: s.object({ - title: s.string, - deletedAt: s.optional(s.string) - }), - instructions: `Extract event metadata. Use undefined when deletedAt is absent.`, -}); - -export default parseEvent; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts deleted file mode 100644 index a359fa7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/39-unknown-raw-output.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: convert the finding into a typed review record. -const reviewRecord = agent({ - model: "typecheck", - output: s.object({ - kind: s.enum("review-finding"), - finding: s.string, - severity: s.enum("info", "warning", "error") - }), - instructions: `Convert the finding into a typed review record.`, -}); - -export default reviewRecord; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts deleted file mode 100644 index 6fa83c8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/40-record-output.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: extract any JSON object from input.text into raw. -const extractJson = agent({ - model: "typecheck", - output: s.object({ - raw: s.unknown, - summary: s.string - }), - instructions: `Extract any JSON object from input.text into raw.`, -}); -export default extractJson; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts deleted file mode 100644 index ae4f716..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/41-parse-coverage.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: parse coverage by file path. -const coverage = agent({ - model: "typecheck", - output: s.object({ - files: s.record(s.object({ - lines: s.number, - branches: s.number, - notes: s.optional(s.string) - })) - }), - instructions: `Parse coverage by file path.`, -}); -export default coverage; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts deleted file mode 100644 index d5640b8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/42-json-repair.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, s } from "rig"; - -// Agent role: summarize the diff. - -const summarize = agent({ - model: "typecheck", - instructions: "Summarize the diff.", - output: s.object({ - summary: s.string, - }), - maxTurns: 2, -}); - -export default summarize; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts deleted file mode 100644 index 56048a1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/43-snapshot-test-updater.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: repair input.text into a JSON-compatible value. -const repair = agent({ - model: "typecheck", - output: s.object({ - repaired: s.unknown, - changes: s.array(s.string) - }), - instructions: `Repair input.text into a JSON-compatible value.`, -}); - -export default repair; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts deleted file mode 100644 index d475778..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/44-flaky-test-analysis.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: decide whether snapshot updates are legitimate. -const snapshotReview = agent({ - model: "typecheck", - output: s.object({ - safeToUpdate: s.boolean, - reason: s.string, - command: s.optional(s.string) - }), - instructions: `Decide whether snapshot updates are legitimate.`, -}); -export default snapshotReview; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts deleted file mode 100644 index 6b40e88..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/45-code-owner-suggestion.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: analyze whether the test failure appears flaky. -const flaky = agent({ - model: "typecheck", - output: s.object({ - likelyFlaky: s.boolean, - signals: s.array(s.string), - stabilizationIdeas: s.array(s.string) - }), - instructions: `Analyze whether the test failure appears flaky.`, -}); -export default flaky; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts deleted file mode 100644 index c1a67bf..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/46-prompt-intent-inspection.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: suggest owners for changed files. -const owners = agent({ - model: "typecheck", - output: s.object({ - owners: s.array(s.string), - unmatchedFiles: s.array(s.string) - }), - instructions: `Suggest owners for changed files.`, -}); -export default owners; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts deleted file mode 100644 index 95d6cae..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/47-prompt-intents.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: summarize the current git workspace changes. -const promptIntents = agent({ - model: "typecheck", - instructions: "Summarize the current git workspace changes.", - output: s.object({ - summary: s.string, - changedFiles: s.array(s.string), - }), -}); -export default promptIntents; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts deleted file mode 100644 index ddffb66..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/48-custom-engine.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: explain when to launch rig with --server. -const review = agent({ - model: "typecheck", - instructions: "Explain when to launch rig with --server instead of connecting to an HTTP Copilot server.", - output: s.object({ summary: s.string, recommendedMode: s.enum("http", "server") }), -}); -export default review; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts deleted file mode 100644 index 85e80d3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/49-timeout-signal-helper.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, timeout } from "rig"; -// Agent role: return a short response before the timeout expires. -const worker = agent({ - model: "typecheck", - instructions: "Return a short response before the timeout expires.", - addons: timeout({ timeout: 5_000 }), -}); -export default worker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts deleted file mode 100644 index 2385e94..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/50-end-to-end-release-agent.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: summarize the release candidate changes. -const analyzeChanges = agent({ model: "typecheck", - input: s.object({ diff: s.string, commits: s.string }), - output: s.object({ summary: s.string, highlights: s.array(s.string) }), - instructions: "Summarize the release candidate changes.", -}); -// Agent role: choose the safest semantic version bump. -const chooseVersion = agent({ model: "typecheck", - input: s.object({ summary: s.string, highlights: s.array(s.string) }), - output: s.object({ bump: s.enum("patch", "minor", "major"), rationale: s.string }), - instructions: "Choose the safest semantic version bump.", -}); -// Agent role: draft the release note from the chosen version bump. -const draftRelease = agent({ model: "typecheck", - input: s.object({ bump: s.enum("patch", "minor", "major"), rationale: s.string, summary: s.string }), - output: s.object({ title: s.string, checklist: s.array(s.string), risks: s.array(s.string) }), - instructions: "Draft the release note from the chosen version bump.", -}); -// Agent role: plan the next release using the provided specialists. -const releaseAgent = agent({ model: "typecheck", - instructions: p`Plan the next release using ${p.bash("git diff --stat -- .")} and ${p.bash("git log --oneline -20")}.`, - output: s.object({ title: s.string, bump: s.enum("patch", "minor", "major"), checklist: s.array(s.string), risks: s.array(s.string) }), - agents: { analyzeChanges, chooseVersion, draftRelease }, -}); -export default releaseAgent; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts deleted file mode 100644 index 1237cbd..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/51-subagent-task-harness.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: draft a runnable rig markdown snippet for the requested task. -const draftRigMarkdown = agent({ - model: "typecheck", - output: s.object({ markdown: s.string }), - instructions: "Return exactly one markdown response with one ```rig fenced block.", -}); -// Agent role: validate generated rig code by running TypeScript in no-emit mode. -const typecheckRigProgram = agent({ - model: "typecheck", - output: s.object({ ok: s.boolean, diagnostics: s.string }), - instructions: p`Run ${p.bash("npx tsc --noEmit --pretty false")} and summarize whether typecheck passed.`, -}); -// Agent role: solve the task by delegating to subagents and returning markdown. -const solveTask = agent({ - model: "typecheck", - output: s.object({ markdown: s.string }), - agents: { draftRigMarkdown, typecheckRigProgram }, - instructions: "Use the drafting subagent, validate with typecheck, then return one runnable rig markdown snippet.", -}); -export default solveTask; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts deleted file mode 100644 index 6a71165..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/52-claude-design.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: coordinate writer/critic/reviser to produce one final response. -const writer = agent({ - model: "typecheck", - output: s.object({ draft: s.string }), - instructions: "Write a helpful, clear response to the request.", -}); -const critic = agent({ - model: "typecheck", - input: s.object({ request: s.string, draft: s.string }), - output: s.object({ issues: s.array(s.string), score: s.number, acceptable: s.boolean }), - instructions: "Evaluate the draft against helpfulness, harmlessness, and honesty principles.", -}); -const reviser = agent({ - model: "typecheck", - input: s.object({ request: s.string, draft: s.string, issues: s.array(s.string) }), - output: s.object({ response: s.string }), - instructions: "Revise the draft to address all issues identified by the critic.", -}); -const root = agent({ model: "typecheck", - instructions: "Use writer, critic, and reviser to produce one final response.", - output: s.object({ response: s.string }), - agents: { writer, critic, reviser }, -}); -export default root; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts deleted file mode 100644 index f49cf75..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/53-ralf-loop.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: diagnose failing tests and decide if the loop is done. -const diagnose = agent({ - model: "typecheck", - input: s.object({ ok: s.boolean, stdout: s.string, exitCode: s.number }), - output: s.object({ done: s.boolean, rootCause: s.string }), - instructions: "Diagnose test failures. Set done to true if all tests passed.", -}); -// Agent role: apply the smallest safe fix for the root cause. -const fix = agent({ - model: "typecheck", - output: s.object({ summary: s.string, changed: s.boolean }), - instructions: "Apply the smallest safe fix for the root cause.", -}); -// Agent role: run a RALF loop iterating diagnose-fix cycles until tests pass. -const ralfLoop = agent({ - model: "typecheck", - output: s.object({ iterations: s.number, fixed: s.boolean }), - agents: { diagnose, fix }, - instructions: p`Run ${p.bash("npm test")} then loop: diagnose failures, fix, repeat up to 3 times.`, -}); -export default ralfLoop; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts deleted file mode 100644 index 26f767d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/54-large-scale-summarization.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: summarize one evidence shard cheaply with a small model. -const summarizeShard = agent({ model: "typecheck", input: s.object({ scenario: s.string, shardLabel: s.string, evidence: s.string }), output: s.object({ shardLabel: s.string, summary: s.string, facts: s.array(s.string) }), instructions: "Summarize only high-signal facts." }); -// Agent role: merge shard summaries into one concise final summary. -const reduceScenario = agent({ model: "typecheck", input: s.object({ scenario: s.string, shardSummaries: s.array(s.object({ shardLabel: s.string, summary: s.string, facts: s.array(s.string) })) }), output: s.object({ scenario: s.string, summary: s.string, savings: s.string }), instructions: "Deduplicate facts and keep the final summary short." }); -// Agent role: orchestrate deterministic search + parallel shard summarization for nine large-scale scenarios. -const summarizeAtScale = agent({ - model: "typecheck", - output: s.object({ scenarios: s.array(s.object({ id: s.string, summary: s.string })), costNotes: s.array(s.string) }), - agents: { summarizeShard, reduceScenario }, - instructions: p`Cover: git diff, 24h repo changes, 24h exported/doc updates, semantic search (query->rg shards->shard summaries->final), plus 24h CI failures, auth/permission changes, dependency risk, API impact, and monorepo owner impact. Use ${p.bash("rg -n \"export|auth|permission|schema\" src docs || true")} and ${p.bash("git log --since='24 hours ago' --name-status --pretty=format:'%h %s'")} first, then parallelize shard work with Promises and use large-model reduction only once per scenario.`, -}); -export default summarizeAtScale; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts deleted file mode 100644 index 55dc29d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-file-change-lint-middleware.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { agent, s, type AgentAddon } from "rig"; -import { $ } from "zx"; - -const fingerprint = async () => { - const { exitCode, stdout } = await $`git status --porcelain`.nothrow(); - return exitCode === 0 ? stdout.trim() : ""; -}; -const lintOnFileChange = (runLint: () => Promise): AgentAddon => async (_context, next) => { - const before = await fingerprint(); - await next(); - const after = await fingerprint(); - if (before !== after) await runLint(); -}; - -// Agent role: update files and run linting after file changes. -const fileChangeMiddleware = agent({ - model: "typecheck", - instructions: "Update files when needed, then summarize the change.", - output: s.object({ changed: s.boolean, summary: s.string }), - addons: lintOnFileChange(() => $`npm run typecheck`), -}); - -export default fileChangeMiddleware; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts deleted file mode 100644 index f017bf5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/55-genaiscript-glossary-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: extract advanced rig glossary terms from docs. -const glossaryPort = agent({ - model: "typecheck", - instructions: p`Read ${p.read("README.md")} and ${p.read("skills/rig/SKILL.md")}. Return only advanced rig terms with short definitions and skip duplicates.`, - output: s.object({ terms: s.array(s.object({ term: s.string, definition: s.string })) }), -}); -export default glossaryPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts deleted file mode 100644 index 19135f6..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/56-genaiscript-refactor-batch-port.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: suggest metadata refactors for the first three sample files. -const refactorOne = agent({ model: "typecheck", instructions: "Suggest one minimal metadata cleanup for a rig sample.", output: s.object({ file: s.string, change: s.string }) }); -const refactorBatch = agent({ - model: "typecheck", - instructions: p`Inspect ${p.bash("find skills/rig/samples -maxdepth 1 -name '*.md' | sort | head -n 3")}. Use refactorOne when helpful and return only the smallest safe cleanup suggestions.`, - output: s.object({ suggestions: s.array(s.object({ file: s.string, change: s.string })) }), - agents: { refactorOne }, -}); -export default refactorBatch; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts deleted file mode 100644 index e928f1a..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/57-genaiscript-issue-review-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: review a GitHub issue report and return concise feedback. -const issueReviewPort = agent({ - model: "typecheck", - instructions: "Review this issue draft: \"The CLI crashes sometimes when reading stdin programs on Windows. I expected it to work.\" Ask only for missing reproduction details and missing expected behavior.", - output: s.object({ summary: s.string, questions: s.array(s.string) }), -}); -export default issueReviewPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts deleted file mode 100644 index 7d81e90..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/58-genaiscript-travel-plan-port.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: merge local advice and language tips into one travel plan. -const localGuide = agent({ model: "typecheck", instructions: "Suggest authentic places and activities for a 3-day trip to Egypt.", output: s.object({ ideas: s.array(s.string) }) }); -const languageTips = agent({ model: "typecheck", instructions: "Suggest communication tips for a 3-day trip to Egypt.", output: s.object({ tips: s.array(s.string) }) }); -const travelPlanPort = agent({ - model: "typecheck", - instructions: "Plan a 3-day trip to Egypt. Use localGuide and languageTips when helpful, then return one integrated itinerary.", - output: s.object({ itinerary: s.array(s.string), tips: s.array(s.string) }), - agents: { localGuide, languageTips }, -}); -export default travelPlanPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts deleted file mode 100644 index 8152153..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/59-genaiscript-city-info-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: extract structured city facts from a short dataset. -const cityInfoPort = agent({ - model: "typecheck", - instructions: "From this dataset, return a JSON array of city facts only: Cairo | population 10.1M | https://en.wikipedia.org/wiki/Cairo ; Alexandria | population 5.6M | https://en.wikipedia.org/wiki/Alexandria ; Giza | population 4.8M | https://en.wikipedia.org/wiki/Giza.", - output: s.array(s.object({ name: s.string, population: s.number, url: s.string })), -}); -export default cityInfoPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts deleted file mode 100644 index b40fb5d..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-genaiscript-schema-cities-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, s } from "rig"; -// Agent role: invent five city records that match a strict schema. -const schemaCitiesPort = agent({ - model: "typecheck", - instructions: "Give 5 cities with their populations and Wikipedia URLs. Return only valid output.", - output: s.array(s.object({ name: s.string, population: s.number, url: s.string })), -}); -export default schemaCitiesPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts deleted file mode 100644 index 93e3701..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/60-workflow-parallel-linter.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { agent, s, workflow } from "rig"; - -// Agent role: check one TypeScript file for code quality issues. -const lintFile = agent({ - name: "lintFile", - model: "typecheck", - input: s.object({ file: s.path }), - output: s.object({ issues: s.array(s.string) }), - instructions: "Check the file for linting issues.", -}); - -// Workflow role: discover and lint TypeScript source files in parallel. -const linter = workflow({ - meta: { name: "linter", description: "Lint TypeScript files in parallel", phases: ["Discover", "Lint"] }, - body: async ({ call, phase, pipeline }) => { - phase("Discover"); - const raw = await call.text("List TypeScript source files to lint, one path per line."); - const files = (raw ?? "").split("\n").map((f) => f.trim()).filter(Boolean); - phase("Lint"); - return pipeline(files, (file) => call(lintFile, { file }, { label: file })); - }, -}); - -export default linter; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts deleted file mode 100644 index d9af390..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/61-genaiscript-list-files-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: pick the most interesting rig sample files. -const listFilesPort = agent({ - model: "typecheck", - instructions: p`Review ${p.bash("find skills/rig/samples -maxdepth 1 -name '*.md' | sort")}. Select the 3 most interesting sample files.`, - output: s.object({ files: s.array(s.string) }), -}); -export default listFilesPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts deleted file mode 100644 index 5bc441f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/62-genaiscript-todo-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: propose minimal TODO implementations from the current workspace. -const todoPort = agent({ - model: "typecheck", - instructions: p`Check ${p.bash("rg -n 'TODO' src skills scripts . || true")}. For up to one actionable TODO, return the target file and the minimal implementation plan.`, - output: s.object({ todos: s.array(s.object({ file: s.string, plan: s.string })) }), -}); -export default todoPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts deleted file mode 100644 index 73c1ac3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/63-genaiscript-slide-deck-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: turn the README into a short slide deck outline. -const slideDeckPort = agent({ - model: "typecheck", - instructions: p`Read ${p.read("README.md")} and draft a short markdown slide deck outline with terse titles and short bullets.`, - output: s.object({ slides: s.array(s.object({ title: s.string, bullets: s.array(s.string) })) }), -}); -export default slideDeckPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts deleted file mode 100644 index 49d23de..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/64-genaiscript-grumpy-review-port.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: review one rig sample in a terse critical voice. -const grumpyReviewPort = agent({ - model: "typecheck", - instructions: p`Review ${p.read("skills/rig/samples/36-subagent-delegation.md")} in a terse senior-engineer voice. Be specific, but keep each point short.`, - output: s.object({ findings: s.array(s.string), verdict: s.string }), -}); -export default grumpyReviewPort; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts deleted file mode 100644 index 4ffaa39..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/65-source-file-annotator.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: generate JSDoc comments for the TypeScript source file provided. -const jsdocWriter = agent({ - model: "typecheck", - input: s.object({ path: s.nonEmptyString, source: s.string }), - output: s.object({ annotated: s.string }), - instructions: "Add JSDoc comments to all exported functions and classes in the source file. Return only the annotated source.", -}); - -// Agent role: annotate TypeScript source files with JSDoc using a subagent, then write the results. -const annotator = agent({ - model: "typecheck", - instructions: p`Annotate each TypeScript file found by ${p.glob("src/**/*.ts")} using the jsdocWriter subagent, then write each annotated file back with ${p.write("src/annotated.ts", "placeholder")}. Hard-code the output path in the report.`, - output: s.object({ - processed: s.array(s.nonEmptyString), - skipped: s.array(s.nonEmptyString), - reportPath: s.string, - }), - agents: { jsdocWriter }, -}); - -export default annotator; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts deleted file mode 100644 index 6054b41..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/66-ci-workflow-health.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, defineTool, p, s, repair } from "rig"; - -const parseYamlSteps = defineTool("parse_yaml_steps", { - description: "Extract step names and uses from a YAML workflow file.", - parameters: s.object({ path: s.nonEmptyString }), - handler: async ({ path }) => { - const { readFileSync } = await import("node:fs"); - try { - const content = readFileSync(path, "utf8"); - const steps = [...content.matchAll(/^\s+-\s+(?:name|uses):\s+(.+)$/gm)].map((m) => m[1]); - return JSON.stringify(steps); - } catch { return "[]"; } - }, -}); - -// Agent role: analyze CI workflow files and return a list of health issues. -const ciWorkflowAnalyzer = agent({ - model: "typecheck", - maxTurns: 3, - addons: repair(), - instructions: p`Scan ${p.glob(".github/workflows/*.yml")} and ${p.bashRaw`find .github/workflows -name '*.yaml' 2>/dev/null`} for workflow health issues. Use parse_yaml_steps to inspect individual files.`, - output: s.object({ - issues: s.array(s.object({ workflow: s.nonEmptyString, severity: s.enum("info", "warning", "error"), message: s.string, fix: s.optional(s.string) })), - healthy: s.boolean, - }), - tools: [parseYamlSteps], -}); - -export default ciWorkflowAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts deleted file mode 100644 index d76a5c2..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/67-glob-file-summarizer.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s } from "rig"; -// Agent role: summarize TypeScript source files found by glob and return a record keyed by path. -const fileSummarizer = agent({ - model: "typecheck", - input: s.object({ path: s.string, content: s.string }), - output: s.object({ path: s.string, summary: s.string }), - instructions: "Summarize the file content in one sentence.", -}); - -// Agent role: find all TypeScript files with p.glob, then use fileSummarizer to summarize each. -const globSummarizer = agent({ - model: "typecheck", - output: s.record(s.string, "summaries keyed by file path"), - agents: { fileSummarizer }, - instructions: p`Find TypeScript source files: ${p.glob("src/**/*.ts")}. For each file use fileSummarizer to produce a one-sentence summary, then return a record mapping each path to its summary.`, -}); -export default globSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts deleted file mode 100644 index 1030532..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/68-changelog-generator.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const validateSemver = defineTool("validateSemver", { - description: "Validate that a bump type is major, minor, or patch", - parameters: s.object({ bump: s.string }), - handler({ bump }) { - const valid = ["major", "minor", "patch"].includes(bump); - return { valid }; - }, -}); - -// Agent role: read recent git changes and produce a structured changelog entry with semver bump classification. -const changelogGenerator = agent({ - model: "typecheck", - instructions: p`Review ${p.bash("git diff HEAD~1 HEAD --stat")} and ${p.bash("git log HEAD~1..HEAD --oneline")} to produce a changelog entry. Classify each change by category and determine the semver bump type. Use the validateSemver tool to confirm the bump value. Write the markdown changelog to CHANGELOG.md via ${p.write("CHANGELOG.md", "")}`, - output: s.object({ - version: s.string, - bump: s.enum("major", "minor", "patch"), - entries: s.array(s.object({ - category: s.enum("feat", "fix", "chore", "docs", "refactor"), - description: s.string, - })), - markdown: s.string, - }), - tools: [validateSemver], - maxTurns: 6, - addons: repair(), -}); - -export default changelogGenerator; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts deleted file mode 100644 index 4a17622..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/69-todo-comment-tracker.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: scan source files for TODO/FIXME/HACK comments and produce a structured report. -const todoCommentTracker = agent({ - model: "typecheck", - instructions: p`Scan source files using ${p.bash("grep -rn 'TODO\\|FIXME\\|HACK' --include='*.ts' . 2>/dev/null || true")} and produce a structured list of all found comments. Write a markdown report to todo-report.md via ${p.write("todo-report.md", "")}`, - output: s.object({ - items: s.array(s.object({ - file: s.path, - line: s.int, - kind: s.enum("TODO", "FIXME", "HACK"), - message: s.string, - })), - totalCount: s.int, - markdown: s.string, - }), -}); - -export default todoCommentTracker; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts deleted file mode 100644 index 3564487..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/70-multi-file-subagent-summarizer.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, p, s, workflow } from "rig"; -// Agent role: summarize a single TypeScript file. -const fileSummarizer = agent({ - name: "fileSummarizer", - model: "typecheck", - input: s.object({ filePath: s.path }), - instructions: p`Summarize the TypeScript file at ${p.readInput("filePath")} in one concise sentence.`, - output: s.object({ summary: s.string }), -}); -// Workflow role: deterministically discover files, run subagent summaries in parallel, and aggregate by file path. -const multiFileSummarizer = workflow({ - meta: { name: "multiFileSummarizer", description: "Summarize TypeScript files", phases: ["Discover", "Summarize"] }, - body: async ({ call, phase, pipeline }) => { - phase("Discover"); - const raw = await call.text( - `List up to 10 TypeScript files from src (one path per line) using ${p.bash("find src -name '*.ts' -not -path '*/node_modules/*' 2>/dev/null | head -10 || true")}.`, - ); - const files = (raw ?? "").split("\n").map((x) => x.trim()).filter(Boolean); - phase("Summarize"); - const rows = await pipeline(files, async (filePath) => { - const out = await call(fileSummarizer, { filePath }, { label: filePath }); - return out ? [filePath, out.summary] as const : null; - }); - return Object.fromEntries(rows.filter((row): row is readonly [string, string] => !!row)); - }, -}); - -export default multiFileSummarizer; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts deleted file mode 100644 index dfcc6c7..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/71-package-script-health.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const validateScriptName = defineTool("validateScriptName", { - description: "Validate that a package.json script name follows conventional naming (lowercase, hyphens only)", - parameters: s.object({ name: s.string }), - handler({ name }) { - const valid = /^[a-z][a-z0-9:-]*$/.test(name); - const reason = valid ? "Name is conventional" : "Name should be lowercase with hyphens/colons only"; - return { valid, reason }; - }, -}); - -// Agent role: analyze package.json scripts for naming and structural health issues. -const packageScriptHealth = agent({ - model: "typecheck", - instructions: p`Read ${p.read("package.json")} and analyze all scripts entries. Use the validateScriptName tool for each script name. Classify each issue by severity and determine overall health.`, - output: s.object({ - issues: s.array(s.object({ - script: s.string, - issue: s.string, - status: s.enum("error", "warning", "ok"), - })), - overallHealth: s.enum("healthy", "degraded", "critical"), - }), - tools: [validateScriptName], - maxTurns: 6, - addons: repair(), -}); - -export default packageScriptHealth; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts deleted file mode 100644 index 98d8aef..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/72-ts-function-signatures.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parseSignatures = defineTool("parseSignatures", { - description: "Extract function signatures from TypeScript source content using regex", - parameters: s.object({ content: s.string }), - handler({ content }) { - const pattern = /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/g; - const functions: { name: string; paramCount: number; isExported: boolean }[] = []; - let match; - while ((match = pattern.exec(content)) !== null) { - const [full, name, params] = match; - const paramCount = params.trim() === "" ? 0 : params.split(",").length; - const isExported = full.trimStart().startsWith("export"); - functions.push({ name, paramCount, isExported }); - } - return { functions }; - }, -}); - -// Agent role: extract TypeScript function signatures from source files and return them keyed by file path. -const tsFunctionSignatures = agent({ - model: "typecheck", - instructions: p`Find TypeScript files using ${p.bash("find src -name '*.ts' 2>/dev/null | head -5 || echo 'no files'")} then read each file and use the parseSignatures tool to extract function signatures. Return results keyed by file path.`, - output: s.record(s.array(s.object({ - name: s.string, - paramCount: s.int, - isExported: s.boolean, - }))), - tools: [parseSignatures], -}); - -export default tsFunctionSignatures; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts deleted file mode 100644 index 1463280..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/73-git-branch-pruner.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: identify git branches that are candidates for pruning based on merge status and last commit date. -const gitBranchPruner = agent({ - model: "typecheck", - instructions: p`Analyze git branches using ${p.bash("git branch --merged HEAD 2>/dev/null || echo 'no branches'")} and ${p.bash("git for-each-ref --format='%(refname:short) %(committerdate:short)' refs/heads/ 2>/dev/null || echo 'no refs'")}. For each branch determine if it should be pruned (merged and not main/master/develop) or kept. Exclude the current branch from prune candidates.`, - output: s.object({ - candidates: s.array(s.object({ - branch: s.string, - lastCommitDate: s.optional(s.string), - action: s.enum("keep", "prune"), - reason: s.string, - })), - totalBranches: s.int, - pruneCount: s.int, - }), - maxTurns: 6, - addons: repair(), -}); - -export default gitBranchPruner; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts deleted file mode 100644 index 87df4b4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/74-prettier-eslint-compat.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const detectConflicts = defineTool("detectConflicts", { - description: "Detect rule conflicts between Prettier and ESLint configs", - parameters: s.object({ prettierConfig: s.string, eslintConfig: s.string }), - handler({ prettierConfig, eslintConfig }) { - const conflicts: { rule: string; prettier: string; eslint: string; fixable: boolean }[] = []; - try { - const p = JSON.parse(prettierConfig || "{}"); - const e = JSON.parse(eslintConfig || "{}"); - const rules = (e.rules || {}); - if (p.printWidth && rules["max-len"]) { - conflicts.push({ rule: "line-length", prettier: `printWidth: ${p.printWidth}`, eslint: `max-len: ${JSON.stringify(rules["max-len"])}`, fixable: true }); - } - if (p.singleQuote !== undefined && rules["quotes"]) { - conflicts.push({ rule: "quotes", prettier: `singleQuote: ${p.singleQuote}`, eslint: `quotes: ${JSON.stringify(rules["quotes"])}`, fixable: true }); - } - } catch { - // invalid JSON — model will handle - } - return { conflicts }; - }, -}); - -// Agent role: check Prettier and ESLint configs for rule conflicts and report compatibility issues. -const prettierEslintCompat = agent({ - model: "typecheck", - instructions: p`Read the Prettier config ${p.readOptional(".prettierrc")} and ESLint config ${p.readOptional(".eslintrc.json")} then use the detectConflicts tool to find rule conflicts. Classify each conflict by severity.`, - output: s.object({ - conflicts: s.array(s.object({ - rule: s.string, - prettier: s.string, - eslint: s.string, - fixable: s.boolean, - severity: s.enum("error", "warning", "info"), - })), - compatible: s.boolean, - }), - tools: [detectConflicts], - maxTurns: 6, - addons: repair(), -}); - -export default prettierEslintCompat; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts deleted file mode 100644 index b85ab02..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/75-workflow-validator.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze a single GitHub Actions workflow file for structural issues and job count. -const workflowAnalyzer = agent({ - name: "workflowAnalyzer", - model: "typecheck", - input: s.object({ filePath: s.path }), - instructions: p`Analyze the GitHub Actions workflow file at ${p.readInput("filePath")} for issues such as missing permissions, deprecated actions, hardcoded secrets, or missing timeout-minutes. Count the number of jobs defined.`, - output: s.object({ - issues: s.array(s.object({ - step: s.string, - problem: s.string, - severity: s.enum("error", "warning", "info"), - })), - jobCount: s.int, - }), -}); - -// Agent role: find all GitHub Actions workflow files and delegate analysis to workflowAnalyzer subagent, then aggregate results. -const workflowValidator = agent({ - model: "typecheck", - instructions: p`Find GitHub Actions workflow files using ${p.bash("find .github/workflows -name '*.yml' -o -name '*.yaml' 2>/dev/null | head -10 || echo 'no workflows'")} then delegate each file to the workflowAnalyzer subagent. Aggregate results keyed by filename, adding a pass/warn/fail status based on issue severity.`, - output: s.record(s.object({ - issues: s.array(s.object({ - step: s.string, - problem: s.string, - severity: s.enum("error", "warning", "info"), - })), - jobCount: s.int, - status: s.enum("pass", "warn", "fail"), - })), - agents: { workflowAnalyzer }, -}); - -export default workflowValidator; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts deleted file mode 100644 index 0b809d4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/76-commit-msg-rewriter.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { agent, p, s, steering, repair } from "rig"; - -// Agent role: rewrite recent git commit messages into conventional commit format with imperative mood. -const commitMsgRewriter = agent({ - model: "typecheck", - instructions: p`Review recent commits from ${p.bash("git log --oneline -20 2>/dev/null || echo 'no commits'")} and rewrite each message in conventional commit format (feat:/fix:/chore:/docs:/test:/refactor:/style: prefix) with imperative mood. Write a markdown summary of all rewrites via ${p.writeOutput("markdown", "commit-rewrites.md")}`, - output: s.object({ - rewrites: s.array(s.object({ - hash: s.string, - original: s.string, - revised: s.string, - category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), - })), - markdown: s.string, - }), - maxTurns: 6, - addons: [steering({ message: "Use imperative mood and conventional commit prefixes. Be consistent." }), repair()], -}); - -export default commitMsgRewriter; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts deleted file mode 100644 index f4c7517..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/77-env-key-checker.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parseEnvKeys = defineTool("parseEnvKeys", { - description: "Extract KEY names from dotenv-style file content", - parameters: s.object({ content: s.string }), - handler({ content }) { - const keys = (content.match(/^([A-Z_][A-Z0-9_]*)=/gm) || []) - .map((line: string) => line.replace("=", "")); - return { keys }; - }, -}); - -// Agent role: compare .env.example required keys against .env actual keys to find missing and extra entries. -const envKeyChecker = agent({ - model: "typecheck", - instructions: p`Read the required env keys from ${p.readOptional(".env.example")} and the present keys from ${p.readOptional(".env")}. Use the parseEnvKeys tool on each file content to extract key names. Compare to find missing keys (in example but not env) and extra keys (in env but not example).`, - output: s.object({ - missing: s.array(s.string), - extra: s.array(s.string), - requiredCount: s.int, - presentCount: s.int, - status: s.enum("complete", "partial", "empty"), - }), - tools: [parseEnvKeys], -}); - -export default envKeyChecker; - diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts deleted file mode 100644 index fd29459..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/78-build-log-analyzer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: run the build and analyze the output for errors, warnings, and success status. -const buildLogAnalyzer = agent({ - model: "typecheck", - instructions: p`Run the build command and analyze its output: ${p.bash("npm run build 2>&1 || true")}. Extract all errors and warnings with their severity and file location if available. Determine whether the build succeeded overall.`, - output: s.object({ - errors: s.array(s.object({ - message: s.string, - file: s.optional(s.string), - severity: s.enum("error", "warning", "info"), - })), - buildSucceeded: s.boolean, - summary: s.string, - }), - maxTurns: 5, - addons: repair(), -}); - -export default buildLogAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts deleted file mode 100644 index c0833c5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/79-ts-type-alias-mapper.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const categorizeAlias = defineTool("categorizeAlias", { - description: "Categorize a TypeScript type alias definition by its kind using regex", - parameters: s.object({ definition: s.string }), - handler({ definition }) { - const trimmed = definition.trim(); - if (/=\s*\w+\s*\|/.test(trimmed)) return { kind: "union" }; - if (/=\s*\w+\s*&/.test(trimmed)) return { kind: "intersection" }; - if (/=\s*\{[^}]*\[[^\]]+\]/.test(trimmed)) return { kind: "mapped" }; - if (/=\s*(string|number|boolean|null|undefined|never|any|unknown)\s*$/.test(trimmed)) return { kind: "primitive" }; - return { kind: "other" }; - }, -}); - -// Agent role: scan TypeScript files for type alias declarations and categorize each one. -const tsTypeAliasMapper = agent({ - model: "typecheck", - instructions: p`Find all TypeScript files: ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' -not -path '*/.git/*'")} and scan their contents: ${p.bash("grep -rn 'type [A-Z]' --include='*.ts' --exclude-dir=node_modules --exclude-dir=.git . 2>/dev/null || true")}. Use the categorizeAlias tool to classify each type alias. For each alias, also record whether it is exported (starts with 'export type').`, - output: s.record(s.object({ - kind: s.enum("primitive", "union", "intersection", "mapped", "other"), - exported: s.boolean, - })), - tools: [categorizeAlias], -}); - -export default tsTypeAliasMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts deleted file mode 100644 index b0298d4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/80-git-contributor-mapper.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: map git contributors to their commit counts, primary work areas, and role classification. -const gitContributorMapper = agent({ - model: "typecheck", - instructions: p`Analyze git contributors using: ${p.bash("git shortlog -sn --no-merges")} and ${p.bash("git log --no-merges --name-only --pretty=format:'%an' | head -500")}. For each contributor, count their commits, identify which directories they primarily touch, and classify their role as core (many commits across many files), peripheral (few commits or limited scope), or single-file.`, - output: s.record(s.object({ - commitCount: s.number, - primaryAreas: s.array(s.string), - role: s.enum("core", "peripheral", "single-file"), - })), -}); - -export default gitContributorMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts deleted file mode 100644 index 01fa916..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/81-markdown-doc-summarizer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize each top-level section of the README, then compile into a full report. -const sectionSummarizer = agent({ - name: "sectionSummarizer", - model: "typecheck", - instructions: p`Summarize the section of documentation provided in the input.`, - input: s.object({ heading: s.string, content: s.string }), - output: s.object({ heading: s.string, summary: s.string }), -}); - -// Agent role: read the project README, delegate per-section summarization, and write the final report. -const markdownDocSummarizer = agent({ - model: "typecheck", - instructions: p`Read the README: ${p.readOptional("README.md", "No README found.")}. Identify each top-level heading (##) and its content. Delegate summarization of each section to the sectionSummarizer agent. Compile all summaries into a report and write it to summaries/README-summary.md via ${p.writeOutput("reportPath", "summaries/README-summary.md")}.`, - output: s.object({ - sections: s.array(s.object({ heading: s.string, summary: s.string })), - reportPath: s.string, - }), - agents: { sectionSummarizer }, -}); - -export default markdownDocSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts deleted file mode 100644 index 1d32f32..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/82-workspace-config-drift.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseJson = defineTool("parseJson", { - description: "Parse a JSON string and return it, or report a parse error", - parameters: s.object({ content: s.string, filename: s.string }), - handler({ content, filename }) { - try { - const parsed = JSON.parse(content); - return { ok: true, parsed }; - } catch (e) { - return { ok: false, error: String(e), filename }; - } - }, -}); - -// Agent role: detect drift in workspace config files by reading them and comparing against known defaults. -const workspaceConfigDrift = agent({ - model: "typecheck", - instructions: p`Read project config files: ${p.readOptional("tsconfig.json", "{}")} (tsconfig.json), ${p.readOptional(".eslintrc.json", "{}")} (.eslintrc.json), ${p.readOptional(".prettierrc", "{}")} (.prettierrc). Use the parseJson tool to parse each file. For each config, identify fields that deviate from sensible defaults and report them as drifted. Assign status ok if no drift, warning for minor issues, error for significant mismatches.`, - output: s.record(s.object({ - driftedFields: s.array(s.string), - status: s.enum("ok", "warning", "error"), - })), - tools: [parseJson], - maxTurns: 4, - addons: repair(), -}); - -export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts deleted file mode 100644 index 28e2897..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/83-commit-format-suggester.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair, steering } from "rig"; - -// Agent role: review recent git commits and suggest conventional-format rewrites for each one. -const commitFormatSuggester = agent({ - model: "typecheck", - instructions: p`Review recent git commits: ${p.bash("git log --oneline -20 --no-merges")}. For each commit, check whether its message follows conventional commit format (type: description). Suggest a rewritten message in conventional format. Classify each commit as one of: feat, fix, chore, docs, test, refactor, style. Write the full report to commit-report.md via ${p.writeOutput("reportWritten", "commit-report.md")}.`, - output: s.array(s.object({ - hash: s.string, - original: s.string, - suggested: s.string, - category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), - })), - maxTurns: 5, - addons: [steering(), repair()], -}); - -export default commitFormatSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts deleted file mode 100644 index b960ec3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/84-json-schema-migration.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: analyze two JSON schema files to identify structural changes and produce a migration plan. -const diffAnalyzer = agent({ - name: "diffAnalyzer", - model: "typecheck", - instructions: p`Analyze the structural differences between the two JSON schemas provided in the input and list each change type (add, remove, modify, rename) with the JSON path and whether it is a breaking change.`, - input: s.object({ oldSchema: s.string, newSchema: s.string }), - output: s.array(s.object({ - changeType: s.enum("add", "remove", "modify", "rename"), - path: s.string, - description: s.string, - breakingChange: s.boolean, - })), -}); - -// Agent role: read two JSON schema files and coordinate a migration plan using the diffAnalyzer subagent. -const jsonSchemaMigration = agent({ - model: "typecheck", - input: s.object({ oldSchemaPath: s.path, newSchemaPath: s.path }), - instructions: p`Read the old schema at ${p.readInput("oldSchemaPath")} and new schema at ${p.readInput("newSchemaPath")}. Pass both to the diffAnalyzer subagent to identify all changes and whether each is a breaking change.`, - output: s.array(s.object({ - changeType: s.enum("add", "remove", "modify", "rename"), - path: s.string, - description: s.string, - breakingChange: s.boolean, - })), - agents: { diffAnalyzer }, -}); - -export default jsonSchemaMigration; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts deleted file mode 100644 index ab26b5b..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/85-dockerfile-security-audit.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const checkSecurityPattern = defineTool("checkSecurityPattern", { - description: "Check a Dockerfile line for known security anti-patterns", - parameters: s.object({ line: s.string, lineNumber: s.number }), - handler({ line, lineNumber }) { - const findings: Array<{ severity: string; message: string; rule: string }> = []; - if (/^USER\s+root\s*$/i.test(line.trim()) || /^RUN.*&&.*&&.*--no-check/.test(line)) { - findings.push({ severity: "critical", message: "Running as root user", rule: "no-root-user" }); - } - if (/ADD\s+/.test(line) && !/ADD\s+https?:\/\//.test(line)) { - findings.push({ severity: "medium", message: "Prefer COPY over ADD for local files", rule: "prefer-copy" }); - } - if (/FROM\s+\S+:latest/.test(line)) { - findings.push({ severity: "high", message: "Avoid :latest tag for reproducibility", rule: "no-latest-tag" }); - } - if (/ENV\s+\w*(KEY|SECRET|PASSWORD|TOKEN)\w*\s*=/.test(line)) { - findings.push({ severity: "critical", message: "Secret embedded in ENV instruction", rule: "no-secrets-in-env" }); - } - return { lineNumber, findings }; - }, -}); - -// Agent role: audit a Dockerfile for security issues by scanning each instruction for known anti-patterns. -const dockerfileSecurityAudit = agent({ - model: "typecheck", - input: s.object({ dockerfilePath: s.path }), - instructions: p`Read the Dockerfile at ${p.readInput("dockerfilePath")}. Use the checkSecurityPattern tool on each instruction line to detect security issues. Compile all findings with their severity, line number, rule, and message.`, - output: s.object({ - findings: s.array(s.object({ - severity: s.enum("critical", "high", "medium", "low"), - lineNumber: s.number, - message: s.string, - rule: s.string, - })), - passes: s.boolean, - }), - tools: [checkSecurityPattern], -}); - -export default dockerfileSecurityAudit; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts deleted file mode 100644 index 28553a8..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/86-npm-audit-simplifier.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, p, s, repair } from "rig"; - -// Agent role: run npm audit, parse the JSON output, and produce a simplified vulnerability report. -const npmAuditSimplifier = agent({ - model: "typecheck", - instructions: p`Run ${p.bash("npm audit --json 2>/dev/null || echo '{}'")} to get the vulnerability report. Parse the JSON and group vulnerabilities by severity level (critical, high, moderate, low, info). Count the total number of vulnerabilities. Provide a one-sentence recommendation for remediation.`, - output: s.object({ - vulnerabilitiesByLevel: s.record(s.array(s.string)), - totalCount: s.number, - recommendation: s.string, - }), - maxTurns: 5, - addons: repair(), -}); - -export default npmAuditSimplifier; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts deleted file mode 100644 index 20fd44e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/87-git-stash-inventory.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: inventory all git stashes with their descriptions, changed files, and staleness classification. -const gitStashInventory = agent({ - model: "typecheck", - instructions: p`List all git stashes: ${p.bash("git stash list 2>/dev/null || echo 'No stashes found'")}. For each stash entry shown, show its changed files: ${p.bash("git stash show --name-only 2>/dev/null || true")}. For each stash, classify its staleness as: fresh (< 1 week), aging (1-4 weeks), stale (1-3 months), ancient (> 3 months) based on the date shown in the stash list.`, - output: s.array(s.object({ - stashRef: s.string, - description: s.string, - changedFiles: s.array(s.string), - staleness: s.enum("fresh", "aging", "stale", "ancient"), - })), -}); - -export default gitStashInventory; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts deleted file mode 100644 index b0298d4..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/88-git-contributor-mapper.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: map git contributors to their commit counts, primary work areas, and role classification. -const gitContributorMapper = agent({ - model: "typecheck", - instructions: p`Analyze git contributors using: ${p.bash("git shortlog -sn --no-merges")} and ${p.bash("git log --no-merges --name-only --pretty=format:'%an' | head -500")}. For each contributor, count their commits, identify which directories they primarily touch, and classify their role as core (many commits across many files), peripheral (few commits or limited scope), or single-file.`, - output: s.record(s.object({ - commitCount: s.number, - primaryAreas: s.array(s.string), - role: s.enum("core", "peripheral", "single-file"), - })), -}); - -export default gitContributorMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts deleted file mode 100644 index 43704e3..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/89-markdown-doc-summarizer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { agent, p, s } from "rig"; - -// Agent role: summarize each top-level section of a markdown doc, then compile into a full report. -const sectionSummarizer = agent({ - name: "sectionSummarizer", - model: "typecheck", - instructions: p`Summarize the section of documentation provided in the input.`, - input: s.object({ heading: s.string, content: s.string }), - output: s.object({ heading: s.string, summary: s.string }), -}); - -// Agent role: read the project README, delegate per-section summarization, and write the final report. -const markdownDocSummarizer = agent({ - model: "typecheck", - instructions: p`Read the README: ${p.readOptional("README.md", "No README found.")}. Identify each top-level heading (##) and its content. Delegate summarization of each section to the sectionSummarizer agent. Compile all summaries into a report and write it to summaries/README-summary.md via ${p.writeOutput("reportPath", "summaries/README-summary.md")}.`, - output: s.object({ - sections: s.array(s.object({ heading: s.string, summary: s.string })), - reportPath: s.string, - }), - agents: { sectionSummarizer }, -}); - -export default markdownDocSummarizer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts deleted file mode 100644 index 1d32f32..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/90-workspace-config-drift.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const parseJson = defineTool("parseJson", { - description: "Parse a JSON string and return it, or report a parse error", - parameters: s.object({ content: s.string, filename: s.string }), - handler({ content, filename }) { - try { - const parsed = JSON.parse(content); - return { ok: true, parsed }; - } catch (e) { - return { ok: false, error: String(e), filename }; - } - }, -}); - -// Agent role: detect drift in workspace config files by reading them and comparing against known defaults. -const workspaceConfigDrift = agent({ - model: "typecheck", - instructions: p`Read project config files: ${p.readOptional("tsconfig.json", "{}")} (tsconfig.json), ${p.readOptional(".eslintrc.json", "{}")} (.eslintrc.json), ${p.readOptional(".prettierrc", "{}")} (.prettierrc). Use the parseJson tool to parse each file. For each config, identify fields that deviate from sensible defaults and report them as drifted. Assign status ok if no drift, warning for minor issues, error for significant mismatches.`, - output: s.record(s.object({ - driftedFields: s.array(s.string), - status: s.enum("ok", "warning", "error"), - })), - tools: [parseJson], - maxTurns: 4, - addons: repair(), -}); - -export default workspaceConfigDrift; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts deleted file mode 100644 index 28e2897..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/91-commit-format-suggester.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agent, p, s, repair, steering } from "rig"; - -// Agent role: review recent git commits and suggest conventional-format rewrites for each one. -const commitFormatSuggester = agent({ - model: "typecheck", - instructions: p`Review recent git commits: ${p.bash("git log --oneline -20 --no-merges")}. For each commit, check whether its message follows conventional commit format (type: description). Suggest a rewritten message in conventional format. Classify each commit as one of: feat, fix, chore, docs, test, refactor, style. Write the full report to commit-report.md via ${p.writeOutput("reportWritten", "commit-report.md")}.`, - output: s.array(s.object({ - hash: s.string, - original: s.string, - suggested: s.string, - category: s.enum("feat", "fix", "chore", "docs", "test", "refactor", "style"), - })), - maxTurns: 5, - addons: [steering(), repair()], -}); - -export default commitFormatSuggester; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts deleted file mode 100644 index e9af2db..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/92-runtime-env-checker.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const checkThresholds = defineTool("checkThresholds", { - description: "Validate environment values against minimum thresholds and return a list of issues", - parameters: s.object({ - nodeVersion: s.string, - heapMB: s.number, - }), - handler({ nodeVersion, heapMB }) { - const issues: string[] = []; - const majorVersion = parseInt(nodeVersion.replace("v", "").split(".")[0], 10); - if (majorVersion < 18) issues.push(`Node.js ${nodeVersion} is below minimum v18`); - if (heapMB < 256) issues.push(`Heap ${heapMB}MB is below 256MB minimum`); - return { issues }; - }, -}); - -// Agent role: inspect the runtime environment and report overall health. -const runtimeEnvChecker = agent({ - model: "typecheck", - instructions: p`Inspect the runtime environment using: ${p.bash("node --version")}, ${p.bash("uname -a")}, and ${p.bash("node -e \"console.log(Math.round(process.memoryUsage().heapTotal/1024/1024))\"")}. Use the checkThresholds tool to validate versions and memory. Determine overall health as ok, degraded, or critical based on issues found.`, - output: s.object({ - health: s.enum("ok", "degraded", "critical"), - nodeVersion: s.string, - os: s.string, - heapMB: s.number, - issues: s.array(s.string), - }), - tools: [checkThresholds], -}); - -export default runtimeEnvChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts deleted file mode 100644 index 148a79c..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/93-hotspot-file-analyzer.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: analyze which source files are hot-spots by measuring churn and top contributors. -const hotspotFileAnalyzer = agent({ - model: "typecheck", - instructions: p`Analyze file churn in this repository. Get recently changed files using ${p.bash("git log --name-only --format='' HEAD~100..HEAD | sort | uniq -c | sort -rn | head -30")} and contributor data using ${p.bash("git shortlog -sn --no-merges HEAD~100..HEAD")}. For each hot-spot file, compute a churnScore 0–100 based on how often it changes, list topContributors, and classify riskLevel as low, medium, or high.`, - output: s.record(s.object({ - churnScore: s.number, - topContributors: s.array(s.string), - riskLevel: s.enum("low", "medium", "high"), - })), - maxTurns: 5, - addons: steering({ message: "Ensure every file entry has a numeric churnScore and at least one topContributor." }), -}); - -export default hotspotFileAnalyzer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts deleted file mode 100644 index 19239a5..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/94-ts-interface-conflict-checker.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { agent, p, s, defineTool, repair } from "rig"; - -const scanInterfaces = defineTool("scanInterfaces", { - description: "Scan a TypeScript file for exported interface names using grep", - parameters: s.object({ filePath: s.string }), - async handler({ filePath }) { - const { execSync } = await import("node:child_process"); - try { - const result = execSync( - `grep -n "^export interface\\|^interface " "${filePath}" 2>/dev/null || true`, - { encoding: "utf8" } - ); - const names = result - .split("\n") - .filter(Boolean) - .map((line) => { - const m = line.match(/interface\s+(\w+)/); - return m ? m[1] : null; - }) - .filter(Boolean) as string[]; - return { filePath, names }; - } catch { - return { filePath, names: [] }; - } - }, -}); - -// Agent role: find duplicate TypeScript interface names across all source files in the project. -const tsInterfaceConflictChecker = agent({ - model: "typecheck", - instructions: p`Find all TypeScript source files using ${p.bash("find . -name '*.ts' -not -path '*/node_modules/*' | head -80")}. Use the scanInterfaces tool on each file to collect interface names. Identify any interface name declared in more than one file. Classify each conflict as warning (same name, compatible) or error (likely clash). Set hasConflicts to true if any conflicts exist.`, - output: s.object({ - conflicts: s.array(s.object({ - interfaceName: s.string, - files: s.array(s.string), - severity: s.enum("warning", "error"), - })), - hasConflicts: s.boolean, - }), - tools: [scanInterfaces], - maxTurns: 6, - addons: repair(), -}); - -export default tsInterfaceConflictChecker; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts deleted file mode 100644 index c4f0cf1..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/95-git-worktree-mapper.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const parseWorktreePorcelain = defineTool("parseWorktreePorcelain", { - description: "Parse the output of git worktree list --porcelain into structured entries", - parameters: s.object({ output: s.string }), - handler({ output }) { - const entries: Array<{ path: string; branch?: string; state: string }> = []; - const blocks = output.trim().split("\n\n"); - for (const block of blocks) { - const lines = block.split("\n"); - const pathLine = lines.find((l) => l.startsWith("worktree ")); - const branchLine = lines.find((l) => l.startsWith("branch ")); - const isLocked = lines.some((l) => l.startsWith("locked")); - const isBare = lines.some((l) => l.startsWith("bare")); - const entry: { path: string; branch?: string; state: string } = { - path: pathLine ? pathLine.replace("worktree ", "") : "", - state: isLocked ? "locked" : isBare ? "bare" : "clean", - }; - if (branchLine) entry.branch = branchLine.replace("branch refs/heads/", ""); - if (entry.path) entries.push(entry); - } - return entries; - }, -}); - -// Agent role: list and classify all git worktrees in the current repository. -const gitWorktreeMapper = agent({ - model: "typecheck", - instructions: p`List all git worktrees using ${p.bash("git worktree list --porcelain")}. Use the parseWorktreePorcelain tool to parse the output. Determine the state of each worktree (locked, bare, clean, or dirty if there are uncommitted changes). Provide a summary with totalCount and activeCount (non-bare worktrees).`, - output: s.object({ - worktrees: s.array(s.object({ - path: s.string, - branch: s.optional(s.string), - state: s.enum("locked", "bare", "clean", "dirty"), - })), - summary: s.object({ - totalCount: s.number, - activeCount: s.number, - }), - }), - tools: [parseWorktreePorcelain], -}); - -export default gitWorktreeMapper; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts deleted file mode 100644 index b60200f..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/96-test-naming-enforcer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { agent, p, s, steering } from "rig"; - -// Agent role: audit test file naming conventions and report files that violate the standard pattern. -const testNamingEnforcer = agent({ - model: "typecheck", - instructions: p`Find all test files in this project using ${p.bash("find . \\( -name '*.test.ts' -o -name '*.spec.ts' -o -name '*.test.js' -o -name '*.spec.js' \\) -not -path '*/node_modules/*' | head -60")}. For each file, check whether it follows the convention of .test.ts or .spec.ts. Classify as correct if it matches, wrong-prefix if the name before the extension separator is unusual, wrong-suffix if it ends differently, or missing-spec if it should be a test file but lacks the marker. Suggest a corrected name where applicable. Set allConform to true only if every file is classified as correct.`, - output: s.object({ - files: s.record(s.object({ - convention: s.enum("correct", "wrong-prefix", "wrong-suffix", "missing-spec"), - suggestedName: s.optional(s.string), - })), - allConform: s.boolean, - }), - maxTurns: 5, - addons: steering({ message: "Ensure every discovered test file has an entry in files and allConform is a boolean." }), -}); - -export default testNamingEnforcer; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts deleted file mode 100644 index 9990514..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/97-pkg-dependency-graph.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { agent, p, s, defineTool } from "rig"; - -const classifyDependency = defineTool("classifyDependency", { - description: "Classify a dependency as runtime, dev, or peer based on its presence in package.json sections", - parameters: s.object({ - name: s.string, - inDependencies: s.boolean, - inDevDependencies: s.boolean, - inPeerDependencies: s.boolean, - }), - handler({ inDependencies, inDevDependencies, inPeerDependencies }) { - if (inPeerDependencies) return "peer"; - if (inDevDependencies) return "dev"; - if (inDependencies) return "runtime"; - return "dev"; - }, -}); - -// Agent role: extract and classify direct dependencies from package.json, then describe the overall tree shape. -const pkgDependencyGraph = agent({ - model: "typecheck", - instructions: p`Read the project manifest: ${p.read("package.json")}. Get the resolved dependency tree using ${p.bash("npm ls --json --depth=1 2>/dev/null || echo '{}'")}. Use the classifyDependency tool to classify each direct dependency as runtime, dev, or peer. Also list all devDependency names. Estimate the treeShape as flat (<5 deps), shallow (5–20), or deep (>20) and set depthScore to the total direct dependency count.`, - output: s.object({ - directDeps: s.array(s.object({ - name: s.string, - version: s.string, - type: s.enum("runtime", "dev", "peer"), - })), - devDeps: s.array(s.string), - treeShape: s.enum("flat", "shallow", "deep"), - depthScore: s.number, - }), - tools: [classifyDependency], -}); - -export default pkgDependencyGraph; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts deleted file mode 100644 index 53a5b07..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/98-async-tool-node-builtins.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { agent, defineTool, p, s } from "rig"; - -const getProcessInfo = defineTool("getProcessInfo", { - description: "Get running-process details for a named process using node:child_process", - parameters: s.object({ name: s.string("process name") }), - async handler({ name }) { - const { execSync } = await import("node:child_process"); - try { - const out = execSync( - `ps -eo pid,comm,rss,etime 2>/dev/null | grep "${name}" | head -5 || true`, - { encoding: "utf8" } - ); - return out.trim() || "not found"; - } catch { - return "not found"; - } - }, -}); - -// Agent role: summarize running Node.js processes and their resource usage. -const processReport = agent({ - model: "typecheck", - instructions: p`Inspect running processes with ${p.bash("ps aux | grep -E 'node|npm' | head -20")}. Use getProcessInfo for any named process you need details on.`, - output: s.object({ - processes: s.array(s.object({ - name: s.string, - pid: s.string, - status: s.enum("running", "idle", "unknown"), - })), - summary: s.string, - }), - tools: [getProcessInfo], -}); - -export default processReport; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts b/scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts deleted file mode 100644 index e2db29e..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/99-bash-each.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { agent, p, s } from "rig"; - -const ProbeResult = s.object({ - results: s.array(s.object({ url: s.url, status: s.string })), - allHealthy: s.boolean, -}); - -// Agent role: probe each endpoint and report its HTTP status code. -const endpointProbe = agent({ - name: "endpointProbe", - model: "typecheck", - input: s.object({ endpoints: s.array(s.url) }), - instructions: p`${p.bashEach("curl -s -o /dev/null -w '%{http_code}' {} --max-time 5", "endpoints")}`, - output: ProbeResult, -}); - -// Agent role: supply the endpoint list and delegate probing to endpointProbe. -const healthProbe = agent({ - model: "typecheck", - agents: { endpointProbe }, - instructions: p`Delegate to endpointProbe with endpoints ["https://example.com", "https://example.org"], then return its result unchanged.`, - output: ProbeResult, -}); - -export default healthProbe; diff --git a/scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json b/scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json deleted file mode 100644 index fa799ae..0000000 --- a/scripts/.tmp-rig-sample-typecheck-FGwCmo/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": [ - "./*.ts" - ] -} \ No newline at end of file