CHANGELOG
サイト更新履歴
COCoLaサイトの機能追加・改善・不具合修正の記録です。
2026年6月
-
2026-06-21
GitHub Actions の data 更新 workflow が大量に「Run failed」通知を発生させていた不具合を修正(push 競合の自動リトライ実装)
「run fail のメールが膨大でかなりメールボックスがいっぱいになっている」というユーザー報告に対応。真因:
update-members-data/update-dao-data/update-events-data/update-dangotsusin-data/update-schedule-data/sync-event-sourcesの各 workflow が 5 分間隔の cron で同時起動し、それぞれがdata.jsonをコミットしてmainに push する際にcannot lock ref 'refs/heads/main'エラーで競合・失敗していた。git pull --rebase origin main && git pushを 1 回だけ実行する旧仕様だったため、同時刻に 2 本以上のジョブが走ると後勝ち側が即失敗していた。対処: 6 本すべての workflow の最終ステップをfor i in 1 2 3 4 5; do git pull --rebase origin main && git push && exit 0; sleep 3; doneの 5 回リトライ方式に変更。効果: push 直後の最新3回連続でconclusion=successを確認。Gmail 受信トレイへの大量Run failed通知が解消される見込み。残課題: 5 回でも失敗するレアケースが発生した場合は、cron 間隔のずらし or 単一統合 workflow への集約を検討。 -
2026-06-18
DAO コメント件数バッジが「0件⇄3件」で揺れる不具合を修正(GAS部分レスポンス耐性化)
「P0046は、何件かチャットしていますが、0件になったり3件になったりの繰り返しです」というユーザー報告に対応。真因:
dao/index.html:5849-5853のloadCommentCounts()がcommentCounts = d.counts || {};で辞書を毎回まるごと置換し、表示ロジックがcommentCounts[pid] || 0となっていたため、dao-comment-gasのmode=countsがたまに「d.ok=trueだが部分的辞書(該当 pid を含まない)」を返したタイミングで表示が 0 に上書きされていた。GAS 内部キャッシュ反映タイミング差やリクエストレース条件で 3 件と 0 件が交互に揺れていた。対処(A案・最小フォールバック):loadCommentCounts()を「fresh辞書にhasOwnProperty(pid)で明示的に含まれているキーだけ表示更新」に変更。未掲載 pid は既存表示を維持して 0 で潰さない。commentCountsも「明示的に存在するキーだけ上書きマージ」に変更(全置換しない)。副作用なし: GAS が正しく返した瞬間に反映される点は変わらず、ユーザーが投稿/削除時の楽観的更新(local +1/-1)にも影響しない。投票数・棒グラフは別経路(data.json)なのでこの修正の影響を受けない。PWA キャッシュ:service-worker.jsCACHE_NAME をv28→v29にバンプ。残課題: GAS 側mode=counts自体の不安定さは残るので、再発頻度を見て B案(GAS 堅牢化)も検討。 -
2026-06-18
DAO 提案・投票ページ(投票中カード)の棒グラフを結果ページと統一(有効投票権重み基準・3区画積み上げ)
「提案中のものもその棒グラフで統一したい」というユーザー要望に対応。変更前:
dao/index.htmlの投票中カードは単一の.progress-bar(緑→シアンのグラデーション)をprogressPercent幅だけ伸ばす旧仕様で、結果ページ(results.html)と表示ロジックが分かれていた。変更後:renderProposal内の vote-box 描画を IIFE で書き換え、yesWeight/noWeight/eligibleWeight(既にrenderProposal冒頭で算出済み)から 協力(緑) / 非協力(赤) / 未投票(透明) の3区画積み上げを生成。CSS: 旧.progress-barを撤廃して.progress-yes/.progress-no/.progress-emptyを新設、.progress-trackを flex 化・背景#eef2f0+枠線。vote-numbers ラベル: 「投票数 / 協力率 / 協力重み / 非協力重み」→「参加率 X% / 投票数 / 協力重み / 非協力重み」に変更し、下に「有効投票権 W 重み」を小さく追記。フォールバック:eligibleWeightが未設定または参加重みより小さい場合は参加重みを母数として扱う(results.html と同仕様)。PWA キャッシュ:service-worker.jsCACHE_NAME をv27→v28にバンプ。 -
2026-06-18
DAO 結果ページの投票棒グラフを「有効投票権重み基準」に変更(参加率+協力/非協力/未投票の3区画積み上げ表示)
「棒グラフは、全体の〇%(重み付け考慮)が投票して、協力を緑、非協力を赤で表示できないか?」というユーザー要望に対応。変更前: 投票総量 (yes+no) を100%として「協力 X% / 非協力 Y%」のみ表示していたため、全体の何%が投票したか(参加率)が分からなかった(例: yes=1.3 no=0 で「100%協力」と表示され、有効投票権10のうち実は13%しか投票していない事実が見えない)。変更後:
cocola-site/dao/results.htmlのprogressBar(yesWeight, noWeight, eligibleWeight)関数を3引数化。バーは 協力(緑) / 非協力(赤) / 未投票(灰背景) の3区画積み上げでeligibleWeightを100%として描画。表示ラベルは「参加率 X%(協力 Y / 非協力 Z / 有効投票権 W)」に変更。fmtNumヘルパーで小数点1桁に整形。フォールバック:eligibleWeightが未設定または参加重みより小さい場合は参加重み (yes+no) を母数として扱う(旧表示互換)。buildCardでp.eligibleWeight(既にcollectDaoProposalPageRows_から JSON に含まれている)を渡すよう修正。CSS:.bar-wrapの背景を#eef2f0(未投票部分を明示)、.bar-emptyを追加、.bar-info bで参加率を強調。PWA キャッシュ:service-worker.jsCACHE_NAME をv26→v27にバンプ。 -
2026-06-18
DAO「期限切れ提案を再期限設定で復活」機能を追加+投票結果ページのバックエンドを cocola_topics に完全移行(
cocola_topics v206 @407)「採用と不採用の結果を提案番号と件名と投票結果(投票数など)、今後の処置案について別ページでリスト化したい。期限切れを再度期限設定して復活させることができるようにしたい」というユーザー要望に対応。GAS側 (cocola_topics):
dao-points.jsのDAO_PROPOSAL_HEADERSに処置案/処置案更新日時/期限延長履歴の3列を追加(ensureHeaders_で自動拡張)、collectDaoProposalPageRows_の戻り値にactionNote/actionUpdatedAt/extendHistoryを追加。新規関数updateDaoProposalAction_(管理者PW or 提案者本人ニックネーム照合で「処置案」列を800文字以内で更新)とextendDaoProposalDeadline_(管理者PWのみ、YYYY-MM-DD 形式の新締切バリデーション・今日以降チェック・「投票締切」更新/「ステータス」を投票中に戻す/「判定日時」クリア/「期限延長履歴」にYYYY-MM-DD HH:MM 旧→新(理由: xxx)を改行追記)を実装。コード.jsdoGet whitelist にupdateProposalAction/extendDeadlineを追加、doGetDao_から両モードを呼び出してキャッシュクリア→triggerDaoSiteUpdate_で data.json 即時更新。フロント側:cocola-site/dao/results.htmlのGAS_URLを退役済のcocola-dao-gas2(AKfycbxM2ybp...)から現用のcocola_topics(AKfycbzVs_...)へ切替。期限切れカードに「📅 期限を再設定して復活」ボタンを追加(黄色.btn--warn)、新規モーダルで<input type="date">(min=明日)/変更理由(任意)/管理者PW を入力→mode=extendDeadline呼出→成功時に旧締切・新締切・新ステータスを alert 表示しローカル状態をvotingに更新(カードはフィルタから消える)。延長履歴は破線枠.extend-historyで全カードに表示。PWA キャッシュ:service-worker.jsCACHE_NAME をv25→v26にバンプ、CORE_ASSETSに./results.htmlを追加。GAS デプロイ: cocola_topics v205 @406(処置案編集+期限再設定)→ v206 @407(whitelist 追加分)として固定IDへ redeploy 済。 -
2026-06-18
全ページにアクセスカウンタを導入(フッター中央・控えめバッジ表示 / 専用GAS
cocola-access-counter-gas v1 @1)「サイトの全ページにアクセスカウンタを付けたい」というユーザー要望に対応。専用GAS新設:
cocola-access-counter-gas(standalone)を新規作成しmode=trackエンドポイントを実装。ページごとにAccessLog(生ログ)とPageSummary(page別累計)の2シートに記録し、レスポンスでそのページの累計countを返す。初回 doGet で集計用 SS「COCoLa-AccessCounter」を自動作成・ScriptProperties.SHEET_IDに保存するgetSpreadsheet_()構造。LockServiceで同時アクセス時の二重カウント防止。フロント側: 既存cocola-site/assets/page-tracker.jsを全面改修。window.COCOLA_ACCESS_COUNTER_URL(site-config.js 経由)にfetchし、受け取ったcountをフッター中央に控えめバッジ(白半透明・茶色文字・border-radius:999pxのピル型・bottom:8px・pointer-events:none)として表示。失敗時はバッジ非表示でページ機能に影響なし(fail-safe)。配信範囲: 既存読込済10ページに加え、未読込だった14ページ(adventure/bunkazai-map/dangotsusin/dao(checkin/minutes/results)/events/lab(index/cidao-roadmap/sbt-mockup)/metaverse/organizations/schedule(index/how-to-use))に<script src=".../assets/site-config.js">+<script src=".../assets/page-tracker.js" data-page="…">を追加。除外: 管理系(admin/、gas/、staff/scan.html、member-app/html.html)、リダイレクト専用(join/index.html)の計6ページ。events/index.html の置換: 旧 cocola_topics へのmode=pageviewインライン呼び出しを削除し新カウンタに統一。site-config.js:window.COCOLA_ACCESS_COUNTER_URLを追加。 -
2026-06-17
DAO「投票結果と処置の記録」ページを新設(終了済み提案を一覧公開、処置編集は管理者または提案者本人 /
cocola-dao-gas2 v36 @92)「投票案件をリスト化して、投票結果とその後の処置(編集可能)についてわかりやすく可視化したい。対象は投票が終了したもの、期限が終了したもの。別ページにまとめてメンバーや外部のものも見えるようにしたい」というユーザー要望に対応(Phase 1)。GAS側:
cocola-dao-gas2/dao-points.jsにensureNamedColumn_('処置内容')/'処置更新日時'で DAO提案シートに2列を自動 ensure、collectDaoProposalPageRows_の戻り値にactionNote/actionUpdatedAtを追加し data.json に出力。updateDaoProposalActionFromApp_を新規実装、PW (cocola2026) または提案者本人 (ニックネーム照合)のどちらでも編集可能。更新履歴はDAO提案更新履歴シートに JSON で残す。フロント側:cocola-site/dao/results.htmlを新規作成。data.json から status がapproved/rejected/expiredの提案だけフィルタしてカード表示。フィルタタブ(すべて/承認/不採用/期限切れ)、ステータスバッジ色分け(緑/赤/グレー)、協力 vs 非協力の積み上げ棒グラフ、投票数、「📌 その後の処置」欄(未記入時は淡色)、「💬 議論を見る」リンク(./index.html#chat-{id})、「✏️ 処置を編集」モーダル(認証ラジオ「管理者PW/提案者本人」→ 認証情報入力 → 800文字以内の textarea → 保存)。動線:dao/index.html提案一覧の上にゴールド帯で「結果一覧を見る →」リンク。TOPページindex.htmlの DAO CTA に「📋 投票結果と処置」セカンダリボタン。GAS デプロイ: cocola-dao-gas2 v36 @92 として固定IDに redeploy 済。PWA キャッシュ: service-worker v24→v25 にバンプ。Phase 2 予定: 投票者属性別分析(年代/性別/地区、3人未満は「少数」表示)。 -
2026-06-17
運営管理画面に「DAO投票ゾンビ クリーンアップ」ボタンを追加(管理画面から1クリック実行 /
cocola_topics v209 @405)ゾンビ確認時に即対処できるよう、運営管理画面の DAO セクション(「誰が投票したか」「DAOメンバー一覧」の隣)に 「🧹 投票ゾンビ クリーンアップ」 カードを新設。GAS側:
cocola_topicsのホワイトリストに'runDaoVoteCleanupAll'を追加、dao-points.js doGetDao_にmode='runDaoVoteCleanupAll'エンドポイントを実装。getDaoAdminPassword_()で PW 認証し、内部でrunDaoVoteCleanupAll(STEP1 ts dedupe → STEP2 voter dedupe → STEP3 壊れた行除去)を順次実行。フロント側:admin/index.htmlに確認ダイアログ(実行内容・バックアップ取得・所要時間を明示)→ 実行中表示「実行中…(最大2分)」→ 結果表示(各STEPの削除件数・残行数・バックアップシート名を整形表示)。エラー時は赤色で詳細メッセージ。運用:?admin=1表示で重複行を発見したらワンクリックで実行。各STEP のバックアップシート(DAO投票_backup_*)に自動退避するので元に戻せる。 -
2026-06-17
投票ゾンビ復活の真の根治(cocola-dao-gas2 側の normalize 系2関数も upsert化 /
cocola-dao-gas2 v35 @91)再発の真因: 2026-06-02 の v201(cocola_topics)で投票ゾンビ根治と思っていたが、実は
cocola-dao-gas2/dao-points.jsのnormalizeDaoVoteResponses_(L2212) とnormalizeLatestDaoVoteResponse_(L2250) が**未対策のまま直接 setValues/appendRow で書き込み続けていた**。両プロジェクトが同じシート (1Xma1V92uN...) に書き込む構造のため、cocola_topics 側だけ upsert化しても cocola-dao-gas2 側の経路で重複が再挿入されていた。今回再発時の状況:DAO投票シートが 370行に膨張、P0021「ゆう/反対/2026-04-19 18:56:29」が7行、P0025「ゆう/賛成」7行、P1009「ゆみ/賛成/2026-04-29 16:37:25」7行 など、前回 v200 で削除したのと**完全同一**のデータが復活。対処: cocola-dao-gas2 にもupsertDaoVoteByVoterFromForm_ヘルパー(10列構成版)を追加し、上記 normalize 系2関数を append→upsert に置換。これで両プロジェクトのどの経路を経ても (提案ID × 投票者) ユニーク性が**構造的に保証**される。クリーンアップ: cocola_topics にrunDaoVoteCleanupAll一括ラッパー新設(v208 @404)→ STEP1: ts キー dedupe で 370→125(245行削除)/STEP2: voter キー dedupe で 125→121(4行)/STEP3: 壊れた行除去で 121→94行(27行)=真のユニーク投票数(94)と完全一致。バックアップは各STEP のバックアップシート(DAO投票_backup_*)に自動退避済。GAS デプロイ: cocola-dao-gas2 v35 @91 + cocola_topics v208 @404 として固定IDへ redeploy 済。 -
2026-06-16
DAO「みんなで話し合う」コメントに編集・削除機能を追加(本人のみ・⋯メニュー /
dao-comment-gas v3 @3)「コメント内容を修正したい、もしくは削除したい」要望に対応。GAS側:
dao-comment-gas/Code.gsのdoPostdispatcher にaction='delete'/action='edit'を追加。commentId該当行を取得し alias 一致を検証→deleteRowor 本文列(4列目)setValue。**本人のコメントのみ削除/編集可能**(他人 alias なら本人のコメントのみ削除/編集できますエラー返却)。フロント側:dao/index.htmlのbuildBubbleで自分のコメント (isMe && !isPending && c.id) に⋯ボタン追加。クリックでchat-actions-popup(✏️編集/🗑️削除)表示。編集はpromptで新テキスト入力→ 楽観的UI更新→ POST失敗時は元に戻す。削除はconfirm→楽観的に opacity 0.4 で淡色化→ 成功でrow.remove()+ 件数カウンタ -1。GAS側 API 認証+フロント側で他人コメントには UI 自体表示しない二重防御。デプロイ: dao-comment-gas v3 @3(固定IDAKfycbzI6vkv7y...)/ cocola-site dao/index.html+service-worker.js v23→v24(PWAキャッシュバンプ)。 -
2026-06-14
メタバース:文化財の「精霊」50体カードと市公式の詳細リンクを追加
メタバース印西で文化財に出会うと、その文化財に宿る「精霊」キャラクター(全50体・完全オリジナル)が カード画像で出現するようにした。出現画面に「実物を詳しく見る(市公式)」ボタンを追加し、 印西市公式サイトの各文化財の個別ページへ直接移動できる。精霊画像は metaverse/spirits/ に WebP で配置。 データは metaverse/bunkazai.json に detailUrl(市公式URL)・spiritName・cardImage を追加。
-
2026-06-11
DAO:提案者本人が自分の提案を編集できるようになりました
DAOページの提案カードに「編集」ボタンを追加した。投票中の提案に限り、提案者本人がログインした状態で 提案タイトル・区分・カテゴリ・理由・詳細・要調整事項・企画提案書URL・投票締切日を上書き修正できる。 本人確認は提案者名の照合で行い、本人以外や投票終了後の提案は編集できない。 修正の履歴はスプレッドシートの「DAO提案更新履歴」シートに更新前後の内容が自動保存される。 対応GAS: cocola-dao-gas2 v32(@89)/cocola_topics v207(@403)に mode=updateProposal を追加。
-
2026-06-12
「いんざい冒険図鑑リアル」公開 — 実際に印西の街を歩いて精霊をあつめるGPS版
メタバース版に続き、実際に印西市内を歩いて文化財50か所をめぐるGPS版「いんざい冒険図鑑リアル」を公開した。 地図上に現在地が表示され、文化財の100m以内まで歩いて行くと精霊が出現。タップでゲットして図鑑を完成させよう。 精霊・レア度はメタバース版と同じ世界観で、50体集めると合言葉が表示される。 スマートフォンのホーム画面に追加できるアプリ形式(PWA)で、インストール不要・無料で遊べる。 はじめる前に交通安全・私有地に立ち入らない等の「やくそく」への同意を必須とし、 位置情報は端末内だけで使いサーバーには送信しない設計とした。トップページに入口リンクを追加した。
-
2026-06-11
「いんざい冒険図鑑」誕生 — 文化財ラリーがキャラ収集ゲームに進化
メタバース印西の文化財パズルラリーが「いんざい冒険図鑑」に進化した。 市内50か所の文化財には6系統の精霊(やしろ・ほとけ・もり・いせき・まつり・たから)がかくれていて、 80m以内まで近づくと精霊が出現。「ゲットする!」をタップすると図鑑に登録され、同時にパズルのピースも開く。 レア度は指定区分に対応(★市指定・★★県指定・★★★国指定)で、★★★の精霊は図鑑で金色に輝く。 これまでの獲得記録はそのまま引き継がれる。図鑑から各精霊のすみか(文化財)へ飛ぶこともできる。
-
2026-06-11
メタバース印西:読み込み中表示を追加、パズルの絵をリニューアル
テレポートや歩行モードの直後に街並みが表示されるまで時間がかかり「何も見えない」ように感じる問題への対策として、 画面下に「🌍 街並みを読み込み中…」の表示を追加した。遊び方ガイドにも読み込み待ちと郊外で映像が粗くなる場合の注意書きを追記した。 また、文化財パズルラリーで完成する絵をリニューアルした。なにが現れるかは、50ピース集めてからのお楽しみ。 あわせて全50か所の文化財の座標を国土地理院とOpenStreetMapの2つの情報源で照合し、全件が正確であることを確認した。
-
2026-06-11
メタバース印西のPR動画を制作(撮影用カメラモードを追加)
COCoLaの活動PRのため、メタバース印西の告知動画(縦型・約28秒)を制作した。 宇宙から印西市へのズームイン、千葉ニュータウン中央駅周辺の3D街並み、 文化財パズルラリーの紹介、COCoLaロゴのエンド画面で構成。 撮影のため、ページにカメラ自動運転の撮影用モードを追加した(通常の利用には影響しない)。
-
2026-06-11
メタバース印西に「遊び方ガイド」を追加
メタバース印西に遊び方の説明を掲載した。初めて訪れたときに操作方法(パソコンのキーボード操作・ スマートフォンのスティック操作)、歩行モードと飛行モードの違い、文化財パズルラリーの遊び方を まとめたガイドが自動で表示される。2回目以降は自動表示されず、画面左上の「❓遊び方」ボタンから いつでも見返すことができる。
-
2026-06-11
メタバース印西を「印西市文化財50か所パズルラリー」に拡張
スタンプラリーを大幅拡張し、印西市の指定・登録文化財50か所(国指定6・県指定17・市指定26・国登録1。 出典:印西市内の文化財一覧)を巡る「文化財パズルラリー」に刷新した。 文化財に80m以内まで近づくとパズルのピースが1枚ずつ開き、50枚すべて集めると 印西の文化財風景を描いた1枚の絵(吉高の大桜・観音堂・獅子舞・観覧車・利根川の帆掛け舟)が完成する。 パズル帳には国指定・県指定・市指定の絞り込みと、各文化財の近くへ移動できる「▶行く」ボタンを備えた。 看板は指定区分ごとに色分けし(国指定=赤・県指定=紫・市指定=青・国登録=橙)、 クリックすると名称・指定区分・所在地が表示される。文化財の座標は国土地理院の住所検索APIで取得した。
-
2026-06-10
メタバース印西に「スタンプラリー」機能を追加
メタバース印西の中を歩いて6つのスポット(千葉ニュータウン中央駅・イオンモール千葉ニュータウン・ 印西牧の原駅・BIG HOPガーデンモール印西・印西市役所・木下駅)を巡るスタンプラリー機能を追加した。 各スポットに50m以内まで歩いて近づくとスタンプが押され、画面左上の「スタンプ帳」で獲得状況を確認できる。 上空を飛んで通過しただけではスタンプは押されない仕組みで、6つすべて集めるとコンプリート画面と合言葉が表示される。 記録は端末のブラウザに保存されるため、続きからいつでも再開できる。今後のCOCoLaイベントでの活用を想定している。
-
2026-06-10
「COCoLaメタバース印西」を新設 — 印西市を3Dでリアルに再現
印西市の街並みを Google Photorealistic 3D Tiles(航空写真ベースの写真品質3D都市データ)で リアルに再現したメタバースワールド「COCoLaメタバース印西」を公開した。 千葉ニュータウン中央駅・イオンモール千葉ニュータウン・印西牧の原駅・BIG HOPガーデンモール印西・ 印西市役所・木下駅の6スポットに看板を設置し、ワンタップで各スポットへ移動できる。 地上目線で街を歩ける「歩行モード」と上空から眺める「飛行モード」を切り替え可能で、 パソコンは WASD キー+ドラッグ、スマートフォンは仮想ジョイスティックで操作できる。 トップページのナビゲーションに「🌏 メタバース印西」の入口を追加した。
-
2026-06-09
DAOメンバーの重複(ゾンビ)行が生まれる根本原因を修正
先日の「ゆうさんの貢献度が1ptに化ける」不具合は、敬称付きの名前(「ゆうさん」)でポイント付与が発生した際に、 既存メンバー「ゆう」を別人と誤認して新しい重複行を作ってしまうのが原因だった。 ポイント付与処理のメンバー照合を、入会登録側と同じ「敬称(さん・ちゃん等)を取り除いて突き合わせる」方式に統一し、 敬称付きの名前で活動が記録されても既存メンバーに正しく合算されるよう修正した(topics GAS @402)。 これで重複行の発生経路を根本から断った。公開メンバー一覧28名で敬称ゆれの重複ゼロを確認済み。
-
2026-06-09
DAO新規提案の通知メールが届かない不具合を修正
新しいDAO提案が投稿された際に運営へ通知メールが送られない不具合を修正した。 提案フォーム送信時の通知用トリガーが未登録だったのが原因で、提案自体はサイトに反映されるが 通知だけが飛ばない状態だった。トリガーを再登録し、テスト送信で受信を確認済み。 今後は新規提案の投稿時に運営へ通知が届く。
-
2026-06-09
DAO投票データのゾンビ(重複・空行230件)を一掃
新設の投票者一覧画面で重複表示が発覚。生の投票シート319行のうち、空の壊れた行135件と (提案×投票者)の重複95件を、バックアップ退避のうえ物理削除し、89行(真のユニーク投票数)に正常化した。 投票結果の数値(賛成率・票数)は元々重複を最新1件に集約して集計しているため変化なし。 現在の取り込み処理(upsert方式)は健全で重複の増殖は停止済み。今回の230件は過去の再処理事故の蓄積分。 クリーンアップ関数を topics GAS にエンドポイント露出(v207)。
-
2026-06-09
運営管理画面に「投票者一覧(実名)」を統合・旧DAO-GAS依存を解消
これまで「誰が投票したか(実名一覧)」は旧 cocola-dao-gas2(GitHub Actions非接続の旧系統)の管理ページを別タブで開く方式だった。 実名投票者APIを現用の cocola_topics GAS に移管(v206 @400、mode=adminVoters)し、 運営管理画面(admin/index.html)内にインライン表示するよう統合。別タブを開かず、絞り込み検索付きで投票者・投票内容・日時を一覧できる。 旧DAO-GASへの依存リンクを削除し、投票・集計・管理がすべて cocola_topics 1プロジェクトに集約された。
-
2026-06-09
初投票でもDAOメンバーになれるよう改善(投票権の鶏卵問題を解消)
これまでは、会員登録だけの「幽霊メンバー」が投票しても重み0で集計外となり、 投票参加ポイントも付かないためいつまでもDAOメンバーになれない仕様だった。 名寄せ(本人特定)に成功した投票者は、重み0でも投票参加ポイントを付与してDAOメンバー登録・活動日更新するよう変更。 これにより初投票でアクティブ化し、次回集計から投票の重みが反映される。休眠メンバーも投票で復活する。 投票処理3系統(フォーム送信時・バッチ集計・高速集計)すべてのゲートを統一修正(cocola_topics GAS v205 @399)。
-
2026-06-09
PWAプッシュ通知の対象を大幅拡充(投票・ステータス・イベント・予定・だんご通信・得点変動)
「何か動きがあれば全員が認知できる」方針に沿い、バックグラウンド通知の検知対象を拡張。 ①DAO提案への投票(voteCount増加)②提案ステータス変化(可決/期限切れ) ③イベント新規追加(events/data.json)④予定新規登録(schedule/data.json) ⑤だんご通信の新着(dangotsusin/data.json)⑥メンバー得点変動(totalPoints増加)を新たに通知。 push-notify.yml の発火パスに3つの data.json を追加し、scripts/send-push.js に差分検知ロジックを実装。
-
2026-06-09
チャット参加者への新着通知機能追加
提案ディスカッションにコメントしたメンバーを「参加者」として記録し、30秒ごとに新着チェック。 タブが非アクティブ状態でも ServiceWorker 経由でシステム通知(ブラウザプッシュ)を表示。 参加中の提案IDをlocalStorageに保存し、ページを開き直しても通知が継続される。 コメントGAS(dao-comment-gas)に参加者シートと newSince モードを追加(v2 deploy済)。
-
2026-06-09
DAO提案ディスカッションをLINE風チャットUIに刷新
提案カードのコメント欄を掲示板スタイルからLINE風チャットバブルUIに全面リニューアル。 自分の発言は右側(緑バブル)、他者は左側(白バブル+丸アイコン)で表示。 送信ボタン押下と同時にバブルを即時表示する楽観的UI更新を実装し、GASのコールドスタート待ちを体感ゼロに。 ダブルタップ・長押しでリアクション(❤️👍😄🎉🤔)を選べるポップアップも追加。
-
2026-06-08
メンバー紹介: GAS直接fetch優先に変更(団体紹介との同期ずれを解消)
メンバー紹介ページのデータ取得を「静的JSON優先」から「GASエンドポイント直接fetch優先・静的JSONをフォールバック」に変更。 団体紹介ページと同じGASソースを参照するため、スプレッドシート編集が両ページに即時反映されるようになった。
-
2026-06-08
メンバー紹介ページに団体紹介ページへのリンクを追加
メンバー紹介ページのヘッダーナビに「団体紹介へ」リンクを追加。
cocola-gas/html.htmlを編集後、build_member_app.pyでmember-app/html.htmlを再生成した。 -
2026-06-07
/join パスに参加登録リダイレクトページを追加(404修正)
Threads投稿に貼られた参加登録URL(
/cocola-site/join)が404になっていた問題を修正。join/index.htmlを新設し、/#joinへ自動転送するリダイレクトページを追加した。 -
2026-06-07
ゆうの所属団体に「1ccプロジェクト」を追加・団体URLの列ズレを修正
ゆうの所属団体3つ目として「1ccプロジェクト」を会員名簿に追記し、メンバー紹介カードに3団体(革工芸クラブ/CBI/1ccプロジェクト)が並ぶようにした。 当初カードに反映されなかったのはブラウザキャッシュが原因で、公開 data.json・描画ロジックともに正常だった(ハードリロードで解消)。 あわせて、手動追記時に1ccのFacebook URLがCBIのURL欄へ入っていた列ズレを修正し、 URLを1ccプロジェクトのバナー側へ正しく紐付けた。
update-members-data.yml手動トリガーで公開反映を確認済み。 -
2026-06-07
ゆうの貢献度が1ptに化けるバグを修正(敬称衝突の重複DAO行を削除+累計優先ロジック化)
メンバー紹介で「ゆう」の貢献度が本来の431ptではなく1ptと表示されていた問題を修正。 原因は DAOメンバーシートに
M0027「ゆうさん」(1pt)の重複ゾンビ行が今日追加され、normalizeDaoNameKey_が敬称「さん」を除去するため本物のM0001「ゆう」(431pt)と 同一キーに衝突、getDaoPointMap_の後勝ち構築で少ポイント側に上書きされていたこと。 ゾンビ行を物理削除し、getDaoPointMap_を「キー衝突時は累計が大きい方を採用」に変更して再発を防止した。 GAS @103 へ redeploy 後、update-members-data.ymlを手動トリガーして公開 data.json に 431/427 を反映済み。 -
2026-06-07
検索欄の過去値残りバグを全ページ水平展開で根治+デプロイ検証スクリプト追加
Chromeのフォーム値復元が原因で検索欄に過去の入力(例「Creema」)が残るバグを、
readonly+onfocus="this.removeAttribute('readonly')"トリックで根治。 member-app に加え dao・events・organizations の全検索欄に水平展開(dao は PWA のため service-worker を v22 にバンプ)。 再発防止として本番URLを直接検証するscripts/verify_deploy.ps1を新設し、 「デプロイ未反映」と「ブラウザキャッシュ」を一発で切り分けられるようにした。 -
2026-06-07
団体登録: つるちゃんをここのわカフェ所属に追加・登録フォームの団体欄順を整備
つるちゃんの所属団体に「ここのわカフェ」を追加(ここのわカフェは計2名に)。 また登録フォームの「所属団体3」欄を団体2の直後へ移動し、団体1〜3が連続して表示されるよう整備した。
-
2026-06-07
メンバー検索欄のブラウザオートコンプリートを完全無効化(再修正)
前回の
autocomplete="off"では Chrome/Edge が無視して「Creema」等の過去入力値が自動補完されるバグが継続。autocomplete="new-password"に変更することで完全抑制。(cocola-gas html.html→build_member_app.pyで同期) -
2026-06-07
メンバー検索欄のブラウザオートコンプリートを無効化
メンバー一覧ページの検索欄に過去の入力値(例:「Creema」)がブラウザ補完で自動入力される問題を修正。
input[id=search]にautocomplete="off"を追加(cocola-gas html.html)。 -
2026-06-07
新メンバー登録検証 #10 改善・dao/data.json手動更新
おいちゃんさん登録時の自動検証レポートで #6(dao/data.json未反映)・#10(Googleフォーム通知0件)が NG。 #6 は
gh workflow run update-dao-data.ymlで手動トリガーし解消。 #10 は検索クエリのnewer_than:1h→newer_than:6hに拡大し、フォーム関連件名フィルタを追加。 未着の場合も ❌ではなく ⚠️詳細付きで報告する形に改善(cocola-gas v97 @97/@98)。 -
2026-06-07
団体登録リスト: 所属団体3以上に対応・CBIメンバーを追加
所属団体を「ヘッダー名で動的特定」する方式に改修し、団体3以降の登録に対応(
cocola-gas @96)。getMembersが全所属団体をgroups配列として出力し、メンバー一覧・団体登録リストの両ページが 団体数に依らず表示できるようになった。登録フォームにも「所属団体3」欄を追加。 あわせて らいさん・しょう・Yakkkooo を CBI(Community Bank Inzai)所属に追加(CBI登録は計4名)、 表記ゆれ(1ccプロジェクト・らんか)を正式名称に統一した。 列番号固定をやめたことで、今後フォーム項目が増えても列ズレ事故が起きない設計になっている。 -
2026-06-07
団体名を正式名称に修正:「女性防災の会」→「防災女性の会」
所属団体名の語順誤りを正式名称に修正(本人=会長の自己紹介と公式 Instagram のプロフィール名で確認)。 会員名簿の元データを修正し、団体紹介ページでも正規化マップで正式名称に統一した。
-
2026-06-07
団体紹介ページへの導線を追加(トップナビ・APPS/LINKS)
新設した団体紹介ページ(
organizations/)がトップページからたどれなかったため、 トップのナビゲーション「メンバー紹介」の隣と、APPS/LINKS のアプリ一覧にリンクを追加した。 -
2026-06-07
団体紹介: カテゴリーを支援センター冊子の9活動分野に統一し全団体を分類
カテゴリーフィルターを印西市市民活動支援センター冊子『団体紹介』の9活動分野 (まちづくり/奉仕活動/生きがいづくり/平和・人権/健康・福祉/自然・環境/子育て支援/歴史・文化・芸術/災害救援・地域安全)に統一。 メンバー所属の全16団体を冊子・自己紹介に基づき分類し「未分類」を解消。 あわせて表記ゆれ(
1CC/1cc・らんか系)を正規化マップで統合表示するようにした。 -
2026-06-07
団体登録リストページを新設(
organizations/index.html)COCoLaメンバーの所属団体を自動集約して一覧表示する新ページを追加。 印西市市民活動支援センターの22カテゴリーによるフィルタリング、 団体ごとの登録メンバー表示、キーワード検索に対応。 団体のカテゴリー・説明文は
data/organizations-meta.jsonで管理。 -
2026-06-07
メンバー紹介: 役職欄に地区名(「千葉ニュータウン」)が誤表示される不具合を修正(
cocola-gas @92)CiDAO 実証で入会フォームに「お住まいの地区」列を追加した際に列番号がずれ、 役職欄(本来「代表」「副代表」等)に地区名が表示されていた問題を修正。
getMembersの役職取得を列番号固定(row[24])から ヘッダー名による動的特定に変更し、今後フォーム項目が増えても列ズレで混入しないようにした。 -
2026-06-07
今週のCOCoLa: 情報更新メンバーが新規入会にも二重表示される不具合を修正(
cocola-gas @91)敬称付き(例「ゆうさん」)で情報更新フォームを提出すると、入会登録名(「ゆう」)と一致せず 「新規入会」バーと「情報更新」バーの両方に表示され、さらに「ゆうさんさん」と敬称が二重になる問題を修正。
recentUpdatesの表示名を入会登録の正規ニックネームに統一する処理を GAS 側に追加した。 -
2026-06-07
メンバーカレンダー: 参加者ピッカーの件数上限を撤廃
参加者・企画者選択ドロップダウンに30件上限があり、52名中22名が常に非表示になっていた問題を修正。
.slice(0, 30)を削除して全件表示に変更。ドロップダウン高さも 220px → 300px に拡大。 -
2026-06-04
だんご通信: 手動更新ボタンを追加
dangotsusin/index.htmlに「最新に更新」ボタンを追加。 クリック時に GAS エンドポイント(mode=dangotsusin)を直接呼び出してリストを再描画。 月次更新を待たずに最新メールを即時反映できるようになった。 -
2026-06-04
Threads自動投稿: 一時エラー時リトライ追加・AI生成URLを後処理で除去(
sns-gas @27)(1)
PostThreads.gs:threads_publishでis_transient: trueのサーバー側一時エラーが発生した場合、 exponential backoff(5s→10s→20s)で最大3回リトライするよう修正。再試行で投稿成功するケースに対応。 (2)GeneratePost.gs: Gemini が誤生成したcocola.jp(別組織のURL)を後処理で自動除去。 プロンプトに「本文中にURLを一切含めない」制約を追記。 -
2026-06-03
ヘルスチェック閾値を30分→180分(3時間)に緩和
GitHub Actions の scheduled workflow はGitHub側の仕様によりcron通りに発火しない(混雑時に遅延・スキップ)。DAOページはdata.json遅延時にGASへ直接フォールバックするため実害なし。誤アラートを抑制するため
health-check.ymlの鮮度閾値(FRESH_MS/RUNS_MAX_MIN)を30分から180分に変更。 -
2026-06-03
Threads自動投稿 500字超過エラー対応(
sns-gas @26)2026-06-02 22:33Z 「食をつくる」自動投稿で
Param text must be at most 500 characters long.エラーが発生。原因:runRotatedAutoPostの既存ドラフト経路で、過去に_trimToThreadsLimit未適用で保存された draft をpostToThreadsがそのまま送信していた。対処:PostThreads.gsのpostToThreads冒頭に最終防衛線を追加。500字超過時は_trimToThreadsLimitを必ず通し、警告ログを残す。これで承認後編集経路・古い下書き経路・別経由のすり抜けにも対応。GAS デプロイ: sns-gas @26 として固定IDAKfycbzoBs-QM0J4azPWNOqp6uxxlFSIsHe2r-ecyByq1qkZNcifR22tKiLMEog0SRmTvZ1LLQに redeploy 済。 -
2026-06-02
メール通知オプトイン基盤を運営手動運用に対応(U+3007「〇」認識/email集約による重複排除/簡易マーカー対応 /
cocola-gas v53-v56 @85-@88)v52 で実装した「希望者のみメール配信」基盤を、運営者がスプレッドシートで直接希望者を指定できる運用に対応。(1) 簡易マーカー対応 (v53):
isEmailOptInValue_ヘルパー新設。AB列に「〇」「希望」「TRUE」「✓」「はい」など短い表記でも希望扱い。isEmailOptOutValue_で「×」「拒否」など明示オプトアウトも区別。フォーム経由の長文ラベルもそのまま動作。(2) email集約 (v54): 入会後に「情報の修正・更新」で複数行ができたメンバーへの誤送信を防ぐため、email キーで「最新行(行番号最大)」を採用するロジックをgetOptedInEmailRecipients_とinspectEmailOptInStatusに実装。複数行どこに〇を入れても1通のみ送信。(3) 診断関数 (v55):inspectEmailOptInDetails新設。AB列に値がある行を全件ダンプし、文字コード(U+????)・isOptIn・isLatest・isWithdrawn を出力。「〇を入れたのに反映されない」場面の真因切り分けに使う。(4) U+3007 認識 (v56): 上記診断で「日本語IME『まる』第一候補の〇(U+3007 IDEOGRAPHIC NUMBER ZERO) が accepted 配列に無かった」ことが判明。○(U+25CB)・◯(U+25EF)・〇(U+3007) +半角/全角の O 変種を accepted に追加。動作確認: 全67行→ユニーク54名→オプトイン4名→未回答50名 と期待通り集約。GAS デプロイ: cocola-gas v56 @88 として固定IDAKfycbyRVO7fLJx6...に redeploy 済。運用ルール確定: 運営は希望者の最新行(最下行)の AB列に「〇」を入力するだけでOK。 -
2026-06-02
メンバー登録フォームに「COCoLaからのメール通知」オプトイン項目を追加(過去事故再発防止のための一斉メール配信基盤 /
cocola-gas v52 @84)背景: 過去にメンバー全員へ文字化けメールが大量送付され苦情が発生した事故あり(コードは既に削除済・git管理なし)。今後の一斉メール配信は**希望者のみ**に送る方針(オプトイン制)をユーザー指示で採用。実装: メンバー登録 Google Form に「COCoLaからのメール通知」チェックボックス項目を追加(`setupEmailOptInChoice` で自動追加)、シート上では
AB列(=28列目)として記録される。堅牢化: 列番号ハードコードでなくヘッダー名で動的に列特定するgetColumnByHeader_ヘルパーを実装。Form項目が将来追加されて列がシフトしても自動追従。ヘッダー未発見時はフェイルセーフで送信先0件返却=暴発しない設計。新規関数:setupEmailOptInChoice(Form項目追加)/getOptedInEmailRecipients_()(将来一斉配信機能で必ず経由するヘルパー)/inspectEmailOptInStatus()(診断)/getColumnByHeader_+columnIndexToLetter_(汎用)。現状: 全67行(退会1/現役66)、現役は全員「未回答」=送信先0件で構造的に全員配信不可能。GAS デプロイ: cocola-gas v52 @84 として固定IDAKfycbyRVO7fLJx6...に redeploy 済。残課題: 既存66名へのオプトイン確認手段(一斉メール禁止なので、LINE告知 or 個別連絡 or オフライン依頼)の方針確定。 -
2026-06-02
DAO投票シートの「空送信」壊れた行28件を物理削除(114→86行 = 真のユニーク投票数に正規化 /
cocola_topics v202 @394)dedupe完了後の残114行のうち、提案ID・投票者・投票内容・タイトルが全て空の「フォーム空送信由来」の壊れた行が28件残存していた。memo列に
フォーム回答: DAO投票フォーム回答:29:Sun Apr 19 2026 ...:::の形式で記録されており、末尾:::が proposalId/voter/vote 全て空の連結痕跡。これらは集計に影響しない(id 空のためnormalizeDaoVote_/collectDaoVotes_も無視)が、管理画面の見通しを悪化させていた。対処:cocola_topics dao-points.jsに診断関数inspectDaoVoteBrokenRows_(行番号・各列値・memo・reason をログ出力)と削除関数removeDaoVoteBrokenRows_/DryRun/Live(提案ID or 投票者が空の行を対象に、バックアップ退避→物理削除)を新規実装。DryRun で 28件全てがboth empty(提案ID/投票者の両方空)と確認後、Live実行で物理削除。バックアップはDAO投票_backup_broken_2026-06-02に退避済。結果: 全データ行数 114→86行。86 = (proposal×voter) ユニーク数と完全一致=真のユニーク投票数。GAS デプロイ: cocola_topics v202 @394 として固定IDAKfycbzVs_W57...に redeploy 済。 -
2026-06-02
DAO投票の「投票ゾンビ復活」を構造的に根絶(フォーム取り込み3関数を append→upsert 化、(提案ID, 投票者) ユニーク化を保証 /
cocola_topics v201 @393)真因:
normalizeDaoVoteResponses_系の idempotency キーはsheetName:row:timestamp:proposalId:voter:voteで**フォーム回答シートの行番号 (row) を含む**ため、DAO投票シートから手動削除後に ScriptProperties が消失すると「未処理」と判定されて全件再挿入される構造的脆弱性があった。提案ゾンビ復活(v21-v30, v188-v198)と同じパターンの**投票版**で、これが P0021 691行(同一秒2026-04-19 18:56:29)の真の発生源。対処: cocola-dao-gas2recordDirectVote_の「同一(id, voter)なら更新で1行に保つ」設計を cocola_topics 側にも導入。共通ヘルパーupsertDaoVoteByVoterFromForm_(voteSheet, id, title, voter, vote, comment, memoText, timestamp)を新規実装し、フォーム取り込み3関数(normalizeDaoVoteResponses_/normalizeRecentDaoVoteResponses_/normalizeLatestDaoVoteResponse_)の append 直前に (提案ID, 投票者) チェックを追加。既存(id, voter)行があれば最新値で update、無ければ append。これでフォーム経由・WebApp経由のどちらでも (提案ID×投票者) ユニーク性が保証され、トリガー多重実行・ScriptProperties消失・行番号ズレのいずれが起きても重複再挿入されない。GAS デプロイ: cocola_topics v201 @393 として固定IDAKfycbzVs_W57...に redeploy 済。残課題: voter/proposal 列が空の壊れた行28件は別途調査。 -
2026-06-02
DAO投票シートの(提案ID×投票者)キー重複を一掃(既存 ts キー dedupe で 811→120、新規 voter キー dedupe で 120→114 /
cocola_topics v200 @392)「誰が投票したか」管理ページ (
?admin=1) で P0021「ゆう/反対/2026-04-19 18:56:29」が大量に並んでいるとのユーザー報告を受け、DAO投票シートの重複を2段階で解消。(1) ts一致重複削除: 既存dedupeDaoVoteSheetByKeyLive(キー: proposal×voter×ts)を実行し、同一秒に多重書込された 691行を物理削除(811→120行、約85%が重複)。バックアップはDAO投票_backup_2026-05-16に自動退避。(2) ts違い重複削除(新規実装): 同じ (proposal, voter) で異なる ts の重複(P0025「ゆう/賛成」3件など)は ts キーでは削除できないため、cocola_topics dao-points.jsにdedupeDaoVoteByVoter_/DryRun/Liveを新規追加。キーproposal+voterでグループ化し、最新 ts の1行だけ残して残りを物理削除。recordDirectVote_の「同一(id, voter)なら更新で1行に保つ」設計(dao-points.js L446 相当)と整合させる。6グループ計6行を削除(120→114行)、バックアップはDAO投票_backup_byVoter_2026-06-02。残った課題: voter または proposal 列が空の壊れた行が約28件残存(114 − 86ユニーク − 重複追加分0 = 28)。これは別途調査・対処予定。GAS デプロイ: cocola_topics v200 @392 として固定IDAKfycbzVs_W57...に redeploy 済。フォーム取り込み経路(candidateVoteResponseSheets3シート)からの多重実行が原因と推測、要後追い調査。 -
2026-06-02
運営管理画面に「DAO(提案・投票管理)」セクションを新設し、「誰が投票したか(実名一覧)」リンクと「DAOメンバー一覧」リンクを追加
「誰が投票したかわかるページを作ったはずだがどこにあるかわからない」というユーザー指摘を起点に、運営管理画面 (
admin/index.html) の「キャンペーン管理」と「アクセス解析・予算監視」の間に新セクション「DAO(提案・投票管理)」を追加。(1) 誰が投票したか(実名一覧):cocola-dao-gas2の WebApp に?admin=1を付けて開く管理者ビューへのリンクカードを設置(実装はdao-points.js:233template.isDaoAdmin = Boolean(e.parameter.admin === '1'))。公開ページではハッシュ化されている投票者名を、運営者は実名・投票内容・日時の一覧で確認できる。(2) DAOメンバー一覧: 投票権の可視化(アクティブ/サポーター/休眠)が見られるdao/index.html#membersセクションへのリンクカードを設置(v198 @362で公開済の機能)。これで未投票者の把握や休眠状態のチェックが運営管理画面から1クリックで到達可能になった。URL はhttps://script.google.com/macros/s/AKfycbxM2yb.../exec?admin=1(cocola-dao-gas2 固定デプロイ)。 -
2026-06-01
DAO提案の「区分」分類問題の真因を特定・修正(GASが空欄を強制的に gyousei 出力していた)
「P0199 等を団体方針タブに表示」が長時間反映されなかった真因が判明。
cocola-dao-gas2のgetDaoProposalPageData_()内で スプレッドシート「区分」セルが空欄の場合、GAS が自動的にproposalType='gyousei'を埋めて返していたため、フロントのFALLBACK_DANTAI_IDSマップは値が既にあると判定されて発動せず、5件全てが「行政につなぐ」扱いになっていた。dao-points.js:759-761を修正し、区分セルが「団体方針」「行政につなぐ」のいずれでもない(空欄含む)場合はproposalType=''(空文字)を返すようにした。これにより GAS が値を強制設定せず、フロント側の FALLBACK 経路に処理が渡るようになる。cocola-dao-gas2は 固定IDAKfycbxM2yb...へ @85 redeploy 済。 -
2026-06-01
DAO PWA:SW更新自体がブラウザHTTPキャッシュに張り付く問題への徹底対策(updateViaCache:none+activate時の旧キャッシュ全削除+既存タブ自動再ナビゲート)
「Ctrl+Shift+R しても時間が経つと元に戻る」現象の根本原因は、Chrome が
service-worker.js自体を GitHub Pages のCache-Control: max-age=600に従って HTTP キャッシュしてしまい、新しい SW がブラウザに届かないこと。SW を v17 にして fetch ロジックを改修しても、ユーザーの Chrome が古い SW(v13〜v16)をそのまま使い続けるため挙動が変わらなかった。今回の対策は3段構え:①navigator.serviceWorker.register()に{ updateViaCache: 'none' }を指定して SW スクリプト取得時の HTTP キャッシュを bypass、② ページ可視化(visibilitychange)のたびにregistration.update()を呼んで SW 更新確認を強制、③ SW の activate イベントで cocola-dao-v?? の旧キャッシュ全削除+既存タブをclient.navigate()で自動再ナビゲート。これにより新SWがインストール完了した瞬間に旧HTMLから新HTMLへ即時切替する。service-worker は v17 → v18 にバンプ。既存ユーザーは一度だけ F12 → Application → Service Workers → Unregister → リロードを行えば、以降は何度開いても古い版に戻らなくなる。 -
2026-06-01
メンバーカレンダー: 参加者・企画者をタグ式マルチセレクトに変更(表記ゆれ根絶)
これまで メンバーカレンダーの参加者・企画者欄は自由入力テキストだったため、表記ゆれ(「ゆう」「ゆうさん」「Yu」「ゆうき」など)で
matchDaoMember_の照合に失敗し、DAO貢献度ポイントが付与されない(またはDAO_LEDGER_REVIEW行きになる)ケースがあった。会員名簿(members/data.json)から取得したニックネーム候補のタグ式マルチセレクトUIに変更し、候補から選んだメンバーは会員名簿の正規ニックネームで保存される(緑チップ)。非会員は「自由入力で追加」から登録可能(オレンジチップ=ゲスト扱い)。企画者欄は1名上限。キーボード操作(↑↓Enter・Backspaceで直前チップ削除・Esc)対応。データ形式は従来通りカンマ区切り文字列を維持するため、既存のawardDaoPointsDiff_()/processDaoEventRow_()など下流処理は無改修で動作する。 -
2026-06-01
メンバーカレンダー: 新規イベント登録時もDAO貢献度ポイントを即時付与
これまで メンバーカレンダーで新規イベントを登録した瞬間に参加者・企画者として記載された人にはDAOポイントが即時付与されておらず、翌朝9時の日次バッチ(
processDaoPointsFromAllRows)を待つ必要があった(最大24時間遅れ)。一方、既存イベントを編集して参加者を追加した場合はawardDaoPointsDiff_()が即時実行され遅延なし、という挙動の不一致があった。schedule_addハンドラを修正し、登録成功時もawardDaoPointsDiff_()(旧参加者・旧企画者は空文字)を呼ぶように統一。新規登録された参加者はDAO_CONFIG.participantPoints、企画者はDAO_CONFIG.organizerPointsがその場で付与される。重複防止は DAO_LEDGER の entryKey で担保(既存と同じ仕組み)。cocola_topics GAS は v201 として固定IDAKfycbzVs_W57...へ redeploy 済(@391)。 -
2026-06-01
メンバーカレンダーに「⟳ サイトに反映」ボタンを設置(公開data.json即時更新トリガー)
メンバーカレンダーのツールバーに「⟳ サイトに反映」ボタンを設置した。
update-schedule-data.yml(GitHub Actions 5分おき自動更新)は不安定で公開schedule/data.jsonが遅延することがあるため、誰でも押せる手動GHA起動ボタンを追加した。cocola_topics GAS v200 @390 に新エンドポイントmode=refreshScheduleを追加し、ボタン押下でupdate-schedule-data.ymlをworkflow_dispatchで即時起動する。連打防止のため GAS 側で 30 秒のデバウンスを設定(30秒以内の再リクエストはthrottled=trueで no-op)。ボタンを押すと TOP ページの「📅 新規予定」バーや他メンバーの公開ページに30秒〜1分で反映される。仕組みは DAO PWA の「⟳ 最新の情報に更新」ボタンと同じパターン。 -
2026-06-01
トップページ「今週のCOCoLa」に「📅 新規予定」バーを新設(メンバーカレンダーの追加を通知)
メンバーカレンダーに新しい予定が追加されると、トップページの「今週のCOCoLa」通知パネルに📅 新規予定バーが表示されるようになった。
schedule/data.jsonのcreatedAt(追加日時)を見て、直近7日以内に追加された予定を「予定タイトル(MM/DD 開催予定)」の形式で並べる。データソースは GitHub Actions(update-schedule-data.yml)が5分おきに GAS から同期するschedule/data.json。タイトルをクリックすると メンバーカレンダーページへ遷移する。 -
2026-06-01
トップページ「今週のCOCoLa」: 情報更新があった人を新規入会バーから除外
新規入会したばかりのメンバーが続けて情報修正フォームを送信すると、「新規入会」バーと「情報更新」バーの両方に同じニックネームが並んでしまう違和感があった。
index.htmlのトップ「今週のCOCoLa」表示ロジックを修正し、当該週のrecentUpdatesに含まれるニックネームは「新規入会」バーから除外するようにした。最新アクション(情報更新)を優先表示する形に統一し、二重表示を防ぐ。data.json 側のスキーマ変更は不要、フロント1ファイル変更のみ。 -
2026-06-01
DAO PWA の Service Worker をナビゲーション時 HTTP キャッシュ完全 bypass に改修(古い index.html 居座り問題の根治)
GitHub Pages は
Cache-Control: max-age=600ヘッダを返すため、ブラウザの HTTP キャッシュが10分間古いindex.htmlを保持し、デプロイ直後の更新がユーザー画面に反映されない問題が継続していた(HTML 内の<meta http-equiv="Cache-Control">は HTTP ヘッダではないため HTTP キャッシュを制御できない)。service-worker.jsの fetch ハンドラを改修し、ナビゲーションリクエスト(req.mode === 'navigate')およびdata.json取得時にfetch(req, { cache: 'no-store' })を使うようにした。これにより SW がブラウザの HTTP キャッシュをスキップして必ず origin(GitHub Pages)から最新を取得する。service-worker は v16 → v17 にバンプ。 -
2026-06-01
DAO PWA「⟳ 最新の情報に更新」ボタンを誰でも押せる一般公開機能として追加(30秒デバウンス付き)
これまで
data.json更新を即座に走らせるには 管理画面(パスワード保護)から「DAOデータ」ボタンを押す必要があったが、DAO PWA の提案・投票タブの更新表示の右隣に「⟳ 最新の情報に更新」ボタンを新設し、メンバーなら誰でも押せるようにした。ボタンを押すと cocola_topics GAS の新エンドポイントmode=refreshDao経由でupdate-dao-data.ymlワークフローが即時起動し、数十秒以内に最新の提案・投票結果が反映される。連打防止のため GAS 側で 30 秒のデバウンスを設定(30秒以内の再リクエストは throttled=true で no-op、現在時刻からの経過秒を返してUIに表示)。叩けるワークフローをupdate-dao-data.yml1種に固定したため、ホワイトリスト不要・乱用不可。service-worker は v15 → v16 にバンプ。cocola_topics GAS は v199 として固定IDAKfycbzVs_W57...へ redeploy 済(@389)。 -
2026-06-01
DAO PWA の HTML キャッシュ無効化メタタグを追加(更新が反映されない問題への恒久対策)
dao/index.htmlの<head>に 3種類のキャッシュ抑止メタタグ(Cache-Control: no-cache, must-revalidate/Pragma: no-cache/Expires: 0)を追加した。これまで PWA/ブラウザのHTTPキャッシュが古いindex.htmlを保持し続け、JavaScript の更新(FALLBACK_DANTAI_IDS など)がデプロイ後もユーザー画面に反映されない事象が発生していた。今回のメタタグ追加によりナビゲーションごとにサーバー検証(ETag)が走るようになり、古いHTMLが居座りにくくなる。あわせて service-worker は v14 → v15 にバンプして既存PWAクライアントを強制更新。 -
2026-06-01
DAO提案 P0199「イルミライ☆INZAI イベント企画」を「団体方針」カテゴリに分類(フロント FALLBACK マップへ追加)
DAO提案一覧(提案・投票タブ)の上部タブ「行政につなぐ/団体方針/すべて」のうち、P0199「イルミライ☆INZAI イベント企画」を「団体方針」に分類するよう
dao/index.htmlのFALLBACK_DANTAI_IDSマップに ID を追加した。既存登録は P0176(団体パネル展出展)/P0123(ココハルまつり2026出店)/P0122(COCoLa オリジナルTシャツ)/P0066(マスコットキャラクター募集)の4件で、今回 P0199 を加えて計5件が「団体方針」タブに表示される。FALLBACK は GAS 側スプレッドシートにproposalType列が実装されるまでの暫定マップで、列が実装され次第このマップは効力を失う(proposalTypeが優先される)設計。あわせて PWA キャッシュ強制更新のため service-worker は v13 → v14 にバンプ。
2026年5月
-
2026-05-31
締切未設定でも記録日時から90日経過で自動的に「期限切れ」判定(活動停止した古い提案を視覚的にアーカイブ化)
「投票締切」を設定していない提案でも、記録日時から90日経過したものは自動的に「期限切れ」ラベルを貼る判定を追加した。これまでは「投票締切」列が未設定の提案は永続的に「投票中」ステータスのままで、活動が止まっている古い提案と新規提案がリスト上で同列に並んでいた。今回
collectDaoProposalPageRows_に 「!deadlineIso かつ 記録日時から90日超過なら isExpired=true」の追加判定を入れることで、古い提案は自動的にexpired(または反対多数ならrejected)に振り分けられ、グレーアウト表示になる。承認済みは保護(既存ロジック維持)。v34 として cocola-dao-gas2 固定IDへ上書きデプロイ済(@84)。実機反映のためupdate-dao-data.ymlを手動キック済。例:P0027(「FreeFree事業と連動した『地域事業者応援掲示板』をサイトに設置」記録日時 2026-01-xx)など、90日以上経過した提案が「期限切れ」表示に切り替わる。 -
2026-05-31
PoC属性データの地区分類を印西市公民館エリア5区分に統一(曖昧な「千葉ニュータウン」を解消)
当初の地区5区分(千葉ニュータウン/木下・大森/印旛/小林・船尾/本埜)は、「千葉ニュータウン」がエリア名で行政区分ではなく曖昧、加えて 「船尾」は印西市内に無く白井市の地名(「船穂」のタイプミス)という整合性の問題があった。指摘を受け、印西市公民館エリア5区分に統一:木下地区(中央公民館エリア)/小林地区(小林公民館エリア)/千葉ニュータウン地区(そうふけ公民館エリア)/印旛地区(印旛公民館エリア)/本埜地区(本埜公民館エリア)。自分がどの地区か分からないメンバー向けに、印西市公民館一覧ページへのリンクをマイカード/Forms ヘルプテキスト/LINE告知文の3箇所に追加(https://www.city.inzai.lg.jp/category/1-9-2-0-0.html)。
cocola_form_update.jsのCIVIC_ATTR_QUESTIONS.choicesとcocola_topics civic-vote.gs.jsのCIVIC_VOTE_DISTRICTS/CIVIC_VOTE_BIASESも同期更新。「印西市外(その他)」を選択肢に追加して市外居住者にも対応。service-worker は v12 → v13 に更新。 -
2026-05-31
PoC属性データ蓄積機能を追加(入会フォーム拡張+マイカードに登録案内)
将来的に「印西市民意向投票PoC」を実証する際に、投票結果を 地区・年代・性別 ごとに匿名化集計できるよう、COCoLaメンバーの属性データを 任意で蓄積する仕組みを追加した。
① Google Forms(入会・情報修正フォーム)に属性3質問を追加するスクリプトをcocola_form_update.jsに実装(addCivicAttributeQuestions())。地区5区分・年代6階層・性別3区分(civic-vote.gs.js と完全一致)。
②コード.gsのmergeMemberRow_を拡張し、「情報の修正・更新」時に 属性列(地区・年代・性別)もマージ対象に追加。findCivicAttributeColumnIndices_でヘッダから動的検出。
③ DAOアプリの マイカードタブに「PoC属性データ登録のお願い」セクションを追加。オレンジ系の civic-attr-prompt で「📝 属性を入力する」ボタン → 入会・情報修正フォームへ誘導。
④ プライバシー設計:入力は任意 / 運営のみ参照 / 個別の意見公開や個人特定は行わない / k-anonymity しきい値5 で匿名化。マイカードに自分の属性は表示しない(プライバシー優先)。
cocola-gas v58 @81 固定IDへ上書きデプロイ済(GASエディタでaddCivicAttributeQuestions()を1回実行すると Forms 側に質問追加)。service-worker は v11 → v12 に更新。 -
2026-05-31
「テスト通知を出す」ボタンを本番運用UIから削除(開発用UI整理)
提案・投票画面の右サイドパネル「通知をオンにする」の下に置かれていた 「テスト通知を出す」ボタンを本番運用UIから完全削除。当初は通知機能の動作確認のために「新規提案」「メンバー増加」の見本通知を交互に出す開発用ボタンだったが、本番運用では一般メンバーが使わない機能で UI ノイズになっていたため整理した。
dao/index.htmlからtestNotifyBtn関連の HTML(ボタン要素)と JS(変数宣言・hidden制御・クリックハンドラ・testToggle 変数)を全削除。通知許可ボタン「通知をオンにする」とその状態表示は従来通り動作し、実際の通知(提案追加・メンバー増加時)には影響なし。service-worker は v10 → v11 に更新(PWAキャッシュ強制刷新)。 -
2026-05-31
DAO投票/取消/復元/いいね 各経路で
update-dao-data.ymlを自動キックする実装を追加(5分cron待ちが不要に)これまで
cocola_topicsのtriggerDaoSiteUpdate_()(GitHub Actionsupdate-dao-data.ymlをPOST /actions/workflows/.../dispatchesで即時起動)は DAO提案フォーム送信時のみ呼ばれており、投票・提案取消・提案復元・市民いいねの各経路では呼ばれていなかった。そのため投票直後は GAS 内では即時反映されるのに(CacheService 60秒キャッシュはrefreshDaoProposalPageCache_で書込時クリア済)、公開dao/data.jsonへの反映は 5分cron schedule(しかも GitHub Actions schedule は不安定)頼みで、最長10〜30分の遅延が発生していた。今回dao-points.jsの 4箇所すべてにtriggerDaoSiteUpdate_()呼出を追加: ①onDaoSpreadsheetFormSubmitの投票分岐(refreshDaoProposalPageCache_直後) ②doGet mode=cancelのcancelDaoProposal_成功時 ③doGet mode=restoreのrestoreDaoProposals_成功時 ④doGet mode=likeのrecordDaoCitizenLike_成功時。いずれもresult.ok === trueのみで起動+ try-catch で本処理に影響を与えない安全側設計。@387 として cocola_topics 固定IDへ上書きデプロイ済。実機検証:実際 P0033(Free Freeと市民活動の連携加速)への投票が公開dao/data.jsonに未反映だったため、手動でgh workflow run update-dao-data.ymlを実行→ 12件目(P0033)が反映=_generatedMs=1780224856705(19:54 JST)で確認済。今後の投票・取消・復元・いいねは 30〜60秒以内に公開data.json+TOPページDAOバーに反映される。 -
2026-05-31
提案一覧に「不採用」ステータス独立化/フィルタ&ソート追加/不採用・期限切れをグレーアウト
提案一覧の改修。
① 「不採用」ステータスを「期限切れ」から分離して独立したrejectedキーに。「不採用」「否決」「却下」と書かれた提案、または締切超過時に反対者が過半数(反対重み > 賛成重み かつ 投票数 > 0)の場合に自動的に「不採用」と判定する。
② フィルタタブを5種類に拡張:すべて / 投票中 / 承認 / 不採用 / 期限切れ。これまで「すべて」にしか表示されず識別困難だった不採用・期限切れの提案を、専用タブで絞り込めるようにした。
③ ソート機能を新設:既定(ステータス順)/ 新しい順 / 古い順 / 賛同率の高い順 / 投票数の多い順の5種類から選択可能。
④ 不採用・期限切れカードはグレーアウト表示(opacity 0.55 + 軽い grayscale)。完全に非表示にせず、自走して新規団体につながる可能性のある提案を後から見返せる設計。マウスホバーで通常表示に戻る。
GAS 側は cocola-dao-gas2 dao-points.js でgetDaoProposalPageStatusKey_から「不採用」を独立化し、collectDaoProposalPageRows_に締切超過時の自動判定ロジック(反対多数 → rejected、それ以外 → expired)を追加(v33 固定IDへ上書きデプロイ予定)。service-worker は v9 → v10 に更新(PWAキャッシュ強制刷新)。 -
2026-05-31
DAO提案フォームを改修:カテゴリ動的切替・要調整事項等・企画提案書URL復活
DAO提案モーダル(『提案する』ボタンから開く)を3点改修した。
① 区分に応じてカテゴリ選択肢が動的に切り替わるようにした。「行政につなぐ」は従来通りイベント / 場づくり / 広報 / 学び / 制作 / その他、「団体方針」を選ぶとカテゴリが 「6つのつくる」+ その他(ものをつくる / まちをつくる / つながりをつくる / 食をつくる / じぶんをつくる / ともにつくる / その他)の7つに自動で差し替わる。
② 任意項目「必要なもの(任意)」を「要調整事項等(任意)」に文言変更(プレースホルダも「人・場所・費用…」→「協議・調整が必要な事項を記載」に)。
③ いつの間にかフォームから消えていた 企画提案書添付欄を復活。Google ドライブ等にアップロードした「リンクを知っている全員」共有の URL を貼付する方式(任意・URL バリデーション付き)。提案カードには従来通り「企画提案書を見る」リンクとして表示される。GAS 側は cocola-dao-gas2 dao-points.js のsubmitDaoProposalFromApp_とbuildDaoProposalRowMap_にattachmentUrl引数を追加し、提案シートの「企画提案書URL」列へ書き込むよう対応(v32 固定IDへ上書きデプロイ予定)。service-worker は v8 → v9 に更新(PWAキャッシュ強制刷新)。 -
2026-05-31
印西PoCの説明文を「事業提案前の独自検証」トーンに修正(協働事業の事前確定を避ける表現に統一)
印西PoCタブのリード文・警告バナーの表現を「CBIと印西市の協働事業として実証中」から「Community Bank INZAI(CBI)が事業提案前の段階で独自に検証中」に修正した。協働事業が確定していない現段階で、市との協働事業を既定路線として記載するのは事実と乖離するため、CBIが事業提案前の独自検証段階で技術的成立性を確かめている PoCであることを明確化。あわせて警告バナーの「市長説明用のPoCデモ/印西市民全体に開いていく次世代基盤を市民・行政に示すための実証段階」も「事業提案前段階で独自に進めている技術検証用PoCデモ/将来的な市民意向把握の選択肢として技術的成立性を確かめる検証段階」に書き換え、最後に「本PoCの結果が事業として採用されるかは未定です」と明示。service-worker は v7 → v8 に更新済(PWAキャッシュ強制刷新)。
-
2026-05-31
DAO提案に「投票締切」を追加:締切超過で自動「期限切れ」ラベル+投票ボタン無効化(既存11件は期限なし扱い)
DAO提案フォームに 「投票締切日(任意)」欄を追加した(
dao/index.html提案モーダル)。空欄ならこれまで通り 期限なし。締切日を入力すると、その日の 23:59:59(JST)を過ぎた瞬間から提案カードのステータスが自動で 「期限切れ」(グレーバッジ)に切り替わり、「投票する」ボタンは 「投票終了」 として disabled 状態(クリック不可)に変わる。バックエンド側でもmode=vote時に締切超過を検知すると{ok:false, error:'expired'}を返すため、フォーム改ざんで投票することもできない。GAS 提案シートに 「投票締切」列を1つ追加(不足列はinsertDaoProposalRowByName_が自動で末尾追加するため既存運用に影響なし)。collectDaoProposalPageRows_で締切超過行は statusKey='expired'、status='期限切れ'に上書きし、承認済み提案は保護。renderStatsの「投票中」カウントから期限切れを除外し、「期限切れ」件数を新規追加表示。既存11件の提案はすべて期限なし扱い(投票締切列が空欄のままなので影響なし)。cocola-dao-gas2 v31 @81(フロント API 側)+ cocola_topics v199 @386(GHA endpoint 側)を本番固定IDへ上書きデプロイ済。service-worker は v6 → v7 に更新済(古いPWAキャッシュを破棄)。 -
2026-05-31
新メンバーに welcome メール(LINEグループ招待リンク入り)を自動送信する仕組みを追加+LINE設定診断関数を新設
新メンバー登録時に 本人宛にwelcomeメールを自動送信する仕組みを追加した。メールは件名「【COCoLa】ご入会ありがとうございます/LINEグループご案内」で、COCoLa公式サイト・メンバーズアプリ・DAO提案投票・イベント一覧の各リンク+緑色の 「▶ LINEグループに参加する」ボタン(Script Properties
LINE_GROUP_INVITE_URLから取得、未設定なら「準備中」表記の fallback 内蔵)が入る。cc はcocola.project@gmail.com、replyTo も同じ。onFormSubmit()の新規登録分岐末尾でsendWelcomeMail_(email, nickname)を呼ぶ。手動再送用にsendWelcomeMailToNickname_(nickname)(会員名簿からメール検索→ 送信)も恒久実装。LINE自動通知が止まっている原因切り分けのため、diagnoseLine_()診断関数を新設(TOKEN/GROUP_ID/招待URLの保存状況確認+ test push HTTP code表示)、setupLineGroupId_(id)・setupLineGroupInviteLink_(url)も補助で追加。実機で Yakkkoooさんに招待メール送付済+ LINEグループ招待リンクhttps://line.me/ti/g/cCTmyBcwK-を Script Properties に保存済(今後の新規登録はすべて自動で招待リンク入りメールが届く)。v79 @79 として本番固定IDへ上書きデプロイ済。 -
2026-05-31
新メンバー登録時に10項目を自動検証→管理者にHTMLメール通知する仕組みを追加
新メンバー登録のたびに「ちゃんと TOP画面・メンバーズアプリ・DAO・LINE・Push・フォーム通知メールに正しく反映されたか」を人手で1つずつ確認するのは大変なので、GAS が自動で10項目を検証して結果をHTMLメールで管理者宛 (
cocola.project@gmail.com+ ccyou0810jmsdf@gmail.com) に送る仕組みを追加した。onFormSubmit()の新規登録分岐末尾でtriggerWorkflow_()実行後にUtilities.sleep(90000)で90秒待機(GitHub Actions の workflow 完走+ CDN 反映待ち)→verifyNewMemberSelfCheck_(timestamp, nickname, email)を呼び出し、以下を検証する: ①TOP🎉新規入会バー表示 ②members/data.jsonrows反映 ③メンバーズアプリ カード一覧 ④mode=verifyMemberレスポンス ⑤DAOメンバーシート行追加 ⑥公開dao/data.jsonのmembers[]⑦DAO提案フォーム提案者プルダウン(⏸️手動) ⑧LINEグループ🎉通知(⏸️手動) ⑨Push通知 購読者数(cocola-push-gas のmode=count) ⑩Googleフォーム回答通知メール(GmailApp.search)。結果は ✅/❌/⏸️ アイコン付きHTMLテーブル+件名サマリ「合格 N/10、NG M、要手動 K」で送信。v76 @76 として本番固定IDへ上書きデプロイ済。⏸️項目(⑦⑧)は将来 cocola_topics WebApp に選択肢取得API追加・sendLineNotification_のHTTPコード返却で完全自動化可能。 -
2026-05-31
テストデータ「テスト_2026-05-26」を会員名簿+DAOメンバーシートから物理削除(一回限りの掃除関数を追加)
5/26 にテスト目的で投入したダミー登録「テスト_2026-05-26」が、サイトTOPの「🎉 新規入会」バー・メンバー紹介カード・DAOメンバー一覧の各所に残っていたため、会員名簿スプレッドシート(
13FwQyLeZK...)の「フォームの回答 1」シートと、DAOメンバースプレッドシート(1Xma1V9...)の「DAOメンバー」シートの両方から物理削除した。cocola-gas/コード.gsに一回限りの掃除関数deleteTestMemberByNickname_(nickname, dryRun)+ DryRun/Live ラッパーを追加(安全弁:ニックネームが「テスト」で始まらない場合は拒否、後方からループしてインデックスずれを防止、Live成功時はtriggerWorkflow_('update-members-data.yml')で公開 data.json を即時更新)。v75 @75 として本番固定ID(GHAが叩くエンドポイント)へ上書きデプロイ済。DryRun → Live 順で実行し victims 1件で削除完了。 -
2026-05-31
メンバー登録/更新/退会フォーム送信時に GitHub Actions を自動キックする実装を復活(5分cron待ちが不要に)
そもそも設計上、メンバー登録フォーム送信時に GAS が GitHub Actions の
update-members-data.ymlを直接叩いて即時反映することになっていたが、onFormSubmit()の3分岐(新規/更新/退会)すべてでtriggerWorkflow_()の呼び出しが抜けていた。triggerWorkflow_()本体(GitHub REST APIPOST /repos/{owner}/{repo}/actions/workflows/{file}/dispatchesを Bearer PAT で叩く実装)と WebApp 入口 (mode=triggerWorkflow) は元から存在していたが、フォームのトリガーから呼ばれていなかったため、TOPページ通知バーやメンバーズアプリへの反映は 5分cron 頼みになっていた(しかも GitHub Actions の schedule は不安定)。今回onFormSubmit()の新規登録分岐・退会分岐・更新分岐の3箇所すべてにtriggerWorkflow_('update-members-data.yml')を追加。clasp redeployで本番デプロイ v74 @74(GHA が叩く固定ID)へ反映済み。これにより、フォーム送信直後にメール通知+GitHub Actions が同時発火し、TOPページ通知バー(新メンバー/退会/情報更新)とメンバーズアプリPush通知が 数十秒以内に反映される。 -
2026-05-31
新規メンバー登録時にメンバーズアプリへPush通知が届くようにした(TOPページ通知バーも即時反映)
これまで新規メンバー登録時は 管理者宛メールのみが飛び、サイトTOPの「新メンバーバー」やメンバーズアプリのPush通知に反映されない不具合があった。原因は2系統:(1) push-notify ワークフローが
dao/data.jsonの変化しか監視していなかった、(2)send-push.jsに members/data.json の差分検知ロジックが無かった。修正として、push-notify の paths にmembers/data.jsonを追加し、send-push.js に「前コミットと現在のrows末尾を比較して新規登録を抽出 → ニックネーム入りのPush通知を全購読者へ送信」する処理を追加した。また、TOPページ通知バー(members/data.json)は GitHub Actions の schedule 遅延で 5/31 10:17 登録の 「Yakkkooo」さんが取り損ねていたため、gh workflow run update-members-data.ymlで手動トリガーし即時反映済み。 -
2026-05-31
印西PoC属性分析に「選択肢別表示」を追加(クロス集計を両方向で見られる)
印西PoC属性分析モーダルに 「軸別表示/選択肢別表示」タブ切替を追加。これまでは「地区別→A/B/C の内訳」の方向しか見られなかったが、「A案/B案/C案ごとに → どの地区・年代・性別の人がどれだけ票を入れたか」を別タブで一覧できるようになった。選択肢別タブでは、各選択肢ごとに 地区/年代/性別 の票数分布が降順横棒グラフで表示され、各属性カテゴリーがその選択肢の中で占める割合(%)も併記される。例:「A案は千葉ニュータウン地区が47%・木下21%・印旛16%…」といった逆方向クロスが一目で分かる。市長説明での「どの層が何案を支持しているか」という典型的な議論に直接答えられるUIになった。あわせてPWAキャッシュを v5 → v6 にバンプして全クライアントで強制刷新。
-
2026-05-31
印西PoCの「属性分析」が動かない不具合を修正(GAS接続先を正しい方に変更)
印西PoCタブで「📊 属性分析を見る」を押すと 「Unexpected token '<'...」エラーが出ていた不具合を修正。原因は、印西PoCの集計を担う GAS が cocola_topics スクリプト側にあるのに対し、フロントエンドが COCoLa本体DAOの GAS(別スクリプト)を叩いていたこと。フロント側で civicVote 専用の GAS_URL を独立定義し、cocola_topics の正しいデプロイメント(v201@385)を直接参照するように切替えた。投票記録の保存・分析データの取得・seed されたダミー90票(議題ごとに45票×2/属性付き)の表示すべてが正常動作する状態になった。あわせてPWAキャッシュを v4 → v5 にバンプして全クライアントで強制刷新。
-
2026-05-31
印西PoCタブに「📊 属性分析」ボタンを追加(地区/年代/性別)
市長説明での議論を見据え、印西PoCタブの各議題カードに 「📊 属性分析を見る」ボタンを追加。クリックすると、その議題の投票内容を 地区別(5区分)/年代別(6区分)/性別(3区分)で分解した分析モーダルが開き、それぞれのカテゴリーで「どの選択肢にどれだけ票が集まったか」が積み上げ棒グラフで一目で分かるようにした。k-anonymity しきい値5を採用し、グループサイズが小さすぎる集計は「少数(非表示集約)」にまとめて個人特定を防ぐ設計。本番運用時は xID 等の認定事業者経由で属性を取得・匿名化集計する想定で、本PoCではデモ用ダミーデータ(印西市の人口比に近い配分+議題に応じた支持傾向)を表示している点を画面下部に明記した。GAS は v201@385 で action=analytics エンドポイントを追加、seed関数も属性付与版に更新済み。あわせてDAOページのPWAキャッシュを v3 → v4 にバンプして全クライアントで強制刷新。
-
2026-05-31
「印西投票」タブをPoC実証用に明示/メンバー誤操作防止
ボトムナビの「印西投票」タブが COCoLa内部の『提案・投票』と混同されるという指摘を受けて、PoC実証であることを視覚的に明示する改修を実施。タブラベルを「印西PoC」に変更し、「実証」バッジを添えた。タブの色をオレンジ系にして規定タブと視覚的に区別。タブを開いた直後の警告バナーで「COCoLaの提案・投票とは別の機能です」「本体の意思決定はこれまで通り『提案・投票』タブで」と明記した。あわせて市長説明用のPoCデモ用ダミー投票データ(議題ごとに約45票・自然な分布)を仕込む関数 seedCivicVotePoCDataを GAS 側に追加(v200@384)。1票しか入っていないと棒グラフが100%になり実証感が出ないため、市長説明前に実行することで「動いている感」を演出する。
-
2026-05-31
DAOページのPWAキャッシュを強制刷新/ハッシュ変更追従を追加
「提案/投票」リンクから飛んでも提案タブが開かず「マイカード」が出てしまう不具合の解消。原因はPWA(Service Worker)が古いキャッシュを配信していたこと。キャッシュバージョンを v2 → v3 にバンプして全クライアントで強制刷新するようにした。あわせて DAO ページに URL ハッシュ変更を検知して即タブ切替するリスナーを追加し、ブラウザ履歴の戻る・進む操作や手動でハッシュを書き換えた際にも正しいタブが開くようにした。なお、まだ「マイカードが出る」と感じる方は Ctrl+Shift+R で強制再読込、または PWA アプリを一度終了→再起動してください。
-
2026-05-31
「提案/投票」リンクから直接提案・投票画面が開くように改善
トップページの「提案/投票」リンク(ヘッダーナビ/中央CTAボタン/フッター/注目提案バー)をクリックしたとき、これまでは DAO ページの初期画面「マイカード」がまず表示され、提案・投票を見るには下部メニューでもう1タップ必要だった。今回の修正で、これらのリンクを ./dao/#proposals に統一し、リンクから1クリックで 「提案・投票」タブが直接開くようにした。提案を見たい・投票したいユーザーが余計な操作なしに目的のタブに直行できる。
-
2026-05-30
DAOページに「印西投票」タブ追加(CBI/印西市協働事業PoC)
COCoLa DAO ページのボトムナビに 「印西投票」タブを追加した。これは Community Bank INZAI(CBI)と印西市の協働事業として実証中の市民意向投票プラットフォーム PoC で、マイナンバーカード(JPKI/公的個人認証)でご本人確認のうえ、印西市の市民意向に投票できる仕組み。PoC段階のためデモ用議題が2件(駅前再整備案・図書館サービス改善)入っている。JPKI 認証はモック画面で動作確認可能で、本格運用時は xID 等の認定事業者を経由する。投票記録は カードシリアル番号のハッシュのみを保存する設計で、個人情報は保持しない。これは 6/12 市長説明での協働事業提案の実証実装として、本番DAOページに先行統合したもの。
-
2026-05-30
Threads自動投稿が6カテゴリー対応+日3回の完全自動投稿に
これまで「じぶんをつくる」「ともにつくる」の2カテゴリー・承認制で運用していた Threads 投稿管理ツールに、「食をつくる」「まちをつくる」「ものをつくる」「つながりをつくる」の4カテゴリーを追加し、COCoLa の全6カテゴリーをまんべんなく毎日配信できるようにした。さらに、朝07:30/昼12:15/夜21:00 の1日3回・完全自動投稿を実装。曜日ごとに当日の担当カテゴリーが自動で切り替わり(月=じぶん/火=ともに/水=食/木=まち/金=もの/土=つながり/日=その週の人気カテゴリー再投稿)、その時間にカテゴリーの未投稿候補から1件をピックして自動でThreadsに投稿される。候補が足りない場合は朝6時の自動補充トリガーが3件まで生成して在庫を保つので、運用者は何もしなくても毎日の投稿が止まらない。管理画面の新設タブ 「🤖 自動投稿スケジュール」で曜日ローテ表と直近の投稿ログ(成功/失敗)が確認できる。投稿失敗時のみメールで通知される設計で、運営の手間を最小化した。
-
2026-05-30
運営管理画面を1か所に集約(TOPの「🔒 管理」から)
これまで別々だった運営ツールへの入口を運営管理画面(admin)に統合した。トップページの「🔒 管理」を押すと、Threads投稿管理・グッズ交換キャンペーン管理・QRスキャナ・アクセス解析/GCloud残高監視・データ手動更新(GitHub Actions)がカードで一覧表示され、そこから各ツールに入れる。これまでトップページのポップアップに分散していたメンバー/イベント/DAO/スケジュール等のデータ即時更新ボタンも運営管理画面に移し、入口を1か所にまとめた。運営管理画面にはパスワード保護をかけ(一度入力すれば同じ操作中は再入力不要)、残高やアクセス解析などの運営情報が第三者に見られないようにした。外部の有料サービスは使用していない(追加費用なし)。
-
2026-05-30
グッズ交換キャンペーンを管理画面から登録できるように
これまでスプレッドシートに直接入力していたグッズ交換キャンペーンの登録を、運営管理画面(admin)から操作できるようにした。新設のキャンペーン管理ページ(運営パスワードで保護)で、キャンペーンの新規登録・有効/無効の切替・削除と、各キャンペーンの配布人数の確認がブラウザだけで完結する。キャンペーンIDは自動採番され、開始日・終了日・1人あたり交換回数を指定できる(開始日が未来なら自動で「開始前」、期間を過ぎれば「終了」と表示)。スプレッドシートを開く必要がなくなり、誤入力(チェック値のタイプミス等)にも強くした。外部の有料サービスは使用していない(追加費用なし)。
-
2026-05-30
グッズ交換キャンペーン用QRと、スタッフ用スキャナを追加
市民の方にもCOCoLa DAOアプリを開放するプロモーションとして、マイページの画面提示でグッズと引き換えできるキャンペーンを運用するための仕組みを追加した。会員QRは登録メールアドレスから生成される永続ID(COCOLA-12文字、SHA256短縮ハッシュ)に変更し、キャンペーンを跨いで使い回せるようにした(毎回QRを差し替える必要なし)。生メールはQRに含まないので、スクリーンショット流出時の漏洩・迷惑メール標的化のリスクを排除している。スタッフ側は新設の staff/scan.html(URLパスワード保護)で、キャンペーンを選んでQRをスキャンするだけ。同一メンバー×同一キャンペーンの重複交換はサーバ側で自動拒否し、「いつ・どのスタッフが渡したか」を返却するので二重交換を防止できる。さらにスタッフ画面に「📋 履歴」タブと、画面上部に「🎁 配布済み ◯名」の配布人数カウンターを追加し、全スタッフの交換状況を10秒ごとの自動更新でリアルタイム共有できるようにした。複数のスタッフが同時に別々の来客を受け付けても、記録は1つの共有シートに集約されるため、全体で何人に配り終えたか・誰が交換済みかをどのスタッフの画面でもその場で確認でき、二重交換を確実に防げる。キャンペーンは「キャンペーンマスタ」シートで複数並行管理可能(期間・1人あたり回数を設定)。外部の有料サービスは使用していない(追加費用なし)。
-
2026-05-29
イベント受付でQRスキャン→DAOポイント付与(受付ページを追加)
会員証のQRコード(ニックネーム)を受付スタッフがスキャンして、その場でDAOポイントを付与できる受付ページ(dao/checkin.html)を追加した。受付ページは受付パスワードで保護し、対象イベントは受付URLで指定(手入力も可)。1イベント参加につき固定2ポイントを付与し、同一会員×同一イベントの二重付与は防止(台帳キーで冪等管理)。会員名簿と照合するため、非会員や誤読のニックネームには付与されない。カメラが使えない場合はニックネームの手入力でも受付できる。外部の有料サービスは使用していない(GitHub Pages+Google Apps Scriptの無料枠のみ・追加費用なし)。
-
2026-05-29
DAOアプリに「メンバー」タブ(メンバー検索・マッチング)を追加
DAOアプリのボトムナビに5つ目の「メンバー」タブを追加し、COCoLaメンバーを検索・マッチングできるようにした。名前・職業・できること(スキル)・今後やりたいこと・保有資格・所属でキーワード検索でき、「ものをつくる」「まちをつくる」などのカテゴリで絞り込みも可能。各メンバーのカードには、できること・やりたいこと・保有資格・SNS/Webリンクを表示し、関心の近い仲間を見つけて各自のSNS等から連絡できる。メールアドレスは表示しない(プライバシー保護)。データは会員名簿(members/data.json)を利用し、メンバータブを開いたときに読み込む(遅延読込)。外部の有料サービスは使用していない(追加費用なし)。
-
2026-05-29
ログイン後のTOPを「マイカード」(会員証)に(QRコード付き)
DAOアプリにログインすると、最初に自分専用の会員証「マイカード」が表示されるようにした。ボトムナビの先頭を「マイカード」にし、ニックネーム・ステータス・貢献度ポイント(累計/直近6ヶ月)・COCoLaメンバー内での順位を会員証デザインのカードで表示。あわせて本人確認用のQRコードを表示する(中身は当面ニックネーム。将来の各種サービス連携の入口)。QRは外部API不要のローカルJSライブラリ(qrcode-generator・MIT)で生成し、追加費用はかからない。ポイントランキングは会員証の下に引き続き表示。※QRをかざしてポイントを使う(消費)仕組みは今後のフェーズで検討。
-
2026-05-29
会員名簿の公開データからメールアドレスを非公開化(プライバシー保護)
メンバー一覧の公開データ(members/data.json)に含まれていた登録メールアドレスを除去し、誰でも閲覧できる状態を解消しました。運営によるメーリングリストのコピー機能は、パスワードで保護された専用窓口から取得する方式に変更しています。本人ログイン(メール照合)には影響ありません。
-
2026-05-29
DAO提案をアプリ内で完結(Googleアカウント不要に)
これまでDAO提案は外部のGoogleフォームに飛ぶ作りで、フォームがGoogleログイン必須だったため、Googleアカウントを持たないメンバーは提案できなかった。これを解消し、アプリ内の入力画面から直接提案できるようにした。「提案する」ボタンを押すと、ログイン中の本人として提案フォーム(提案タイトル/区分〈行政につなぐ・団体方針〉/カテゴリ/理由・詳細/必要なもの)が開き、送信すると一覧に反映される。提案者はログイン中のニックネームで自動設定され、Googleアカウントは不要。サーバー側(cocola-dao-gas2)に
mode=submitProposalを新設し、既存のフォーム送信と同じ仕組みで提案を登録・提案ポイント(3pt)を付与・重複チェックも行う。投票に続いて提案もアプリ内で完結するようになり、外部の有料サービスやメール送信APIは使用していない(追加費用なし)。 -
2026-05-29
印西イベントを「当日/期間」で切り替え表示(長期講座が混ざらないように)
DAOアプリの「印西イベント」タブに、イベントの種類で切り替えられるボタンを追加した。「2026年1月11日〜6月28日」のような長期講座(期間イベント)が一覧の上に溜まり、1日だけの当日イベントを見るのにスクロールが大変だった問題を解消。切替は「当日イベント」(既定・113件)/「期間イベント」(12件)/「すべて」(過去含む全件)の3つ。日付欄が「○月○日〜○月○日」のように日付範囲になっているものを期間イベントとして自動判別する(「13:00〜17:00」のような時間の表記は誤判定しない)。既定表示が「当日イベント」になったため、開いてすぐ直近の単発イベントが見られる。
-
2026-05-29
DAOアプリを本人ログイン制にし、自分専用画面に(メール照合・全タブ本人モード)
DAOアプリ(
dao/index.html)を個人認証アプリ化した。起動時にCOCoLaに登録したメールアドレスでログインすると、以降は全タブが「あなた専用」の表示になる。ログイン方式: 入力されたメールアドレスを Google Apps Script(cocola-gas に新設したmode=verifyMember)がサーバー側で会員名簿と照合し、一致すればニックネームだけを返す。メールアドレスは端末にも公開データにも保存されない(照合のみ)。退会者・未登録のメールではログインできない。DAOポイント画面: ニックネーム選択式をやめ、ログイン中の本人のポイント(累計・直近6ヶ月)とCOCoLaメンバー全体での順位(会員名簿の全員を分母に集計)を本人カードとして表示。ランキング表では自分の行をハイライトする。投票: 投票時のニックネーム選択を廃止し、ログイン中の本人として投票する。ヘッダーにログイン中のニックネームと「ログアウト」ボタンを追加。追加費用なし: GitHub Pages と Google Apps Script の無料枠のみで動作し、外部の有料認証サービスやメール送信APIは使用していない。 -
2026-05-28
DAOポイント画面のメンバー一覧が消える不具合を解消(GAS本体を修正)
DAOアプリは初回に公開JSON(
dao/data.json)でメンバー一覧(26名)を表示した後、5分経過すると GAS エンドポイントを直接読み込む。この直叩き応答(mode=json)にmembersが含まれておらず、DAOポイント画面のメンバー一覧が空になる不整合があった。GAS本体(cocola-dao-gas2)のmode=json応答にメンバー一覧(ニックネーム・ステータス・投票権重み・ポイント)とstats.members/stats.eligibleMembersを追加し、公開JSONと同じ内容を返すよう修正。直叩き後もメンバー一覧(26名・有効投票権26名・合計重み30.2)が表示され続けるようにした。 -
2026-05-28
DAOアプリに画面切替メニューを追加(提案・投票/DAOポイント/印西イベント/予定)
dao/index.htmlの画面下部にボトムナビ(4タブ)を新設し、1つのアプリ内で4つの画面を切り替えられるようにした。提案・投票(従来の提案一覧・投票)、DAOポイント(メンバー一覧と投票権・ポイント付与基準)、印西イベント(events/data.jsonから印西市周辺の地域イベントを「これから/すべて」で表示)、予定(schedule/data.jsonから COCoLa の予定を月別・日付順に表示)。印西イベント・予定はタブを開いたときに読み込む(遅延読込)。あわせて、GAS応答にmembersが含まれない場合でも取得済みのメンバー一覧を保持するよう修正し、DAOポイント画面が空にならないようにした。 -
2026-05-28
DAO提案・投票ページをPWA化+新着通知機能を追加(スマホアプリ実証)
dao/index.htmlを PWA(Progressive Web App)化し、スマホのホーム画面に「アプリ」として追加できるようにした。追加要素:dao/manifest.webmanifest(standalone表示・テーマカラー#1d8f6f・COCoLaロゴアイコン 192/512/maskable)、dao/service-worker.js(アプリシェルのオフラインキャッシュ+通知表示+通知タップでアプリを前面化)、Apple Touch Icon/iOS用メタタグ。新着通知: 「🔔 通知をオンにする」ボタンを提案・投票フォーム欄に新設。許可するとdata.json(GitHub Actions が5分毎更新)を3分間隔でポーリングし、新しい提案・新しいメンバーを検知して端末に通知する。前回表示分はlocalStorageに記録し差分のみ通知(初回・既存分は通知しない)。実証段階のため Web Push(VAPID)は未使用=アプリ/ブラウザ起動中の通知に限定。テスト通知: 動作確認用に「テスト通知を出す」ボタンを設置(通知オン時のみ表示)。押すたびに「新しい提案」「メンバー増加」の見本通知を交互に表示し、その場で通知の見え方を確認できる。注記: iOS はホーム画面に追加した PWA でのみ通知可(iOS 16.4 以降)、Android はブラウザでも可。既存の提案一覧・投票・DAOポイント・メンバー一覧の機能には影響なし。 -
2026-05-27
CiDAO ロードマップにセクション目次+コメント折りたたみ機能を追加(UX改善)
コメント蓄積による可読性低下を解消するため、セクション目次(TOC) をページ上部に新設し、各セクションのコメント欄を
<details>ベースの折りたたみ式に変更。セクション目次: 7セクション全てを2カラム配置(モバイルは1カラム)でアンカーリンク表示、ジャンプ可能。さらに「💬 コメントを全て開く」「📕 コメントを全て閉じる」ボタンを目次右側に配置し、一括操作可能に。コメント折りたたみ: 各セクション末尾の「💬 メンバーコメント・調整履歴 (N件)」の summary をクリックで開閉。デフォルトは閉じた状態で、件数バッジは0件時にグレー・1件以上で緑色に変化し存在を可視化。開閉状態の記憶: 各セクションの開閉状態をsessionStorage(キー:cidao_open_<section>)に保存し、ページ内移動・リロードでも維持。UI仕様: summary は緑色のチェブロン(▶/▼)アニメーション付き、ホバーで背景がグリーンソフトに変化。目次パネルはlinear-gradient(135deg,#fff,green-soft)の柔らかい背景+ドット下線リンクで視認性向上。これにより、サマリ本文を「読む」状態とコメント・調整履歴を「議論する」状態を明確に切り分け、長期運用でもページが過度に伸びない。 -
2026-05-27
CiDAO ロードマップ各セクションにコメント・調整履歴機能を追加(GAS v200 @366)
lab/cidao-roadmap.htmlの7セクション(CiDAOの目的/5段階の開発フェーズ/想定累積予算/外注必須項目/主要懸案/通常開発工程との照合/文書バージョン管理)にメンバーのコメント・調整履歴を残せる機能を実装。4種類のラベル(所見・調整履歴・質問・決定事項)でカテゴライズし、それぞれ専用色で表示。投稿者名は自由入力(sessionStorageに直近の入力を保存して次回自動補完)、追記のみ(編集・削除不可)で履歴を完全保全。GAS側:cocola_topics_clasp_syncにmode=cidaoRoadmapCommentエンドポイントを新設(doGetのaction=listでセクション別取得、doPost+action=submitで投稿)。スプレッドシートに「CiDAOロードマップコメント」シートを自動作成(列:timestamp / section / author / kind / body / visible)。本文は5,000文字まで、投稿者名60文字まで、XSS対策のためHTMLエスケープを徹底。UI: 各セクション末尾に投稿件数バッジ・コメント一覧(新しい順、最大320pxスクロール)・投稿フォーム(投稿者名・種別ドロップダウン・本文・投稿ボタン)を配置。レスポンシブ対応(600px以下で2列レイアウト)。GASデプロイ: v200 @366 として cocola_topics に反映済み。 -
2026-05-27
CiDAO 開発計画サマリページに部外秘パスワード保護を追加
研究室ページ(
lab/index.html)の「CiDAO 開発計画」セクションに 🔒 部外秘バッジ(赤色) と注意文を表示。サマリページ(lab/cidao-roadmap.html)へのアクセスにパスワード認証を導入。「サマリを見る」ボタン押下時にprompt()で入力を促し、SHA-256ハッシュで照合(プレーンテキストパスワードはソースに含めない設計)。直接URLアクセスにも対応するためcidao-roadmap.html冒頭でdocument.writeによりbodyを即時非表示化し、DOMContentLoaded時に認証チェック → 不正・キャンセル時は研究室TOPへリダイレクト、認証成功時のみマスクを除去して内容表示。認証フラグはsessionStorageに保存し、同一セッション内で再入力不要。今後の外注先・関係者には別途パスワードを伝達。 -
2026-05-27
CiDAO 開発専用フォルダ新設+初期文書 v1.0 群を整備(仕様書/ロードマップ/外注計画/懸案事項/工程定義)
全印西市民向け市民DAO(CiDAO = Citizen DAO)と地域通貨「COCoLa Coin」の開発を本格化させるため、専用フォルダ
C:\COCoLa\cidao\を新設し、担当エージェント定義(CLAUDE.md)と5本の主要文書を初版作成。バージョン管理規約(VERSIONING.md、セマンティックバージョニング準拠)に従い、各文書をファイル名NN_タイトル_vX.Y.md形式で命名、README.md を Single Source of Truth として運用。主要文書: (1) 開発仕様書 v1.0(C1〜C13 の13コンポーネント、JPKI/SBT/ERC-20 アーキテクチャ、データモデル、法務8法令対応)。(2) 開発ロードマップ v1.0(Phase 0〜4 の5段階、2026〜2029、累積予算1.5〜2億円、撤退条件+Plan B 明記)。(3) 外注計画 v1.0(O-01〜O-18 の18項目:JPKI事業者・スマコン開発・監査・モバイルアプリ・法務・PR等の選定基準と費用想定)。(4) 懸案事項管理表 v1.0(25懸案を法務/政治/技術/運用/財務/倫理/災害/国際の8軸でリスクスコア化、上位R-01資金決済法・R-02公職選挙法・R-03印西市協定の対処計画)。(5) 工程定義 v1.0(通常開発25工程との照合、15項目の抜けを補完:EOL計画・SLA定義・インシデント対応・IaC・CI/CD・経済モデル検証等)。研究室ページに CiDAO サマリ公開ページ を新設し、TOPからアクセス可能に。詳細文書はローカル管理。 -
2026-05-27
COCoLa研究室ページ新設(スマホ会員証SBT実証実験/視認性チェック/コメント収集)
将来の「印西市民全員による投票」「地域ポイント導入」に向けた実証実験ページとして
lab/index.htmlを新設。TOPナビに「🧪 研究室」リンクを追加。導入目的を①投票時の個人識別(なりすまし防止)②地域ポイント導入の2点に明示。機能: (1) SBT会員証モックアップ(lab/sbt-mockup.html)— 初回登録/JPKI認証/会員証発行/投票/履歴 の5画面を1ファイルでタブ切替表示、cocola-site/dao のブランドカラーを完全踏襲。(2) 端末別プレビュー切替 — スマホ縦横/タブレット/PC(375×812〜1280×800 の7プリセット)と表示倍率35〜100%で iframe スケーリング。(3) 実機検証QRコード — qrcode.js でモックアップURLを即時QR化(実機での視認性確認用)。(4) 視認性自動チェック — WCAG 2.1基準でコントラスト比・タップターゲット・最小フォントを4カード表示。(5) コメント収集機能 —cocola_topics_clasp_syncの GAS にmode=labCommentエンドポイント新設(doPost新規+研究室コメントシート自動作成)、トピック分類(SBT/なりすまし/ポイント/UI/その他)・匿名投稿対応。GASデプロイ: v199 @365 として cocola_topics に反映済み(200バージョン上限到達のため旧バージョン整理を実施)。 -
2026-05-27
DAO投票モーダルで「ニックネームを選択も変更もできない」事象を根本対処(メンバー一覧読込失敗のリトライ)
利用者スクリーンショットから真因が判明。プルダウンに「-- 選択してください --」しか option が無い状態(=メンバー一覧の fetch が完了していない or 失敗)が原因だった。
loadMemberNicknames()はページロード時に1回呼ばれるだけで、モバイル回線で完了前に投票ボタンが押されたケース・ネットワークエラーで.catch(function(){})に握りつぶされたケースで、選択肢ゼロの状態のまま固まっていた。対処: (1)loadMemberNicknames()を Promise 返却+エラーを再 throw する構造に変更、cache: 'no-store'指定。(2)openVoteModal()内でvoteNicknameSelect.options.length <= 1を検出したら自動再 fetch、ローディング中は disabled+「メンバー一覧を読み込み中…」表示、失敗時は「ページを再読み込みしてからもう一度お試しください。」と明示。(3) 投票モーダルの<label><select/></label>構造をlabel[for]+selectに分離(iOS Safari の既知挙動回避、autocomplete="off"追加)。(4)openVoteModal()冒頭でsetVoteModalLoading(false)を呼び disabled 残留も同時に解消。 -
2026-05-27
DAOページに「行政につなぐ/団体方針」区分タブを追加(市民の関心と団体運営を分離表示)
「市民から見れば団体方針なんて興味ないので」というユーザー要望を起点に、DAO提案一覧の上部に種別タブを新設。
cocola-dao-gas2/dao-points.jsのDAO_PROPOSAL_HEADERSに'区分'列を追加(カテゴリ列の直後)、getDaoProposals_()の出力JSONにproposalType('dantai'=団体方針 /'gyousei'=行政につなぐ)とproposalTypeLabelを付与。区分列が空欄の場合は'gyousei'をデフォルトとする。既存12件の初期値を一括設定するmenuApplyInitialProposalTypes()関数を新設し、DAO運営メニューに「既存提案に区分を初期設定」項目を追加。cocola-site/dao/index.htmlに.type-tabsセクションを追加し、「行政につなぐ(デフォルト)/団体方針/すべて」の3タブと種別ピル(橙=団体方針/青=行政につなぐ)を実装。state.typeFilterでフィルタロジックを拡張。GAS デプロイ前でも分類が機能するよう、フロント側にFALLBACK_DANTAI_IDS = {P0176, P0123, P0122, P0066}の暫定IDマップを実装。初期分類:団体方針 4件(団体パネル展/ココハレ出店/オリTシャツ/マスコット)、行政につなぐ 7件(その他全件)。 -
2026-05-27
DAOページに「DAOメンバー一覧」テーブルを追加(投票権の可視化/未投票者把握の基礎)(
cocola_topics v198 @362)「いずれ未投票者一覧を出すようになるかもしれないので、誰が投票権を有しているか把握するため」のユーザー要望を実装。
dao-points.jsにcollectDaoMembersForPage_(ss)を新設し、DAOメンバーシート全行から{nickname, totalPoints, recentPoints, lastActiveAt, status, weight}を抽出(重み降順→直近pt降順→五十音順)。getDaoProposalPageData()の戻り値にmembers配列とstats.members/stats.eligibleMembersを追加。cocola-site/dao/index.htmlに「DAOメンバー一覧」セクション追加:サマリ(総メンバー数/投票権あり/投票権なし/母数weight)+「投票権あり」テーブル(ニックネーム/重み/直近6ヶ月pt/ステータス)+「投票権なし」テーブル(折りたたみ)。ステータスバッジはアクティブ(緑)/サポーター(青)/休眠(茶)の3色。反映結果:総26人、全員アクティブ=投票権あり、母数30.2。仕様: 最終活動6ヶ月以内→アクティブ(base weight 1.0)/6〜12ヶ月→サポーター(base 0.5)/12ヶ月以上 or null→休眠(weight 0)。シートから行は消えず、ステータスとweightが変わるのみ。新たな活動でポイント付与されれば自動でアクティブ復活。 -
2026-05-26
DAO投票「検討中」「わからない」票を投票数にカウント+ゴーストエイリアス3件削除で P0199 = 12票復活(
cocola_topics v194-v197 @358-@361)ユーザー報告「P0199 イルミライは12名以上は票が入っていたはず」を起点に、集計の欠落を2段階で修正。(1) 名寄せ修正:
debugDaoMemberMatch_で「つる」検索が ambiguous(候補2件: "つる","つるちゃん")と判明、memory v178 と同じ「ゴーストエイリアス」パターン。removeDaoGhostAliases_(dryRun)関数+DAOメニュー+WebAppエンドポイント(スマホ対応)を新設、DAOメンバー別名シートから 3件物理削除(「ゆみちゃん→ゆみ」「ひこ→ひこさん」「つるちゃん→つるちゃん」自己ループ)→dao_aliases_archiveに退避。これで「つる」さんの票が全提案で +1票復活。(2) abstain対応: 残り P0199 8票 vs 期待12票のギャップは「検討中3件・わからない1件」が集計外だったため。ユーザー要望「投票数にはカウントしたい(誰が投票していないか管理ページで把握)」を受け、normalizeDaoVote_で「検討中」「わからない」を空文字→'abstain'に変更。集計関数のcount += 1は vote種別問わず加算する設計なので、abstain も voteCount に含まれる(yes/no重み・承認判定には影響なし)。最終結果: P0199 = 12票 yes=10.8、他提案も abstain票が voteCount に加算(P0123 2→5、P0176 1→3、P0066 3→5)。 -
2026-05-26
DAO投票集計のP0020新形式対応(協力できる/協力は難しい/検討中/わからない)を cocola_topics に移植(
cocola_topics v192-v193 @356-@357)cleanup後にユーザー報告で「投票数が全部消失(P0213/P0199/P0176/P0123/P0122/P0066/P0063 が votes=0)」が発覚。
debugDaoVoteDump_エンドポイントを追加(v192 @356)して投票シート 619行を分析、投票値分布が「賛成229/反対12/協力できる34/協力は難しい1/検討中12/わからない6/空325」と判明。原因は cocola-dao-gas2 で v18 実装済みの P0020 投票方式変更(選択肢を['協力できる','協力は難しい','検討中','わからない/もう少し聞きたい']に変更)が cocola_topics のnormalizeDaoVote_に未移植だったこと。GHA endpoint切替(cc376f1)で cocola_topics 側集計に切り替わった瞬間、新形式投票が全て「判定不能」扱いで votes=0 へ。v193 @357 でnormalizeDaoVote_に新選択肢処理を追加(「協力できる」→ yes/「協力は難しい」→ no/「検討中」「わからない」→ 集計外)。修復後 P0199 を含む7提案の票数が全復活、既存提案も「協力できる」票が正しく yes 扱いされ票数が増加(例:P0027 2→5、P0025 2→4、P0016 3→5)。 -
2026-05-26
DAO提案ゾンビ重複の構造的根治+既存120行の一括クリーンアップ(
cocola_topics v188-v191 @352-@355)cocola_topics に dedup ロジック移植(cocola-dao-gas2 の v28由来):
normalizeTitleForDedup_/normalizeProposerForDedup_/scanDaoProposalSheetForDedupKey_/isDuplicateDaoProposal_を新設し、createDaoProposalRowFromResponse_内で title+proposer 正規化キーによる全期間重複チェック→重複は{duplicate:true, row:null}を返してスキップ。3箇所の呼び元(normalize系)にentry.duplicate || !entry.rowガード追加。これでフォーム再送信や force refresh による ID-rotation zombie を構造的にブロック。既存の残存ゾンビ用にcleanupDaoProposalDuplicates_(dryRun)関数を新設(正規化キーでグループ化→票数/yes/最古順で最良1行を残し他をdao_proposals_archiveシートに退避+物理削除)、DAO運営メニューに「重複提案を一括クリーンアップ(DryRun/Live)」追加。Live 実行で DAO提案シート 120行→32行(過去のフォーム回答転記事故による破損データ80件+正規重複8件をすべて退避削除)、公開 data.json 14→12件で完全クリーン化。あわせて重大バグ修正:doGetのホワイトリストに新規 mode(refreshMemberChoices/debugDaoProposalDump)が登録されておらず HTML が返っていた(cocola-gas からの即時メンバーリスト更新呼び出しが実は機能していなかった)件を修正。 -
2026-05-26
DAO提案フォームの設問タイトル変更に追従+GHA endpoint切り替え(
cocola_topics v187 @351+cocola-site cc376f1)ユーザーがDAO提案フォームで設問タイトルを変更したのに合わせ、サイト側ラベル・コード側エイリアスを統一: 「理由・詳細」→「提案内容の概要」、「必要なもの」→「要調整事項・その他」。
dao-points.jsのgetFirstFromRowValues_検索エイリアスに新ラベルを追加(旧ラベルも維持=過去回答との互換性確保)、configureDaoProposalForm_の新規作成タイトルと通知メール本文ラベルも統一、cocola-site/dao/index.htmlと GAS Webアプリdao-proposals.htmlのカードラベルも置換。あわせて、GitHub Actions のupdate-dao-data.yml・health-check.ymlが長らく別プロジェクトcocola-dao-gas2(v29 @77 古い)を叩いていた問題を発見・修正し、cocola_topicsの最新 deployment(AKfycbzVs...)に統一。これによりv181〜v187 で追加した機能(attachmentUrl、カテゴリ説明文、メンバーニックネームリスト、五十音順ソート、即時更新エンドポイント等)が公開 data.json にも反映されるようになり、提案数も 12 → 14 に増加。 -
2026-05-26
DAO提案・投票フォームをメンバーニックネームのリスト選択方式に変更・メンバー入会時に即時自動反映(
cocola_topics v186 @350+cocola-gas v57 @69)DAO提案フォーム「提案者」と DAO投票フォーム「投票者」を、自由テキスト入力からメンバーニックネームのドロップダウン選択方式に変更。表記ゆれ・スペル誤りがなくなり「保留」状態(メンバー確認できないため公開・集計外)になる提案が発生しなくなる。
dao-points.jsにbuildDaoMemberNicknameChoices_(メンバー入会フォーム回答シートから取得・五十音順ソート:ひらがな/カタカナ→漢字→英字、カタカナはひらがな換算)/ensureDaoMemberChoiceItem_(TEXT型→ListItem 自動変換、既存回答と後方互換)/専用メニュー「提案者・投票者リストを更新」を追加。カテゴリ項目には6つのつくる分類の説明文をsetHelpTextで付与+専用メニュー「カテゴリ説明文を更新」追加。メンバー新規入会時の即時反映のため、cocola_topicsに Web App エンドポイント?mode=refreshMemberChoices&pw=...を新設、cocola-gasのonFormSubmitからUrlFetchAppで呼び出す構成(失敗時も入会処理は止めず Logger に残し、DAO運営メニューから手動復旧可)。 -
2026-05-26
DAO提案カードに「📄 企画提案書を見る」ボタンを表示する仕組みを追加(
cocola_topics v180 @344)DAO提案フォームのファイルアップロード項目(質問タイトルに「企画提案書」「企画書」を含むもの、または
FILE_UPLOAD型)の回答URLを、提案カードのタイトル下に「📄 企画提案書を見る」ボタンとして表示。本文の冗長化を抑えつつ詳細資料へ誘導できる。dao-points.jsにextractFirstDaoAttachmentUrl_/findDaoProposalAttachmentItem_/ensureDaoProposalAttachmentFolder_を新設、DAO_PROPOSAL_HEADERSに「企画提案書URL」列追加、createDaoProposalRowFromResponse_で19列目にURL転記、collectDaoProposalPageRows_がJSONにattachmentUrlを載せる。公開ページcocola-site/dao/index.htmlと GAS Webアプリdao-proposals.htmlに.attachment-linkボタン(緑系・📄プレフィックス)を追加。Apps Script の制約でファイルアップロード項目はスクリプトから新規作成不可のため、DAOメニュー「企画提案書アップロード項目を追加」はフォーム編集URLと手動追加手順を案内する形(質問タイトル・許可ファイル種類・サイズ・必須オフを明示)。 -
2026-05-25
Threads予約カレンダーをコース別に色分け(
sns-gas v7 @16)sns-gas Webアプリの「📅 予約カレンダー」で、予約済みチップを「じぶんをつくる」=緑(#0a8a4a)・「ともにつくる」=紫(#6a4caf)・前回失敗=赤(#cc0000)に色分けして識別可能に。
Calendar.gsの byDay バケットにcourseフィールドを追加し、チップ生成時にコース別CSSクラス(cal-chip--tomoni)を付与。グリッド上部に凡例(緑●じぶん/紫●ともに/赤●前回失敗)を表示。紫は cocola-site のpage-hero--violet(tomoniカテゴリーバナー)と整合。 -
2026-05-25
Threads自動投稿に定型句2行を自動付与・手動起案フォームを追加(
sns-gas v6 @15)全Threads投稿の末尾に COCoLa の定型句2行(
🌱 COCoLaはともにまちをつくる(行政に声を届けたい)仲間を募集中+サイトURLhttps://you0810jmsdf.github.io/cocola-site/)を自動付与。GeneratePost.gsに_ensureSignoff関数を実装しsaveDraftで必ず通すことで、Claude 生成・手動起案の両ルートで漏れなく付与(冪等で二重付与なし)。Claude 生成プロンプトには「本文は380字以内(定型句約80字+ハッシュタグが自動追加されるため)」を明記。あわせてCode.gsに?action=manual_postの「✍️ 起案」フォーム(コース選択+本文テキストエリア+500字カウンタ)を追加し、自分で書いた投稿文も既存の予約投稿スケジュール(5分毎のrunScheduledPosts)に流せるようにした。 -
2026-05-25
「ともにつくる」カテゴリにThreads発信枠を追加・CiDAO関連5本を登録(
categories/tomoni/index.html+data/threads-tomoni.json+sns-gas)「ともにつくる」カテゴリページ末尾に「自分をつくる」と同形式のTHREADS発信欄を新設。CiDAO・市民参加・vTaiwan・印西市の地域自治をテーマにした5本(2026-05-25〜05-29 投稿予定)を
data/threads-tomoni.jsonに初期登録。urlがnullの行は「📝 投稿予定」バッジ付きで表示し、Threads投稿後にURLを記入するとリンク化される設計。あわせて COCoLa-SNS-PostManager GAS(projects/cocola/sns-gas)をコース制(じぶん/ともに)に拡張:GeneratePost.gsの SYSTEM_PROMPT・トピック・必須ハッシュタグをコース別に分岐、Keywords.gs・FetchWebReferences.gsをコース別キャッシュ対応、Setup.gsに 8:00 jibun / 8:10 tomoni の毎日生成トリガーと週次fetchトリガーを追加、Code.gsにコース切替UI・コースフィルタ・コースバッジを追加。 -
2026-05-24
クリエイターズマップに最新登録通知バナーを追加(
creators-map)「+ 掲載登録する」ボタンの上に「最新登録: YYYY/MM/DD ××さん(N日前)」を表示するバナーを実装。クリエイターズマップでいつ・誰が新しく登録されたか一目で分かるように。GAS の
getCreators()にtimestampフィールドを追加し、フロント側で最新エントリを抽出して表示。タイムスタンプが無いデータでは非表示にフォールバック。 -
2026-05-22
TOPICS一覧で日時が過去のイベントを非表示(GAS
buildHtmlv278)TOPページの「最近のTOPICS一覧」において、開催日時がJST当日深夜0時より前のイベントを自動で非表示にした。
buildHtml()内でparseEventDate()を用いて日時をパースし、過去日時のものは一覧から除外する。日時が未設定の場合は従来通り表示維持。 -
2026-05-22
TOP通知欄を「🔔 今週のCOCoLa」枠でグループ化(
index.html.notice-panel追加)入退会・情報更新・DAO提案・FreeFree新着・だんご通信の各通知バーが増えてきたため、角丸の枠(
.notice-panel)でまとめてグループ化。セクションタイトル「🔔 今週のCOCoLa」を先頭に表示。いずれかのバーが表示されたとき JS で枠ごと表示し、全バー非表示時は枠も非表示のまま。 -
2026-05-22
TOPページにだんご通信リンク・更新通知バーを追加(
index.htmlナビ・.dango-bar・JS)TOPページのナビゲーションに「だんご通信」リンクを追加し、
./dangotsusin/へ直接遷移できるようにした。また、dangotsusin/data.jsonの最新エントリの日付が7日以内の場合、入退会・DAO提案等と並ぶ通知バーエリアに「📰 だんご通信」として件名と日付を表示する.dango-barを追加した。同じ日付の重複は1件にまとめて表示する。 -
2026-05-22
だんご通信アーカイブページを新設(
dangotsusin/index.html追加・GASDangoTsusin.gs追加・doGetにmode=dangotsusin分岐追加)印西市市民活動支援センターから毎月代表宛に届くメールマガジン「だんご通信」をメンバー全員がサイト上で閲覧できるよう、新規ページ
dangotsusin/index.htmlを追加。GAS 側ではDangoTsusin.gsを新規作成し、cocola.project@gmail.comの Gmail からinzai.activity@machikatsu.co.jp発信メールを全件取得、添付ファイルは Google Drive「だんご通信」フォルダに自動保存・公開リンク化し、doGet?mode=dangotsusinでJSON配信。フロントエンドはGASエンドポイントをfetchして日付・件名のカード一覧を表示し、クリックでモーダル(本文+添付ファイルリンク)を開く構成。アクセス制限なし(全員公開)。CacheServiceで1時間キャッシュして負荷を軽減。 -
2026-05-20
Threads 事前プレビューメールに広報いんざい掲載イベントが0件表示されるバグを修正(
threads-daily-post.gs.jsisCNT_()に「広報いんざい」情報元の特例判定を追加 +CNT_AREASに「北総」を追加 / GAS v341 デプロイ)発見の経緯:毎日18時に送信される翌日投稿プレビューメールで「明日のイベントはシートに登録されていません」と表示されたが、実際には2026年5月21日(木)の「運転技能(北総自動車学校)」「健康体操(高齢者就労支援センター)」など複数の広報いんざい掲載イベントがシートに存在していた。「情報元が広報いんざいなら含めるべきでは」という運営者の指摘で調査開始。
根本原因:Threads投稿対象の絞り込みはisCNT_()関数(千葉ニュータウン関連判定)が行う。この関数はevents/index.htmlの_isCNT()と同一ロジックで、判定対象をタイトル(t)・場所(l)・説明(desc)の3フィールドに限定し、s(情報元)フィールドを意図的に除外していた。除外理由はコメントにも明記:「印西市公式サイトが拾った市外イベントを印西扱いしないため」。しかし「北総自動車学校」「高齢者就労支援センター」は場所名にCNTキーワード(千葉ニュータウン・印西市・いんざい等)を一切含まないため、isCNT_()がfalseを返し除外されていた。
修正方針の検討(3案):(A)isCNT_()に「ev.sが広報いんざいを含む場合は即true」の特例を追加、(B)CNT_AREASに「北総」を追加、(C)sフィールド全体をhayに含める(除外ルールの全撤廃)。案Cは「市外イベント混入」という元々の懸念が戻るため採用せず、AとBを組み合わせて対応。広報いんざいは印西市の公報誌であり掲載イベントは市内確定のため、特例として情報元からの判定を許容することは合理的と判断した。
修正①:isCNT_()の先頭にif ((ev.s || '').indexOf('広報いんざい') !== -1) return true;を追加。sフィールドの値が「広報いんざい」または「広報いんざい4月号」等の月付き表記でも部分一致で対応できる。
修正②:CNT_AREASに'北総'を追加。「北総自動車学校」等の施設名を場所キーワードとしてマッチさせる。
デプロイ:clasp push --force→clasp deploy --deploymentId AKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1 -d "広報いんざいCNT判定追加・北総CNT_AREAS追加"にて v341 としてデプロイ完了。次回18時のsendEveningPreview()実行から広報いんざい掲載イベントがプレビューメールに反映される。 -
2026-05-19
data/threads-jibun.jsonから サンプルエントリを削除(posts[1]のhook=ここに Threads 投稿の冒頭フックを記入します(サンプル)。、url=https://www.threads.net/@your_account/post/xxxxxxxxxxx)背景:同日先行で実装・動作検証成功した「Threads 自動投稿パイプライン → 「自分をつくる」カテゴリ実績への自動反映機能」の動作検証残課題(α)として残置していた、
data/threads-jibun.json内の初期サンプルエントリ(posts[1]、date=2026-05-19、hook=ここに Threads 投稿の冒頭フックを記入します(サンプル)。、url=https://www.threads.net/@your_account/post/xxxxxxxxxxx)が、リンク切れのダミー URL(@your_account・xxxxxxxxxxx)であり、公開URL https://you0810jmsdf.github.io/cocola-site/categories/jibun/ の「Threads発信」セクションに表示され続けると訪問者が誤クリックして 404 に到達するため、運営者判断で削除を実施。処置:C:/COCoLa/cocola-site/data/threads-jibun.jsonのposts配列からposts[1](サンプルエントリ)を削除し、posts[0](実投稿エントリ:hook=「今ここに集中しよう」と言われるたび、少し疲れた経験はないだろうか。、url=https://www.threads.com/@cocola_project/post/DYg_FHRkqsY)のみを保持する形に整形。JSON 構造(_comment・postsキー)は不変。cd C:/COCoLa/cocola-site && git add data/threads-jibun.json && git commit -m "chore(threads): remove placeholder sample entry from threads-jibun.json" && git push origin mainで main ブランチへ反映。確認:(a)data/threads-jibun.jsonのposts配列が 1 件(実投稿エントリのみ)になっていることを Edit 後の状態で確認。(b) GitHub Pages 自動デプロイ完了後、公開URL https://you0810jmsdf.github.io/cocola-site/categories/jibun/ の「Threads発信」セクションからサンプル行が消えていることを目視確認予定(数分要)。結論:(i) リンク切れ URL を公開サイトから除去できた、(ii) 「Threads発信」セクションは今後append_jibun_post()経由でのみ追記される(手動編集を伴わない運用へ完全移行)、(iii) 動作検証残課題(α)をクローズ。不変点:approve_server.py本体ロジック・append_jibun_post()の実装・threads-jibun.jsonスキーマ(_comment+postsキー)・posts[0]の実投稿エントリ・GitHub Pages デプロイ設定・COCoLa_ApproveServerタスクスケジューラ設定は不変。 -
2026-05-19
Threads 自動投稿パイプライン → 「自分をつくる」カテゴリ実績への 自動反映機能を実投稿で動作検証成功(旧
approve_server.pyプロセス 3 件(PID 12124・6096・11572)を停止 → 新プロセス(PID 13132)起動 → 既投稿 permalink を Threads Graph API で取得 → ワンショットスクリプトでappend_jibun_post()直接呼出 →cocola-site/data/threads-jibun.json先頭追記+自動 git push 完遂)背景:同日先行で実装した「Threads 自動投稿パイプライン → サイト実績自動反映機能」(
approve_server.pyのappend_jibun_post()、承認=公開と同時に#じぶんをつくる付き投稿をdata/threads-jibun.json先頭に追記+ git push する機能)について、運営者から「試しに一つ投稿文を作って承認してみたい」「#じぶんをつくる付き本番投稿で動作確認したい」という要望が発生し、実投稿による動作検証を実施。検証中に「承認は通り Threads 投稿は成功するがthreads-jibun.jsonが更新されない」という不具合に遭遇したが、原因究明と修復まで完了した。原因:approve_server.pyは Windows タスクスケジューラ(COCoLa_ApproveServer、ログオン時起動、start_approve_server.vbs経由)で常駐起動しているが、Python プロセスは起動時にメモリへロードしたコードで動き続けるため、ソースファイルを更新しただけでは反映されない。Get-CimInstance Win32_Process -Filter "Name='python.exe'"で 3つの古い approve_server プロセス(PID 12124 起動 2026/05/18 11:51:06/PID 6096 起動 2026/05/18 11:51:08/PID 11572 起動 2026/05/19 07:58:04)がappend_jibun_post実装前の旧コードを実行中であることを確認。処置(3択合意:A 案を採用):(A) 古いサーバー停止 → 新サーバー起動 → ワンショットスクリプトでappend_jibun_post()を直接呼び出して既投稿分を後追い反映、(B) 古いサーバー停止 → 新サーバー起動のみ(既投稿分は手動でthreads-jibun.json編集)、(C) 古いサーバーは放置 → 次回投稿から新コードで動作(既投稿分は何もしない)の3択で運営者が A を選択。実行手順:(1)Stop-Process -Id 12124,6096,11572 -Forceで旧プロセス3件を強制停止。(2)Start-Process -FilePath "python" -ArgumentList "C:/COCoLa/projects/cocola/sns/approve_server.py" -WindowStyle Hiddenで新プロセス起動(PID 13132、起動時刻 2026/05/19 18:39:45)。Get-NetTCPConnection -LocalPort 8080でOwningProcess=13132の LISTENING を確認。(3) permalink 取得用ワンショットfetch_latest_post.py:Meta Graph APIhttps://graph.threads.net/v1.0/{user_id}/threads?fields=id,permalink,text,timestamp&limit=3へrequests.get(...)。.envからCOCOLA_THREADS_USER_ID・COCOLA_THREADS_ACCESS_TOKENを読み込み、最新投稿としてid=17920568676142267、timestamp=2026-05-19T09:35:12+0000、permalink=https://www.threads.com/@cocola_project/post/DYg_FHRkqsYを取得(投稿本文に#じぶんをつくる含有を確認)。(4) JSON追記用ワンショットoneshot_append_jibun.py:sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")で cp932 UnicodeEncodeError 回避 →sys.path.insert(0, "C:/COCoLa/projects/cocola/sns")→from approve_server import append_jibun_post→text(投稿全文)とurl=https://www.threads.com/@cocola_project/post/DYg_FHRkqsYを渡して呼出 → 戻り値ok=True、msg=JSON追記+push成功(commit: chore(threads): add jibun post 2026-05-19)。(5)append_jibun_post()内部でdata/threads-jibun.jsonのposts配列先頭に{"date": "2026-05-19", "hook": "「今ここに集中しよう」と言われるたび、少し疲れた経験はないだろうか。", "url": "https://www.threads.com/@cocola_project/post/DYg_FHRkqsY"}をinsert(0, ...)で挿入 →git add data/threads-jibun.json→git commit -m "chore(threads): add jibun post 2026-05-19"→git pull --rebase origin main→git push origin mainがcwd=C:/COCoLa/cocola-siteで順次成功。(6) ワンショット2ファイルの掃除:Remove-Item C:/COCoLa/projects/cocola/sns/fetch_latest_post.py, C:/COCoLa/projects/cocola/sns/oneshot_append_jibun.pyで削除。確認:(a)cocola-site/data/threads-jibun.jsonのposts配列先頭に新エントリ(date=2026-05-19、hook=「今ここに集中しよう」と言われるたび、少し疲れた経験はないだろうか。、url=https://www.threads.com/@cocola_project/post/DYg_FHRkqsY)が正しく挿入されていることを Read で確認。既存サンプルエントリ(hook=ここに Threads 投稿の冒頭フックを記入します(サンプル)。)はposts[1]に残存(別タスクで削除予定)。(b) git push 成功= GitHub Pages の自動デプロイで https://you0810jmsdf.github.io/cocola-site/categories/jibun/ の活動実績カード内「Threads発信」セクションに新エントリ反映予定(GitHub Pages の反映には数分要する)。結論:(i)append_jibun_post()関数自体は完全に動作することを実投稿データで証明、(ii) Threads Graph API による permalink 取得も正常動作、(iii) ワンショットスクリプトでの後追い反映パターンも有効な復旧手段として確立、(iv) 次回以降の運用では新 PID 13132 のサーバーが承認時に自動でappend_jibun_post()を実行するため手動介入不要。教訓・運用上の注意:(I)approve_server.pyのコード修正後は 必ず Python プロセスを再起動する(タスクスケジューラ経由の常駐は再起動なしで反映されない)。(II)Get-CimInstance Win32_Processで起動時刻ベースに古いプロセスを特定する手法は今後も再利用可能。(III) Windows PowerShell の cp932 出力エンコーディング問題はsys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")で回避可能。(IV) Threads Graph API の permalink フィールドはコンテナ作成直後ではなく publish 後に GET できる(5秒待機後)。残課題:(α)threads-jibun.jsonのposts[1]に残るサンプルエントリ「https://www.threads.net/@your_account/post/xxxxxxxxxxx」の削除(リンク切れのため運営者判断で別途実施)、(β) 旧 PID 6096・12124 が 2 重起動していた件の根本原因調査(タスクスケジューラの「複数インスタンス可」設定が悪さした可能性、start_approve_server.vbs側で多重起動防止のロックファイルチェックを追加すべきか)、(γ) ワンショットでの後追い反映機能をapprove_server.py自身に/admin/reflect?post_id=...のような管理エンドポイントとして組み込むかの検討、の3点を継続課題として残置。不変点:approve_server.py本体ロジック・append_jibun_post()の実装・post_threads.pyの Threads Graph API シーケンス・data/threads-jibun.jsonスキーマ・GitHub Pages デプロイ設定・start_approve_server.vbs/COCoLa_ApproveServerタスクスケジューラ設定は不変。.env内COCOLA_THREADS_ACCESS_TOKEN/COCOLA_THREADS_USER_IDも不変(再発行・ローテーション無し)。 -
2026-05-19
Threads 自動投稿パイプラインに「自分をつくる」カテゴリ実績への 自動反映機能を統合(
C:\COCoLa\projects\cocola\sns\post_threads.py+C:\COCoLa\projects\cocola\sns\approve_server.py、承認=公開と同時にcocola-site/data/threads-jibun.jsonへ追記し自動 git push)背景:同日先行で追加した「https://you0810jmsdf.github.io/cocola-site/categories/jibun/ の活動実績カード内 Threads 投稿リンク」は手動 JSON 更新方式(運用者が Threads 投稿のたびに
data/threads-jibun.jsonを編集して git push)で構築済みだったが、運営者から「本来なら自動投稿と同時に実績反映したい、それは無理なのか?」「スレッズのURLを入れたら自動で実績に反映されるI/Fがほしい」という要望が発生。既存の Threads 自動投稿パイプライン(メール承認 →approve_server.py(localhost:8080)→post_threads.py経由で Threads Graph API へ投稿)に対して「#じぶんをつくるハッシュタグを含む投稿は 承認=公開成功と同時にthreads-jibun.json先頭への追記+cocola-siteリポジトリへの git push を自動実行する」フローを内部統合した。採用方式(3択合意):(a) 判定基準 =#じぶんをつくるハッシュタグ(投稿本文へのin検査)/(b) permalink 取得 = Threads Graph API(GET /v1.0/{post_id}?fields=permalink)/(c) git push 失敗時のハンドリング = 投稿成功扱い・push 失敗のみ警告表示(Threads 公開はロールバック不可なので push 失敗で投稿全体を失敗扱いにはしない)。処置1(post_threads.py改修):(1-a) 新規関数fetch_permalink(token, post_id) -> strを追加。https://graph.threads.net/v1.0/{post_id}?fields=permalink&access_token={token}へ GET しres.json().get("permalink", "")を返却。timeout=30。失敗時は呼び出し元で空文字フォールバック。(1-b)post(text)の戻り値型をstrからtuple[str, str]に変更し(post_id, permalink)を返却。(1-c) ステップ表示を [1/2][2/2] から [1/3][2/3][3/3] に更新(コンテナ作成 → 5秒待機 → 投稿 → permalink 取得)。permalink 取得失敗時は[WARN] permalink取得失敗: {e}のログを出し permalink="" で継続。処置2(approve_server.py改修):(2-a) 定数追加:SITE_DIR = Path("C:/COCoLa/cocola-site")、JIBUN_JSON = SITE_DIR / "data" / "threads-jibun.json"。(2-b) 新規関数extract_hook(text: str, max_len: int = 50) -> str:投稿本文の最初の改行までを優先抽出し、max_len(既定50文字)を超える場合は切り詰めて末尾に…を付与。threads-jibun.jsonのhookフィールド用フォーマッタ。(2-c) 新規関数append_jibun_post(text: str, url: str) -> tuple[bool, str]:①JIBUN_JSONをjson.loads(read_text(encoding="utf-8"))で読み、posts配列の 先頭に{"date": datetime.now().strftime("%Y-%m-%d"), "hook": extract_hook(text), "url": url}をinsert(0, ...)で挿入しjson.dumps(data, ensure_ascii=False, indent=2)で書き戻し(UTF-8)。②subprocess.run(cwd=str(SITE_DIR), capture_output=True, text=True, timeout=60)でgit add data/threads-jibun.json→git commit -m "chore(threads): add jibun post YYYY-MM-DD"→git pull --rebase origin main→git push origin mainを順次実行。各 step でcheck=True。subprocess.CalledProcessError時はstderr先頭300文字を含むメッセージで(False, "git 失敗: ...")を返却、JSON更新自体の失敗は(False, "JSON更新失敗: ...")。成功時は(True, "JSON追記+push成功(commit: ...)")。(2-d)/approve分岐の投稿成功時処理を改修:post_id, permalink = post_threads.post(text)で permalink を受け取り、if "#じぶんをつくる" in text:のときのみsite_url = permalink or f"https://www.threads.net/@cocola_project/post/{post_id}"(permalink 失敗時は手組み URL でフォールバック)でappend_jibun_post(text, site_url)を呼出。結果ok, msgを承認画面 HTML に表示:成功時は✅ サイト実績にも反映しました(小さなグレー注釈で commit 情報)、失敗時は⚠️ サイト実績への反映に失敗(手動pushが必要)+ 黄色背景の<pre>でエラー詳細を表示。Threads 投稿自体の成功表示・元投稿本文の<pre>表示・https://www.threads.com/@cocola_projectへのリンクは従来通り維持。運用フロー(自動化後):(i) Threads 投稿草稿がdrafts/*.jsonに生成される → (ii) 運営者のメールに承認リンクが届く → (iii) 承認リンクhttp://localhost:8080/approve?token=...をクリック → (iv)approve_server.pyがpost_threads.post(text)で Threads Graph API に投稿し permalink を取得 → (v) 投稿本文に#じぶんをつくるが含まれる場合のみappend_jibun_postがdata/threads-jibun.jsonを更新しcocola-siteに自動 git push → (vi) GitHub Pages の自動デプロイで数分以内に https://you0810jmsdf.github.io/cocola-site/categories/jibun/ の活動実績カード内 Threads 発信セクションに新着投稿が反映される。確認:(a)python -c "import ast; ast.parse(open('approve_server.py').read())"で Python 構文チェック OK。(b) Windows タスクスケジューラCOCoLa_ApproveServer(ログオン時起動、start_approve_server.vbs経由)で常駐するapprove_server.pyは次回再起動時に新ロジック反映(手動再起動でも可)。(c) 実投稿時の動作検証は次回#じぶんをつくる付き Threads 投稿で実施予定。不変点:post_threads.create_container/publish_containerの Threads Graph API シーケンス(media_type=TEXT、5秒待機)、approve_server.pyの/keywords//keywords/save//keywords/fetch//cancel各ハンドラ、DRAFTS_DIR/KEYWORDS_PATH/SNS_DIR/PORT=8080、BaseHTTPRequestHandlerベースの構成、HTML レスポンスのレイアウト・スタイルは不変。cocola-site/data/threads-jibun.jsonのスキーマ({_comment, posts: [{date, hook, url}, ...]})も不変。手動追記したい場合は従来通り直接 JSON 編集+ push も可能。残課題:(I) git push 失敗時に承認サーバー側で再試行キューに乗せるロジック(現状は警告のみ)、(II) 他カテゴリ(mono/machi/tsunagari/shoku/tomoni)への横展開(data/threads-{cat}.json+ ハッシュタグマッピングテーブル化)、(III) permalink 取得失敗時に Threads 公式 URL 形式https://www.threads.net/@cocola_project/post/{post_id}をフォールバック使用しているが Threads の正規ドメインはwww.threads.comに移行中のため将来的なリンク切れ可能性、の3点を継続課題として残置。 -
2026-05-19
「自分をつくる」カテゴリページに Threads 投稿リンク掲載機能を追加(
cocola-site/categories/jibun/index.html+cocola-site/data/threads-jibun.json新規)背景:運営者が「自分をつくる」をテーマに Threads 発信を継続中で、その投稿を該当カテゴリページ
https://you0810jmsdf.github.io/cocola-site/categories/jibun/に「日付+冒頭フックの文字+リンク」の最小フォーマットで掲示したい要望が発生。採用方式:手動JSON更新(運用負荷最小化のため Threads 公式API・公式embed は採用せず、JSON1ファイルへの追記+git push のみで反映される静的JSONドリブン方式)。範囲は当面「自分をつくる」専用。掲載位置は既存の「このカテゴリの活動実績」(topics-embed-card) カード内部に統合(同カードのtopics-embed-card__actionsの直下に Threads セクションを差し込み、見出しを<p class="eyebrow">Threads発信</p>+<h4>「自分をつくる」関連の Threads 投稿</h4>として活動実績カードの一部に位置づけ)。処置:(1)data/threads-jibun.json新規作成:{ "_comment": "「自分をつくる」関連の Threads 投稿リンク集。手動で追記する。新しい投稿ほど上に書く。date は YYYY-MM-DD、hook は投稿冒頭の40〜60文字程度。", "posts": [ { "date": "2026-05-19", "hook": "ここに Threads 投稿の冒頭フックを記入します(サンプル)。", "url": "https://www.threads.net/@your_account/post/xxxxxxxxxxx" } ] }形式。新しい投稿ほど配列先頭に追記する運用。dateはYYYY-MM-DD、hookは投稿冒頭の40〜60文字程度、urlは Threads 投稿のパーマリンク。(2)categories/jibun/index.html修正:既存topics-embed-card(data-cat-key="self"data-topics-mode="category")内部のtopics-embed-card__actions直下に<div class="threads-feed" id="threads-feed" hidden>を新設。子要素として eyebrow ラベル「Threads発信」、<h4 class="threads-feed__title">「自分をつくる」関連の Threads 投稿</h4>、リード文「日々の学びや小さな挑戦の発信です。タップすると Threads の投稿が開きます。」、空の<ul class="threads-feed__list" id="threads-feed-list"></ul>を配置。直後にローカル<style>で.threads-feed(活動実績iframe との境界用border-top:1px dashed #e6dfd1+margin-top:1.25rem+padding-top:1.25rem)/.threads-feed__title/.threads-feed__lead/.threads-feed__list(フラットなカード型リスト、border:1px solid #e6dfd1、border-radius:12px、background:#fff、hover でわずかに浮く)/.threads-feed__date(color:#8a7a5c、font-variant-numeric:tabular-nums)/.threads-feed__hook(font-weight:600)を定義。続く<script>でfetch('../../data/threads-jibun.json', { cache: 'no-store' })→ JSON取得成功+postsが配列+非空 のときのみ<li><a target="_blank" rel="noreferrer noopener"><span.threads-feed__date><span.threads-feed__hook></a></li>をforEachで生成し、最後にfeed.hidden = falseでセクション全体を表示。投稿0件・fetch失敗時はセクション自体がhiddenのままで何も表示しない設計(管理画面類似のフォールバック)。運用:新しい Threads 投稿のたびにdata/threads-jibun.jsonのposts配列の先頭に{ "date": "YYYY-MM-DD", "hook": "冒頭フック…", "url": "https://www.threads.net/@…/post/…" }を追記して git push するだけ。HTML/CSS/JS は無修正。確認:https://you0810jmsdf.github.io/cocola-site/categories/jibun/ を開き、活動実績カード内部に「Threads発信」セクションが点線区切りで表示されること、リンクをクリックで Threads 投稿が別タブで開くこと、現在のサンプル1件(2026-05-19)が日付+フック文字列の体裁で並んでいることを目視確認。不変点:topics-embed-card(data-cat-key="self"data-topics-mode="category")のtopics_webappiframe・data-topics-link・topics-embed-card__note・既存 CSS(styles.css)・page-hero--pink・category-nav・detail-grid・photo-panel・theme-list・signal-list・topics-embed-card__header・app-links.js・category-topics.js・page-tracker.js・site-config.jsの各既存機能は不変。他カテゴリ(mono/machi/tsunagari/shoku/tomoni)のindex.htmlは無修正。拡張余地:他カテゴリへの横展開はdata/threads-{cat}.json+ 同カテゴリindex.htmlのtopics-embed-card内部に同等ブロックを追加すれば可能(当面は jibun 専用)。 -
2026-05-19
DAO提案ゴーストエイリアス除去(
cocola_topics_clasp_sync_20260416_175648GAS v178 @337dao-points.jsのseedDaoAliases_から「ゆう→ゆうさん」削除 + 一回限り修復関数fixGhostYuuAlias_追加・実行)事象:COCoLa DAO 提案
P0123(タイトル「【期限6/5】ココハレまつり…」、カテゴリ「つながりをつくる」、提案者「ゆう」、2026/05/19 11:36:08 登録)とP0198(同提案者「ゆう」)がスプレッドシート上で「ステータス=保留・公開=FALSE」のまま投票画面に出ない一方、同提案者「ゆう」のP0199のみ「投票中・公開=TRUE」で正常表示されるという食い違いが発生。サイト管理画面https://you0810jmsdf.github.io/cocola-site/dao/admin.htmlおよび公開 DAO 投票ページhttps://you0810jmsdf.github.io/cocola-site/dao/でP0123・P0198が非表示。根因:cocola_topics_clasp_sync_20260416_175648/dao-points.jsのseedDaoAliases_関数が初期データとして['ゆう', 'ゆうさん', '初期候補: 敬称ゆれ対策']行をdao_aliasesシートにシードしており、メンバー名「ゆう」が DAO 投票処理(loadDaoAliasMap_/normalizeMemberName_)で強制的に「ゆうさん」へ正規化されていた。実メンバーDBに「ゆうさん」が存在しないケースで DAO マッチが失敗し、提案のステータス昇格(保留→投票中)と公開フラグ(FALSE→TRUE)が阻止されていた。P0199のみ正常だったのは、登録タイミングでdao_aliasesシートのキャッシュ更新前にマッチ判定が走った僅差によるもの(後発のP0198・P0123は確実に正規化を経由)。処置:(1)seedDaoAliases_から該当行削除:dao-points.js内でsheet.getRange(2, 1, 6, DAO_ALIAS_HEADERS.length).setValues([...6行...])から「ゆう→ゆうさん」行を物理削除しgetRange(2, 1, 5, DAO_ALIAS_HEADERS.length).setValues([...5行...])へ縮小。残存5行は['ゆみちゃん','ゆみ','初期候補: 2026-04-13移行メモより']/['Yasu','Yasutaka','初期候補: 2026-04-13移行メモより']/['やすたか','Yasutaka','初期候補: 表記ゆれ対策']/['ひこ','ひこさん','初期候補: 敬称ゆれ対策']/['つるちゃん','つるちゃん','初期候補: 明示登録']。(2) 一回限り修復関数fixGhostYuuAlias_追加:dao-points.js末尾に新規追加。SpreadsheetApp.getActiveSpreadsheet().getSheetByName('dao_aliases')からalias === 'ゆう'かつcanonical === 'ゆうさん'の行を全件削除(既存シードがすでに展開済みのスプレッドシートをseedDaoAliases_のif (sheet.getLastRow() > 1) return;ガードが再シードしないため、コード修正だけでは既存ゴースト行は消えない問題への対応)。(3) デプロイ:clasp push --force→clasp deploy --deploymentId AKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1 -d "v178 ゴーストエイリアス除去"実行成功(v178 @337)。(4) 修復関数の手動実行:エディタhttps://script.google.com/d/1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B/editからdao-points.jsを開きfixGhostYuuAlias_を実行。実行ログ「row=2 alias="ゆう" canonical="ゆうさん" を削除しました。削除件数=1」を確認。確認:(a) スプレッドシート1Xma1V92uNPTcXmj1cDNzU0jePcxAtTR_4vEF2ZXRgdoのdao_aliasesタブで row=2 が物理削除され、残行がゆみちゃん/Yasu/やすたか/ひこ/つるちゃんの5件であることを目視確認。(b)P0123の列構成(A:提案ID / B:記録日時 / C:タイトル / D:カテゴリ / E:理由 / F:必要なもの / G:提案者「ゆう」/ H:ステータス「保留」/ I:公開「FALSE」)が正常で列ズレ無しと再確認(前回の「列ズレ判定」は撤回)。残課題:(i)P0198・P0199が同一提案の重複である件、(ii)P0123提案者の「いと/ゆみ/ゆう」表記の最終的な書換方針、(iii)P0198の「保留・公開=FALSE」をどの方法で「投票中・公開=TRUE」に手動修復するか、の3点は別作業として継続。不変点:固定デプロイIDAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1、Script ID1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B、スプレッドシートID1Xma1V92uNPTcXmj1cDNzU0jePcxAtTR_4vEF2ZXRgdo、メンバー統計API、triggerDaoSiteUpdate_/pushDaoDataToGithub_/normalizeMemberName_/stripHonorific_/ensureDaoAliasSheet_/loadDaoAliasMap_、CacheService 60秒キャッシュ、SHA-256 投票者秘匿化、admin UI、past判定(JST境界)等の既存機能は不変。教訓:初期シードに登録する正規化ルールは「短い別名が一般名と衝突する」ケースを避ける。メンバー名正規化は「正規候補が一意でない場合は何もしない(恒等変換)」を原則とすべき。 -
2026-05-19
DAO提案用 GitHub Fine-grained PAT 差し替えの追加対応:第3のGAS(
cocola-siteGAS)の Script PropertiesGITHUB_PAT更新漏れを修復 +index.htmlハードコード期限「2026-05-19」→「2027-05-19」修正 + 認証情報台帳に「cocola-site GAS」追記同日先行対応で
cocola_topics_clasp_sync_20260416_175648GAS とcocola-dao-gas2GAS の Script PropertiesGITHUB_PATを新PAT(次回失効 2027-05-19)へ差し替え済だったが、サイト管理画面https://you0810jmsdf.github.io/cocola-site/dao/admin.htmlの「DAOデータ」ボタン押下時に HTTP 401 が継続発生。真因:「DAOデータ」ボタンはindex.htmlL481-504 のtriggerWorkflow('update-dao-data.yml','s2')がhttps://script.google.com/macros/s/AKfycbycw2FBvcm34mS9R8SUNg28KscGqqGjR1zjz3hnLYq8ckgKCZObYaC9kbMs8R2SGXgC/exec?mode=triggerWorkflow&workflow=update-dao-data.ymlを叩く構造で、この受け口は 第3のGAS = cocola-site GAS(Script ID1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B、エディタhttps://script.google.com/d/1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B/edit)に存在。先行対応では cocola_topics と cocola-dao-gas2 の2GASしか更新しておらず、cocola-site GAS の Script PropertiesGITHUB_PATは旧失効PATのままだった。さらにcocola-site/index.htmlL159 にハードコードされた期限表示「PAT有効期限: 2026-05-19」も旧期限のままで、運用者が現在期限を誤認する状態だった。処置:(1) cocola-site GAS Script Properties 更新:エディタhttps://script.google.com/d/1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B/editの「プロジェクトの設定」→「スクリプト プロパティ」でGITHUB_PATの値を新PAT(OneDrive 保全部C:\Users\nsfactory\OneDrive\レザークラフト\保全部\.envL64COCOLA_DAO_GITHUB_PATの値)に上書き保存。(2)index.htmlL159 修正:<p style="font-size:.75rem;color:#999;margin:4px 0 0">※ 通常は5分ごと自動更新。PAT有効期限: 2026-05-19</p>→<p style="font-size:.75rem;color:#999;margin:4px 0 0">※ 通常は5分ごと自動更新。PAT有効期限: 2027-05-19</p>。(3) 認証情報台帳更新:C:\Users\nsfactory\OneDrive\レザークラフト\保全部\認証情報台帳.md#19 行の格納先列に「cocola-site GAS Script Properties (GITHUB_PAT)」を追記し、同一PATを保持するGASが3つある(cocola_topics_clasp_sync_20260416_175648 / cocola-dao-gas2 / cocola-site)構造を明記。次回失効時の更新漏れ防止策として運用ノートに「PAT更新時は3GAS全てを必ず更新」を追加。確認:(a)https://you0810jmsdf.github.io/cocola-site/dao/admin.html上で「DAOデータ」ボタン押下 → HTTP 401 が解消し「✓ 起動しました(約1分後に反映)」表示。(b)update-dao-data.ymlワークフローがworkflow_dispatch経由で起動されdao/data.jsonが再生成されること。(c) 管理画面下部の「PAT有効期限」表示が 2027-05-19 に更新されていること。不変点:cocola-site GAS のデプロイIDAKfycbycw2FBvcm34mS9R8SUNg28KscGqqGjR1zjz3hnLYq8ckgKCZObYaC9kbMs8R2SGXgC、Script ID、triggerWorkflowモードハンドラ・pushDaoDataToGithub_等のロジック、固定デプロイID、公開URL、DAO投票・メンバー管理・Threads 自動投稿の各機能は不変。再発防止:GITHUB_PAT を共有する GAS は 3 プロジェクトある(cocola_topics_clasp_sync / cocola-dao-gas2 / cocola-site)。次回失効 2027-05-19 前後の更新作業時は 3GAS 全ての Script Properties を必ず更新。台帳 #19 行の「格納先」列に3GAS明記済。 -
2026-05-19
DAO提案用 GitHub Fine-grained PAT を再発行・差し替え(旧PAT 2026-05-19 失効に伴う
cocola_topicsGAS Script PropertiesGITHUB_PAT更新 + 保全部3ファイル+メモリ2ファイル同期)サイト管理画面
https://you0810jmsdf.github.io/cocola-site/dao/admin.htmlでDAO提案登録時に「DAOデータ HTTP 401」エラーが発生(画面表示「PAT有効期限: 2026-05-19」)。cocola_topics_clasp_sync_20260416_175648/dao-points.jsのtriggerDaoSiteUpdate_()がPropertiesService.getScriptProperties().getProperty('GITHUB_PAT')で取得してhttps://api.github.com/repos/you0810jmsdf/cocola-site/actions/workflows/update-dao-data.yml/dispatchesに POST する際の認証トークンが本日(2026-05-19)失効したことが原因。処置:(1) 新PAT 発行:GitHubhttps://github.com/settings/personal-access-tokens/newで Fine-grained PAT を発行。Resource owner:you0810jmsdf/ Repository access: Only select repositories →cocola-siteのみ / Permissions: Actions: Read and write+Contents: Read and write(最小権限。workflow_dispatchトリガーとdao/data.json書き戻しに必要)/ Expiration: 1年(次回失効 2027-05-19)。(2) GAS Script Properties 更新:cocola_topics GAS(Script ID1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B、エディタhttps://script.google.com/d/1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B/edit)の「プロジェクトの設定」→「スクリプト プロパティ」で既存キーGITHUB_PATの値を新PAT へ上書き保存(キー名は変更なし、値のみ更新)。(3) 保全部 3ファイル更新:C:\Users\nsfactory\OneDrive\レザークラフト\保全部\.envにCOCOLA_DAO_GITHUB_PATエントリを追加(取得日 2026-05-19・スコープ・格納先・有効期限を明示するコメントブロック付き)、C:\Users\nsfactory\OneDrive\レザークラフト\保全部\認証情報台帳.mdに #19 行を新規追加(最終更新 2026-05-19・更新履歴行も追記)、C:\Users\nsfactory\OneDrive\レザークラフト\経営戦略本部\保全幕僚_引き継ぎ書.mdの管理対象表に「GitHub (COCoLa DAO) / Fine-grained PAT / cocola_topics GAS → cocola-site workflow_dispatch(DAO data.json 更新) / 保全部\.env + GAS Script Properties / 2027-05-19」行を追加。(4) メモリ 2ファイル更新:memory/feedback_dao_proposal_safety.mdL331 の「GITHUB_PAT が 2026-05-19 に失効」警告を取消線+「✅ 2026-05-19 に失効発生・新PAT で再発行差し替え完了(次回失効 2027-05-19)」表記に書き換え、memory/MEMORY.md該当行末尾の「GITHUB_PAT 2026-05-19 失効注意」を「GITHUB_PAT 2026-05-19 再発行済(次回失効 2027-05-19)」に更新。確認:GAS Script Properties 反映後、サイト管理画面「DAOデータ」ボタン再クリックで HTTP 401 が解消、update-dao-data.ymlワークフローがworkflow_dispatch経由で起動されdao/data.jsonが再生成されることを目視確認。不変点:旧PAT・新PAT ともキー名は GAS 側GITHUB_PAT/保全部 .env 側COCOLA_DAO_GITHUB_PATで固定。スコープ・対象リポジトリ・GAS Script Properties キー名・triggerDaoSiteUpdate_()のロジック・固定デプロイID・公開URL・投票者秘匿化(SHA-256)・mode=jsonCacheService 60秒キャッシュ等の既存機能は不変。運用注意:次回失効 2027-05-19。保全幕僚の「認証情報有効期限確認」毎月1日タスクで残30日以内アラート対象として継続監視。 -
2026-05-18
Health check ワークフロー(
.github/workflows/health-check.yml)のghCLI コール 9 箇所に--repo ${{ github.repository }}を付与し、毎朝 10:00 JST 自動実行のクラッシュを修正cocola-site/.github/workflows/health-check.ymlのghCLI 呼び出し全 9 箇所(gh run list×3/gh label create/gh issue list×2/gh issue create/gh issue comment/gh issue close)に--repo ${{ github.repository }}を追加し、ジョブ実行時のリポジトリ自動判定失敗による exit code 1 を解消。事象:2026-05-18 1:00 UTC(JST 10:00)のHealth check #23が Fetch workflow run history ステップでfailed to determine base repo: needs a repositoryを出して落ち、その後の集計・Issue 連携も巻き添えで中断していた。原因:本ワークフローは GAS 疎通確認のみを目的とするためactions/checkout@v4を意図的に省いており、ワーキングディレクトリ配下に.git/が存在しない。ghCLI はカレントディレクトリの git remote または--repo引数のいずれかからリポジトリを解決する仕様のため、両方欠落していたことで「ベースリポジトリを決定できない」エラーになっていた。処置:(1) Fetch workflow run history ステップの 3 件のgh run list --workflow=...に--repo ${{ github.repository }}を付与。(2) Report failure via GitHub Issue ステップのgh label create/gh issue list/gh issue comment/gh issue create4 件に同フラグを付与。(3) Auto-close resolved Issue ステップのgh issue list/gh issue close2 件に同フラグを付与。合計 9 箇所すべてで「対象リポジトリはyou0810jmsdf/cocola-site」が明示される状態に。確認:修正コミットab2cb12をmainに push 後、gh workflow run health-check.yml -R you0810jmsdf/cocola-siteで手動トリガー → Run 26015120450 が 9 ステップすべて成功("conclusion":"success")で完了。副次的に検知された別問題:本ワークフローが正常動作したことで、update-dao-data.yml/update-members-data.yml/update-events-data.yml3 本の最終成功が 200 分以上前(30 分閾値超過)であることが Issue #2 として自動起票された。これは「GitHub Actions schedule は不安定」という既知の運用上の問題で、本タスクのスコープ外。手動トリガー(gh workflow run update-dao-data.yml等)で都度反映する運用は維持。影響範囲:監視ワークフロー自体の安定化のみ。GAS エンドポイント・data.json生成パス・固定デプロイ ID・公開 URL・DAO 投票・メンバー管理・Threads 自動投稿の各機能は不変。 -
2026-05-17
印西エリア判定(
isCNT_/_isCNT)の対象から情報元サイト名ev.sを除外し、市外イベント混入を修正(cocola_topics v334 @334threads-daily-post.gs.js+cocola-site/events/index.html)cocola_topics_clasp_sync_20260416_175648/threads-daily-post.gs.jsのisCNT_(line 289-300)とcocola-site/events/index.htmlの_isCNT(line 282-304)の千葉ニュータウン判定ロジックから 情報元サイト名ev.sフィールドを判定対象hayから除外し、v334 @334 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ。事象:2026-05-17 7:13 JST の Threads 自動投稿で「松戸 オープンフォレスト 📍市内18ヶ所の森」が印西エリアイベントとして混入。シート上で場所を松戸に修正したにもかかわらず投稿に出続けていた。原因:4段階判定(CNT_OFFICIAL → CNT_AREAS → CNT_EXCLUDE → CNT_CITY)の入力hayは[ev.t, ev.l, ev.desc, ev.s].join(' ')でタイトル・場所・説明・情報元サイト名を連結していた。ev.sの値が「いんざい市公式サイト(画像)」となっていたため、CNT_CITY 段階の'いんざい'キーワードに毎回マッチ → 場所が「松戸」でも印西扱いされ、Threads 投稿とevents/index.htmlの「印西エリア」フィルタ両方で混入していた。シート上の場所列のみ変更してもev.s(ソース列)は不変のため、ユーザー修正が反映されない構造的バグ。処置:両ファイルのhay構築からev.sを除外し[ev.t, ev.l, ev.desc].join(' ')に変更(コメントに「いんざい市公式サイトが拾った市外イベントを印西扱いしないため」と理由を明記)。これによりタイトル・場所・説明の3フィールドのみで CNT 判定。影響範囲:(a) Threads 自動投稿(7時postTodayEventsToThreads/ 18時sendEveningPreview)、(b)events/index.htmlの「印西エリア」絞り込み、いずれも市外イベントを排除。CNT_OFFICIAL / CNT_AREAS / CNT_EXCLUDE / CNT_CITY のキーワード定義・順序・データ仕様・投票・DAO・固定デプロイIDは不変。確認:明日以降の Threads 自動投稿とhttps://you0810jmsdf.github.io/cocola-site/events/の印西エリアフィルタで松戸オープンフォレストが表示されないこと。既に公開済みの 2026-05-17 投稿の手動削除は Threads アプリで実施が必要。 -
2026-05-17
Threads 毎朝7時イベント投稿の時刻表示破綻を修正(cocola_topics v333
threads-daily-post.gs.jslpad_(-1)バグ)cocola_topics_clasp_sync_20260416_175648/threads-daily-post.gs.jsの時刻文字列組立条件を修正し、v333 @333 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ。事象:Threads@cocola_projectの毎朝7時自動投稿(2026-05-17 7:13 JST 公開)で「松戸 オープンフォレスト 📍市内18ヶ所の森 0-1:0-1〜」「ハンドメイド ポップアップCharm 📍イオンモール千葉ニュータウン 1階 メイン通路 0-1:0-1〜」のように時刻表示が壊れる事象が継続発生(2026-05-16 投稿でも同症状を確認)。原因:events/data.jsonでは「時刻未設定」イベントをh: -1, mi: -1センチネル値で表現しているが、buildTodayEventListMessage_(line 192-200)の条件if (typeof ev.h === 'number' && typeof ev.mi === 'number')は-1も'number'として通過してしまい、続くlpad_(ev.h) + ':' + lpad_(ev.mi)でlpad_(n < 10 ? '0' + n : '' + n、line 299-301)が'0' + (-1)という文字列連結を実行 →'0-1'文字列を生成し、最終的に' 0-1:0-1〜'として出力されていた。ピザ教室などh=10, mi=0が正常設定されているイベントは表示正常。処置:line 194 の条件にev.h >= 0 && ev.mi >= 0を追加し、-1を含む負値を弾いてelse分岐(ev.d文字列からHH:MMを正規表現抽出するフォールバック、抽出不可ならtimeStr = ''で時刻非表示)にルーティング。これにより時刻未設定イベントは時刻表記なしで「・タイトル 📍場所」形式で表示される。影響範囲:Threads 自動投稿(7時postTodayEventsToThreads/ 18時sendEveningPreview)の両方が修正対象。投票・DAO・データ仕様には不変。残対応:既に公開済みの 2026-05-17 / 2026-05-16 の壊れた Threads 投稿2件は Threads Graph API の DELETE 権限スコープがアプリに付与されていない({"error":{"code":10,"message":"Application does not have permission for this action"}})ため、ユーザー手動削除が必要([2026-05-17投稿](https://www.threads.com/@cocola_project/post/DYancGok-9E) / [2026-05-16投稿](https://www.threads.com/@cocola_project/post/DYYCss9mBXW))。明日以降の自動投稿から正常表示。投票者秘匿化・LockService 化・固定デプロイIDは不変。 -
2026-05-17
DAOポイント Ledger 付与ロジックを
LockServiceで排他制御化+日次 audit を自動実行(cocola_topics v175 @332withDaoLedgerLock_/dailyDaoLedgerAudit_/installDailyDaoLedgerAuditTrigger_)cocola_topics_clasp_sync_20260416_175648/dao-points.jsに DAO_LEDGER シートの付与クリティカルセクションを保護するwithDaoLedgerLock_(LockService.getScriptLock().waitLock(30000)、release をfinallyで保証)を新規追加し、v175 @332 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ。本日(2026-05-16)先行実施の v171-v174(DAO投票シート 708行物理削除+Ledger 監査・補正で ゆう 358→357pt 補正完了)の残課題3件((A) 重複行流入経路の継続監視、(B) 根本対策として LockService 排他制御化、(C) 補正結果の継続観測)に対する根治対応。(1) LockService 排他制御化(3か所):(a)appendDaoPointEntryIfMissing_(dao-points.jsline 1602)──hasLedgerEventKey_チェック +addDaoPoints_+ledgerSheet.appendRowの一連をwithDaoLedgerLock_コールバック内に封入し、同秒競合時も後発実行はロック解放まで最大 30 秒待機 → 重複検知ですり抜け不可能に。(b)awardDaoVoteParticipationPoint_(line 1619)── DAO投票参加ポイント単発付与を同様に保護。awarded戻り値で条件付きrefreshDaoMemberStatuses呼出を維持し I/O コストを抑制。(c)preSeedVoteParticipationPoints_(line 1670〜)── DAO投票画面起動時のバルク事前付与ループ内もwithDaoLedgerLock_で保護。ループのi + 2をvar rowIndex = i + 2;に切り出してクロージャ参照の最終値バグを回避。(2) 日次 audit 自動実行:dailyDaoLedgerAudit_(line 4659+)──auditDaoVoteParticipationDoublePoints_を呼び出し、result.dupKeys >= 1の場合のみMailApp.sendEmailで運営宛(you0810jmsdf@gmail.com)に 件名「[COCoLa DAO] Ledger 重複検出 N件」 + 監査日時・総エントリ・ユニークキー数・重複キー数・追加付与pt・重複キー詳細・対処案内(inspectDaoLedgerDuplicateRows_→fixDaoVoteParticipationDoublePointDryRun→Liveの補正フロー)を本文で通知。audit 自体が例外発生時も別件名「[COCoLa DAO] Ledger 日次監査 実行エラー」で例外内容+スタックを通知してから rethrow し、トリガーログにも残す設計。(3) トリガー設置:installDailyDaoLedgerAuditTrigger_(line 4659+)── 既存の同名 handler トリガーを全削除(多重登録防止)したうえでScriptApp.newTrigger('dailyDaoLedgerAudit_').timeBased().everyDays(1).atHour(3).create()を実行し、毎日 03:00 JST に自動実行。GAS Editorhttps://script.google.com/d/1zOZBorvfkKZAmCtJB9KDkQLXMxsTfGhUXWOdbxJ4lFLyA92Ts_gM0t7B/editからdao-points.jsのinstallDailyDaoLedgerAuditTrigger_を一度手動実行することで本トリガーが投入される(以降は自動継続)。原理:LockService.getScriptLock() は GAS プロジェクト単位のロックで、複数バッチ実行・同時 doGet 呼出・time-based trigger 並行のいずれも 1 つずつ直列化される。waitLock(30000) で 30 秒以内に他処理が完了すれば待機継続、30 秒超で例外 → ログに記録。これにより v172-v174 で観測された「hasLedgerEventKey_チェック →appendRow間の TOCTOU 競合」を物理的に排除。投票者秘匿化(SHA-256 ハッシュ化)・管理者向け投票者一覧UI・mode=jsonCacheService 60秒キャッシュ等の既存機能・URL・固定デプロイIDは不変。運用:トリガー設置以降、重複検出時のみ運営にメール通知され、空運転時は通知ゼロ(ノイズなし)。万一通知が来た場合は本文記載の手順に従いinspectDaoLedgerDuplicateRows_→fixDaoVoteParticipationDoublePointDryRun→Liveの順で補正可能。 -
2026-05-16
DAO投票参加ポイント Ledger 重複行を監査・補正(cocola_topics v172-v174
auditDaoVoteParticipationDoublePoints_/inspectDaoLedgerDuplicateRows_/fixDaoVoteParticipationDoublePoint_)cocola_topics_clasp_sync_20260416_175648/dao-points.jsに DAO 投票参加ポイント(DAO_VOTE_PARTICIPATION_POINT)の二重付与を検知・特定・補正する 3 関数を追加し、v172-v174 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ。背景:本日先行実施の v171 @328dedupeDaoVoteSheetByKey_(DAO投票シート (proposal,voter,ts) キー重複 708行物理削除)で残課題として残っていた「参加ポイント二重付与リスクの調査」を実施するため、(1) 監査:auditDaoVoteParticipationDoublePoints_(dao-points.jsline 4443、エントリポイント同名)── DAO_LEDGER シート全行をevent_key(dao-vote-participation:{proposal_id}:{voter_canonical}形式)でグルーピングし、グループ内に 2 件以上ある event_key を「二重付与候補」として列挙、各メンバーの超過 pt も算出。(2) 原因特定:inspectDaoLedgerDuplicateRows_(line 4611、エントリポイント同名)── 指定 event_key に紐づく Ledger 全行をrow/timestamp/delta/reason/note込みで可視化し、同秒記録の TOCTOU 競合 (hasLedgerEventKey_→appendRow間で別エントリ混入) を確認可能に。(3) 補正:fixDaoVoteParticipationDoublePoint_(line 4535、エントリポイントfixDaoVoteParticipationDoublePointDryRun()/fixDaoVoteParticipationDoublePointLive())── 指定 event_key の重複行のうち最古行のみ残し、残りを物理削除 + 該当メンバーの DAOポイント残高を-1 pt × 削除件数で補正。実行手順:監査 → 検出されたdao-vote-participation:proposal_xxx:ゆう(提案「焼き鳥交流会」、行 233/234 の同秒記録 2 件、Ledger 重複 1 件、ゆう超過 +1 pt)をinspectDaoLedgerDuplicateRows_で精査 → DryRun で削除対象 1 行・ポイント補正 -1 を確認しユーザー承認 → Live で行 234 を物理削除しゆうの DAOポイントを 358 → 357 に補正。補正後監査結果:Ledger 行数 398 → 397、ゆう DAOポイント 358 → 357、重複 event_key 数 0、超過 pt 合計 0。原因:バッチ実行内の同秒競合(hasLedgerEventKey_でのチェック →appendRow実行の間に並列バッチの別エントリが割り込み、重複検知をすり抜けて 2 件目が追加された)。影響範囲:参加ポイント二重付与は焼き鳥交流会/ゆうの 1 件のみで、他の DAO提案・他メンバーには影響なし。公開data.json側のメンバー DAOポイント表示は次回更新で 357 に反映。gh workflow run update-dao-data.yml -R you0810jmsdf/cocola-siteでupdate-dao-dataワークフローを手動トリガーし、公開https://you0810jmsdf.github.io/cocola-site/dao/data.jsonおよびhttps://you0810jmsdf.github.io/cocola-site/dao/に反映。GitHub Actions の schedule は不安定なため手動トリガーを必須としている運用ルールに準拠。投票者秘匿化(SHA-256 ハッシュ化)・管理者向け投票者一覧UI・mode=jsonCacheService 60秒キャッシュ等の既存機能・URL・固定デプロイIDは不変。残課題:(A) 重複行流入経路の継続監視(GAS time-trigger によるauditDaoVoteParticipationDoublePoints_定期実行を検討)、(B) 根本対策として参加ポイント付与ロジックをLockServiceで排他制御化(hasLedgerEventKey_+appendRowをクリティカルセクションで囲い同秒競合を物理的に防止)。 -
2026-05-16
DAO投票シート (proposal,voter,ts) キー重複 708行を物理削除(cocola_topics v171 @328
dedupeDaoVoteSheetByKey_/ バックアップDAO投票_backup_2026-05-16)cocola_topics_clasp_sync_20260416_175648/dao-points.jsにdedupeDaoVoteSheetByKey_(エントリポイントdedupeDaoVoteSheetByKeyDryRun()/dedupeDaoVoteSheetByKeyLive())を追加し、v171 @328 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ。背景:DAO 管理ページhttps://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/exec?admin=1の投票者一覧で提案 P0016「野草ハンター」に「成田由美」が「賛成」を同一タイムスタンプで 15件以上重複表示する事象を起点にauditDaoVoteDuplicates_で全件監査を実施したところ、DAO投票シート(DAO_CONFIG.voteSheetName='DAO投票'、列構成DAO_VOTE_HEADERS11列)の 809行中 708行(87%)が (proposal_id, voter, timestamp) 複合キーでの重複行であることが判明(つる +302、ゆう +207、ゆみ +68、空 +52、まさみ +45、成田由美 +34 等が複数提案にまたがり大量重複)。本日先行実施の v255 @324purgeDaoVoteDuplicates_(同memo複製 54件)・v257 @326purgeEmptyMemoBatchDuplicates_(memo 空のバッチ書込痕跡 866行)でカバーしきれなかった「memo は異なるが (proposal_id, voter, timestamp) が完全一致する実投票重複」を対象とする最終クリーンアップ。判定ロジックはauditDaoVoteDuplicates_と完全同一(voterCols/proposalCols/timestampColsから voter/pid/ts を取得し、ts はUtilities.formatDate(v, 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss')で正規化、3つすべて揃った行のみグルーピング対象とし、各グループ内で最小 row index 行のみを残して残りを削除)。DryRun(GASエディタからdao-points.jsのdedupeDaoVoteSheetByKeyDryRunを実行)で 削除対象 708件・残存予定 101行を事前確認しユーザー承認を取得。Live 実行(dedupeDaoVoteSheetByKeyLive)で 708件を DAO投票_backup_2026-05-16 シートへ全列退避(archived_at/archived_reason='dedupe-by-(proposal,voter,ts) key'/original_row3列を先頭付与)した後、行番号降順(rowsDesc)でsheet.deleteRow()実行することで row index ずれを回避し物理削除完了(809 → 101 データ行)。完了後gh workflow run update-dao-data.yml -R you0810jmsdf/cocola-siteでupdate-dao-dataワークフロー(Runhttps://github.com/you0810jmsdf/cocola-site/actions/runs/25962388289)を手動トリガーし、公開https://you0810jmsdf.github.io/cocola-site/dao/data.jsonおよびhttps://you0810jmsdf.github.io/cocola-site/dao/に反映。GitHub Actions の schedule は不安定なため手動トリガーを必須としている運用ルールに準拠。重要:公開data.json側の集計はlatestVotes[proposalId][canonicalName]による上書きパターンで生成されているため票数自体は重複の影響を受けていなかった(最後の1票で上書きされる仕様)。本処理はあくまでシート上の物理重複の掃除と管理ページ表示の正常化が目的。誤削除時はDAO投票_backup_2026-05-16シートのoriginal_row列を参照して復元可能。投票者秘匿化(SHA-256 ハッシュ化)・管理者向け投票者一覧UI・mode=jsonCacheService 60秒キャッシュ等の既存機能・URL・固定デプロイIDは不変。残課題:参加ポイント二重付与リスク(hasDaoVoteParticipationPoint_が重複行で二重カウントしていた可能性)の調査、および重複行流入経路の特定(v254 @320〜@323 の memo 上書き根治で新規発生はないと想定されるが要監視)。 -
2026-05-16
DAO投票シート memo空のバッチ書込痕跡 866行を物理削除(cocola_topics v257 @326
purgeEmptyMemoBatchDuplicates_/ バックアップDAO投票_backup_2026-05-16_emptymemo)cocola_topics_clasp_sync_20260416_175648/dao-points.jsにpurgeEmptyMemoBatchDuplicates_(エントリポイントpurgeEmptyMemoBatchDuplicatesDryRun()/purgeEmptyMemoBatchDuplicatesLive())を追加し、v257 @326 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ。本日先行実施の「同memo複製 54件物理削除」(v255 @324purgeDaoVoteDuplicates_)ではスコープ外としていた memo 空行 1534件に対し、疑似 keyvoter|pid|yyyy-MM-dd HH:mmでグルーピングし、安全弁として「実投票者あり(voter列に値あり)またはpidあり」のグループは丸ごとスキップ(実投票履歴を絶対に削らない)。スキップグループは 21グループ・合計約934件(例:まさみ|P0027|2026-05-01 09:5544件、つる|P0020|2026-04-19 19:5733件、成田由美|P0016|2026-05-01 07:3333件 等)として個別精査用に保留。削除対象は「voter 空 かつ pid 空」かつグループ内で最古行以外の 866件(row 178〜1658)。Live 実行(GASエディタからdao-points.jsのpurgeEmptyMemoBatchDuplicatesLive、実行時間 4分38秒)で 866行をDAO投票_backup_2026-05-16_emptymemoシートへ全列退避(先頭にarchived_at/archived_reason='empty-memo batch-dup purge (keep oldest, no-voter no-pid only)'/original_row3列を付与、行 2〜867 に追記)した後、行番号降順(rowsDesc)でsheet.deleteRow()実行することで row index ずれを回避し物理削除完了。完了後gh workflow run update-dao-data.yml -R you0810jmsdf/cocola-siteでupdate-dao-dataワークフロー(Runhttps://github.com/you0810jmsdf/cocola-site/actions/runs/25961950410)を手動トリガーし、公開https://you0810jmsdf.github.io/cocola-site/dao/data.jsonおよびhttps://you0810jmsdf.github.io/cocola-site/dao/に反映。GitHub Actions の schedule は不安定なため手動トリガーを必須としている運用ルールに準拠。誤削除時はDAO投票_backup_2026-05-16_emptymemoシートのoriginal_row列を参照して復元可能。なお同 deployId への上書きデプロイのため URL・固定デプロイID・投票者秘匿化(SHA-256 ハッシュ化)・管理者向け投票者一覧UI・mode=jsonCacheService 60秒キャッシュ等の既存機能は不変。残課題:スキップした 21グループ(合計約934件)の実投票者重複については日付・時刻パターンから「同一バッチ書込」由来の可能性が高いが、票数集計に直結するため別タスクで個別精査予定。また v255 @324 以降に流入したと思われる新規空memo行(48件程度)の流入経路特定も別タスクで対応。 -
2026-05-16
DAO投票シート 同memo複製 54件を物理削除(cocola_topics v255 @324
purgeDaoVoteDuplicates_/ バックアップDAO投票_backup_2026-05-16_dup)cocola_topics_clasp_sync_20260416_175648/dao-points.jsのpurgeDaoVoteDuplicates_を「同 memo 複製の最古以外を削除」ロジックに全面書き換え(v255 @324 として GHA live deployIdAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ上書きデプロイ)。背景:A案修正(collectDaoVotes_/collectDaoVotesFast_/collectSingleDaoVote_の memo 上書き根治、v254 @320〜@323)により以降の新規投票は memo 重複が発生しなくなったが、修正前に蓄積した DAO投票シート(DAO_CONFIG.voteSheetName = 'DAO投票'、列構成DAO_VOTE_HEADERS11列、memo は col 11)上の既存重複は残置されたままだったため、本処理で物理掃除を実施。エントリポイントはpurgeDaoVoteDuplicatesDryRun()とpurgeDaoVoteDuplicatesLive()の2関数。DryRun(GASエディタからdao-points.jsのpurgeDaoVoteDuplicatesDryRunを実行)で 全データ 1681行・memo 空行 1534件・memo 付き 147件・ユニーク memo 93件・重複グループ 27件・削除対象 54件(先頭5件 row 49/90/50/91/51、末尾5件 row 114/74/115/77/78)を事前確認したうえでユーザー承認を取得。Live 実行(purgeDaoVoteDuplicatesLive)で 54件をDAO投票_backup_2026-05-16_dupシートへ全列退避(先頭にarchived_at/archived_reason='dup-memo-purge (keep oldest)'/original_row3列を付与)した後、行番号降順(rowsDesc)でsheet.deleteRow()実行することで row index ずれを回避。groups[memo]でグルーピングし各 group の最小 idx 行のみを残し、残りの全行を targets として削除する単純ロジックのため誤判定リスクは低い。memo 空行 1534件は dedup key(memo)消失によりグルーピング不能のためスコープ外(別途調査推奨)。掃除後、gh workflow run update-dao-data.yml -R you0810jmsdf/cocola-siteでupdate-dao-dataワークフロー(Runhttps://github.com/you0810jmsdf/cocola-site/actions/runs/25961539440)を手動トリガーし、公開https://you0810jmsdf.github.io/cocola-site/dao/data.jsonおよびhttps://you0810jmsdf.github.io/cocola-site/dao/に反映。GitHub Actions の schedule は不安定なため手動トリガーを必須としている運用ルールに準拠。なお v255 @324 はバックアップ+退避+削除の安全弁を備えるため、誤削除時はDAO投票_backup_2026-05-16_dupシートのoriginal_row列を参照して復元可能。投票者秘匿化(SHA-256 ハッシュ化)・管理者向け投票者一覧UI・mode=jsonCacheService 60秒キャッシュ等の既存機能・URL・固定デプロイIDは不変。 -
2026-05-16
DAO 終了済み提案 21件を物理削除(管理ページ ?admin=1 / cocola_topics v24 @58
purgeAllZeroVoteSoftDeletedProposals_経由)DAO管理ページ
https://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/exec?admin=1の「終了済み提案の物理削除」セクションから、累積していた ステータス=「終了」かつ投票数=0 の DAO提案 21件 をハード削除。直前に DryRun(?mode=purgeZeroVotesDryRun)で対象が 21件であることを確認したうえで、安全策としてスプレッドシート COCoLa_TOPICSイベント登録 を COCoLa_TOPICSイベント登録_backup_2026-05-16(https://docs.google.com/spreadsheets/d/1GhQykghkr_L_7wtOXVWPSn_ncOdVrTTQs_tBy0Tog0I/edit)として「ファイル」→「コピーを作成」で完全バックアップ取得。その後「物理削除を実行」ボタンで Live 実行(?mode=purgeZeroVotesLive)。purgeAllZeroVoteSoftDeletedProposals_(v24 @58)の安全弁により 票数 > 0 の行は絶対に物理削除されず、削除前に全行がdao_proposals_archiveシートへarchived_reason='soft-delete-zero-vote-purge (status=終了, vote=0)'付きで自動退避される設計のため、誤削除時はdao_proposals_archiveから復元可能。削除実行後 DryRun を再度叩き{ok:true, count:0, dryRun:true, victims:[]}を確認、対象消化を保証。続けてgh workflow run update-dao-data.yml -R you0810jmsdf/cocola-siteでupdate-dao-dataワークフロー(Run 25960329960)を手動トリガーし、公開https://you0810jmsdf.github.io/cocola-site/dao/data.jsonに反映。GitHub Actions の schedule は不安定なため手動トリガーを必須としている運用ルールに準拠。公開ページhttps://you0810jmsdf.github.io/cocola-site/dao/側の提案一覧から終了済み 21件が完全に消える。投票者秘匿化(v24 SHA-256 ハッシュ化)・管理者向け投票者一覧UI(v25 @68)・mode=jsonCacheService 60秒キャッシュ(v26 @69)等の既存機能・URLは不変。 -
2026-05-16
DAO 管理ページ(?admin=1)の投票者一覧・管理UI表示不具合を根本修正(サーバー側admin判定/配信HTMLでの
https://破壊回避/管理パネル配置改善/cocola-dao-gas2 @73)v27 @70 で exec 絶対URL ハードコードを行ったにもかかわらず
https://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/exec?admin=1で開いた管理ページに統計カウンタ・物理削除パネル・投票者一覧パネルがいずれも表示されない問題に対応。原因は 4 つ複合:(1) クライアント側でlocation.search.includes('admin=1')により admin 判定していたが、HtmlServiceiframe サンドボックスではlocation.searchも*.googleusercontent.com/userCodeAppPanel側に解決されるため常に false になっていた。(2)HtmlService配信時に JavaScript テンプレートリテラル内のhttps://連続文字列が壊れて URL が破損していた。(3) 管理パネルがdocument.body.appendChildでページ末尾に追加されていたため、提案一覧の下に隠れて見つけづらかった。(4) 上記によりsetupAdminPanel/setupAdminVotersPanelがそもそも実行されなかった。修正内容:(A)cocola-dao-gas2/dao-points.jsのdoGet(e)でテンプレート評価前にtemplate.isDaoAdmin = Boolean(e && e.parameter && e.parameter.admin === '1')をサーバー側で評価し、(B)cocola-dao-gas2/dao-proposals.html冒頭でconst IS_DAO_ADMIN = <?!= isDaoAdmin ? 'true' : 'false' ?>;とconst DAO_GAS_EXEC_URL = 'https:' + '/' + '/script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/exec';(文字列連結でhttps://破壊を回避)として埋め込み、(C)mountAdminPanel(panel)ヘルパで.toolbarを含む section の直前にinsertBefore配置(提案一覧の手前に出る)、(D)setupAdminPanel/setupAdminVotersPanel冒頭でif (!IS_DAO_ADMIN) return;によりサーバー側判定を尊重、(E) すべてのfetch(?mode=json/?mode=purgeZeroVotesDryRun|Live/?mode=adminVoters)をDAO_GAS_EXEC_URL + '?mode=...'形式に統一。Grep検証:IS_DAO_ADMIN/DAO_GAS_EXEC_URL/mountAdminPanel/template.isDaoAdminすべて反映確認、配信HTMLにconst IS_DAO_ADMIN = true;出力確認、?mode=jsonで10件・?mode=adminVoters正常応答確認。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ @73 として上書きデプロイ完了。URL・固定デプロイID不変、GitHub Actions の data.json 取得経路も影響なし。なお公開ページの投票者秘匿化方針は不変(公開data.jsonのvotersは SHA-256 ハッシュ配列のまま、実名は?admin=1管理ページからのみ閲覧可能、投票者本人にだけ見える「〇〇さん 投票済み」バッジも維持)。※codex 作業 -
2026-05-16
DAO 管理ページ(?admin=1)の統計0/提案一覧「読み込みに時間がかかっています」問題を解消(fetch URL を exec 絶対URL にハードコード/cocola-dao-gas2 v27 @70)
GAS exec URL
https://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/exec?admin=1で開いた管理ページにおいて、上部の「進行中/承認済/否決/合計」の4ステータスカウンタが全て 0 のまま、提案一覧は「提案データの読み込みに時間がかかっています。少し待ってから再読み込みしてください。」のメッセージのまま反映されない問題に対応。原因はcocola-dao-gas2/dao-proposals.htmlのクライアント側 JavaScript がfetch(`${location.pathname}?mode=json`)のようにテンプレートリテラルで相対URLを組み立てていたこと。HtmlServiceがページをiframeサンドボックス内で配信するため、location.pathnameがscript.google.com/macros/s/.../execではなく*.googleusercontent.com/userCodeAppPanelに解決されてしまい、fetchが GAS のdoGetに届かないままタイムアウト相当のローディング表示が続いていた。dao-proposals.htmlの以下 3 箇所を固定デプロイID付き exec 絶対URLhttps://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/execに書き換え:(1) L715 メインデータ取得fetch(... /exec?mode=json)、(2) L768 物理削除パネル内callPurge(mode, pw)のfetch(... /exec?mode=${mode}&pw=...)(modeはpurgeZeroVotesDryRun/purgeZeroVotesLive)、(3) L916 v25 で追加した投票者一覧パネル内fetch(... /exec?mode=adminVoters&pw=...)。修正後Grepでlocation.pathname残骸ゼロ件・絶対URL 3箇所すべて存在を確認。clasp push --force(3 files:dao-proposals.html / dao-points.js / appsscript.json、17:35:45 完了)→ 固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへclasp deploy -i ... -d "v27 ..."で v27 @70 として上書きデプロイ完了。URLおよび固定デプロイIDは不変、GitHub Actions の data.json 取得経路も影響なし。なおこの問題は?admin=1管理ページ側のみで発生しており、GitHub Pages 公開 LPhttps://you0810jmsdf.github.io/cocola-site/dao/は静的data.json(GitHub Actions が?mode=jsonを curl して定期更新)を直接読むため影響を受けていなかった。 -
2026-05-16
DAO 提案一覧の読み込み遅延を解消(mode=json に CacheService 60秒キャッシュ/cocola-dao-gas2 v26 @69)
DAO投票ページ
https://you0810jmsdf.github.io/cocola-site/dao/および GAS exec URLhttps://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/execで「提案データの読み込みに時間がかかっています。少し待ってから再読み込みしてください。」のメッセージが頻発し、ステータスカウンタが全て 0 のまま表示される問題に対応。原因はcocola-dao-gas2/dao-points.jsの?mode=json経路(getDaoProposalPageDataJson_())が毎リクエストgetDaoProposalPageData()→refreshDaoProposalPageData_()(validateDaoProposalSchema_/repairDaoProposalResponseKeys_/normalizeLatestDaoProposalResponse_/repairDaoProposalDefaults_の4関数)を同期実行しシート全走査をかけていたため。CacheService用キーDAO_PROPOSAL_PAGE_DATA_JSONおよびclearDaoProposalPageCache_()は元から定義されていたもののcache.put()が一度も書かれておらず事実上デッドコード状態だった。getDaoProposalPageDataJson_()冒頭でCacheService.getScriptCache().get('DAO_PROPOSAL_PAGE_DATA_JSON')を確認し、HIT なら即返却、MISS のときのみ build →cache.put('DAO_PROPOSAL_PAGE_DATA_JSON', json, 60)(TTL 60秒)→ 返却するキャッシュ層を追加。投票/編集/修復系の経路は既存のclearDaoProposalPageCache_()呼び出しがあるためキャッシュは即時無効化され、最新状態の反映性は維持される。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ v26 @69 として上書きデプロイ完了。curl実測:1回目(cache miss、build 含む)19.87秒、2回目以降(cache hit)1.86秒/1.89秒(いずれも 14545 bytes 同一)で約 10倍高速化を確認。 -
2026-05-16
DAO 管理者向け投票者一覧UIを追加(?admin=1 内に実名テーブル/cocola-dao-gas2 v25 @68)
DAO投票ページの公開 JSON
https://you0810jmsdf.github.io/cocola-site/dao/data.jsonは v24 で投票者ニックネームを SHA-256 ハッシュ化して秘匿化済みのため、サイト管理者が「誰が何に投票したか」を直接確認できる経路が無くなっていた問題に対応。cocola-dao-gas2/dao-points.jsに管理者向け関数getDaoVotersForAdmin_()(DAO投票シートを記録日時昇順・提案ID昇順で全件取得しproposalId / title / voter / vote / normalized / timestampを返却)と、パスワード認証ラッパーgetDaoVotersForAdminWithAuth_(pw)(スクリプトプロパティDAO_ADMIN_PASSWORDと照合、不一致なら{ok:false, error:'パスワードが違います'})を追加。doGet(e)にmode === 'adminVoters'分岐を追加し、エンドポイントhttps://script.google.com/macros/s/AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g/exec?mode=adminVoters&pw=XXXとして公開。cocola-dao-gas2/dao-proposals.htmlの?admin=1管理セクションに「投票者一覧」緑枠パネル(setupAdminVotersPanelIIFE)を追加。パスワード入力+「投票者一覧を取得」ボタンでfetch(${location.pathname}?mode=adminVoters&pw=...)を叩き、提案ID/提案タイトル/投票者(実名)/投票内容(協力できる=緑/協力は難しい=赤/その他=黄バッジ)/記録日時 の5列テーブル(max-height:60vh, sticky header)でレンダリング。#votersFilterによる提案ID/投票者/タイトル部分一致のライブ絞り込みも実装。公開 JSON のハッシュ化(v24)はそのまま維持し、実名は ?admin=1 経由+スクリプトプロパティ一致時のみ 取得可能。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ v25 @68 として上書きデプロイ完了。 -
2026-05-16
DAO 投票者名を公開ページで秘匿化(SHA-256 ハッシュ照合方式/cocola-dao-gas2 v24 @67 + cocola-site dao/index.html)
DAO投票ページ(
https://you0810jmsdf.github.io/cocola-site/dao/)の公開 JSONhttps://you0810jmsdf.github.io/cocola-site/dao/data.jsonに含まれていた投票者ニックネーム実名(proposal.voters配列)を、SHA-256 ハッシュ値の配列に置換して秘匿化。GAS 側cocola-dao-gas2/dao-points.jsにhashDaoVoterNickname_(nickname)(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, s, Utilities.Charset.UTF_8)で hex 64桁を返却)を追加し、getDaoVotersByProposal_内で投票シート D列(投票者)を全てハッシュ化してからmap[pid]に push する方式に変更。サイト側cocola-site/dao/index.htmlはstate.nicknameHashを新設し、computeSha256Hex(text)(window.crypto.subtle.digest('SHA-256', new TextEncoder().encode(text)))とrefreshStoredNicknameHash()を追加。votersIncludeStored(proposal)をstate.nicknameHashとproposal.voters配列のハッシュ照合に書き換え、一致時のみgetStoredNickname()から実名を取り出して「✓ ◯◯さん 投票済み」バッジを維持。setStoredNickname()と初期化シーケンスからrefreshStoredNicknameHash().then(renderProposals)を呼び、ニックネーム変更時にも非同期で照合状態を更新。これにより他人の実名は公開 JSON にも localStorage にも残らず、自分が投票したかどうかだけが自分の端末で判定できる。実名確認が必要な場合はスプレッドシート1Xma1V92uNPTcXmj1cDNzU0jePcxAtTR_4vEF2ZXRgdoの DAO投票シート D列を直接参照する。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ v24 @67 として上書きデプロイ完了。 -
2026-05-16
DAO 投票送信「送信中…」長時間化への根本対策(vote 後の集計を時間トリガで非同期化/cocola-dao-gas2 v66 @66)
DAO投票ページ(
https://you0810jmsdf.github.io/cocola-site/dao/)の投票モーダルで「送信中…しばらくお待ちください」が異常に長く表示される問題への根本対策として、cocola-dao-gas2/dao-points.jsのdoGetvote 分岐内で同期実行していたprocessDaoProposalVotesFast()(30秒LockService.waitLock(30000)+投票シート正規化2回+集計+キャッシュクリアの重処理)を切り離し、ScriptApp.newTrigger('processDaoProposalVotesFastTriggered').timeBased().after(1000).create()による時間トリガキューイング方式に変更。フロントへのレスポンスは投票記録(recordDirectVote_)が完了した時点で即時返却される。新規追加したprocessDaoProposalVotesFastTriggered(e)は実行完了後にScriptApp.getProjectTriggers()からe.triggerUid一致のトリガを検索してdeleteTriggerで自身を削除し、トリガ枠(GAS制限20個)が膨らまないようクリーンアップ済み。前提として v65 で導入したrecordDirectVote_の B/D 列限定取得+setValues バッチ化はそのまま維持。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ v66 として上書きデプロイ完了。集計反映はトリガ発火後(約1秒〜数秒後)になるため、投票直後の集計反映は GitHub Actions の5分ポーリングまたは管理画面手動更新で確認する。 -
2026-05-16
DAO 投票記録の Lock タイムアウト対策(recordDirectVote_ 最適化/cocola-dao-gas2 @65)
DAO投票ページ(
https://you0810jmsdf.github.io/cocola-site/dao/)で、投票送信モーダルに「しばらく時間をおいてお試しください」エラーが発生する事象(GASLockService.waitLock(10000)の10秒タイムアウト)への根本対策として、cocola-dao-gas2/dao-points.jsのrecordDirectVote_を最適化。具体的には ①投票シート走査時にgetLastColumn()ベースの全列読み込みをやめ、B列(提案ID)と D列(投票者)のみgetRange(2, 2, n, 1).getValues()/getRange(2, 4, n, 1).getValues()で2列だけ取得するよう変更、②既存行発見時の更新をsetValue×3回(A列・E列・I列)からgetRange(rowNum, 1, 1, 5).setValues([[...]])による A〜E列一括書き込み+I列のみ単発setValueの合計2回呼び出しに削減、③ existingVote の比較は一致行発見後の単一セル読みに局所化。これにより Lock 保持期間が短縮され、同時投票時のタイムアウト発生確率を下げる。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ @65 として上書きデプロイ完了。前提として v25 @64 で導入した「投票変更(上書き)」機能・LockService.getScriptLock()による TOCTOU 対策・noteKey 重複付与防止はそのまま維持。 -
2026-05-16
DAO 投票変更(上書き)機能を追加(取消は廃止/cocola-dao-gas2 v25 @64)
DAO投票ページ(
cocola-site/dao/index.html)で、メンバーが一度投じた投票を別の選択肢に変更できるようにした。検討した4案(A:取消フォーム再送/B:固有フォーム発行/C:管理画面取消/D:変更のみ・取消し不可)のうち、P0020 承認条件「参加率20%以上」を維持するため 投票数を減らさないD案を採用。GAS 側cocola-dao-gas2/dao-points.jsのrecordDirectVote_を改修し、同じ提案ID+投票者の既存行があれば「記録日時(1列目)」「投票(5列目)」を上書きして「投票集計済(9列目)」をfalseにリセット、再集計対象に戻す方式とした。LockService.getScriptLock()による TOCTOU 対策および投票ポイント台帳のnoteKey重複付与防止は既存実装をそのまま活用。フロント側は投票済みボタンをdisabled解除して「投票を変更」ラベルに変更し、レスポンスのres.changedで通知メッセージを「投票を変更しました」「投票しました」に分岐。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ v25 @64 として上書きデプロイ完了。 -
2026-05-13
DAO「市民いいね」をリロード後も即時表示(localStorage マージで GitHub Actions 5分ラグを吸収)
これまでは押下直後にカウントが +1 されても、ページをリロードすると
dao/data.json(GitHub Actions が5分ごとに上書き更新)の古い値で画面が再描画され、最大5分間は数字が押下前に戻って見える挙動だった。cocola-site/dao/index.htmlにCOCOLA_DAO_CIVIC_LIKE_COUNTSキーで提案IDごとの最新いいね数を localStorage に保存する仕組みを追加し、applyDaoData/restoreLastDaoData経由でデータを描画する際にmergeLocalCivicLikeCounts()でローカル値とサーバ値の max を採用するよう変更。さらにstats.citizenLikesの合計値もマージ後の値で再集計するため、ヘッダーの累計表示も即時反映される。これでリロード直後も自分が押下したカウントが保持され、サーバ側が追いついた時点で自然にサーバ値が優勢になる。 -
2026-05-12
メンバースケジュール 期間登録対応(A3-α 方式:終了日入力+複数日表示/cocola_topics v200 @310)
印西市市民活動支援センターの「予約受付期間(5/1〜5/7)」のような 多日間にまたがる単発イベントを1件として登録できるよう、メンバースケジュール機能を期間対応に拡張。スプレッドシート「メンバースケジュール」に Q列「終了日」を非破壊で追加し、GAS(
schedule.gs.js)の list/add/edit/delete/get/upsertCalendar 全6関数をendDate受け渡し対応に。Googleカレンダー連携はcreateEvent(title, startDate, endDate, opts)を用いて時刻ありの多日間連続帯として1件登録する方式(A3-α)を採用し、開始日の朝〜終了日の夕方までを1イベントとして表現する。フロント(cocola-site/schedule/index.html)はモーダルに「終了日(複数日にまたがる場合のみ)」入力欄を追加、saveEvent でバリデーション(終了日は開始日以降)、リスト表示は「開始日〜M月D日」形式に拡張、過去判定を endDate 基準に変更(多日間イベントは終了日まで「現在」扱い)、カレンダーグリッドは itemMap を期間展開して期間中の各日に同一イベントを表示するよう修正。GAS は固定デプロイIDAKfycbzVs_W57Iphxcc5PHShXBNae63CKqjF5fB82tUkQwaf1vyuNWWLgtWZgglY7Qbuuft1へ v200 @310 として上書きデプロイ完了。 -
2026-05-11
DAO「竹箸つくり」系ゾンビ9件をID指定で物理削除+workflow失敗で誤検知だった件の決着(cocola-dao-gas2 v29/v30、公開data.json検証完了)
v28 で dedup を正規化キー化したが、過去に既にスプレッドシートへ書き込まれていた「竹箸つくり」系9件(P0150/P0152/P0154/P0156/P0158/P0160/P0162/P0164/P0165)は dedup ブロックの対象外で残存していたため、v29 で
purgeProposalsByIdHard_ラッパー(purgeBambooChopsticksZombiesDryRun/Live)経由でdao_proposals_archiveへ退避+物理削除を実施。直後に公開dao/data.jsonを確認するとゾンビ9件が依然表示されており「また復活した」と判断して v30 で診断関数debugDumpDaoStateV30を追加デプロイしたが、原因を切り分けたところ workflow run 25672340304(22:12 JST)が curl --max-time 30 を踏んでexit code 28(GASエンドポイントタイムアウト)で失敗しており、公開 data.json が v29 削除前のスナップショット(_generatedMs22:06)のままだったことが判明。gh workflow runで run 25672761483 を手動再投入したところ正常完了、公開側も proposals 10件・v29ゾンビ9件すべて消滅・P0025(焼き鳥交流会)保全を確認。教訓:物理削除直後は workflow を必ず手動再実行し_generatedMsの前進を確認するまで「ゾンビ復活」と判断しない。固定デプロイIDAKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7gへ v29 @63/v30 @64 として上書きデプロイ済み。 -
2026-05-11
DAO提案ゾンビ問題の構造的根治:dedup を正規化キー+archive横断スキャン化(cocola-dao-gas2 v28 @62)
v23〜v27 で個別タイトルを物理削除しても、同タイトル・別IDで再投函されると
isDuplicateRecentProposal_がタイトル完全一致比較しかしていなかったため通過してしまい、再びゾンビ提案として復活する穴が残っていた。v28 では dedup 比較を「正規化キー(空白除去+『つくり/造り → 作り』置換+小文字化)」ベースに変更し、さらにdao_proposals_archiveシートも横断スキャン対象に追加。これにより物理削除でアーカイブ済みのタイトルが再投函された場合もアーカイブ側の正規化キーがヒットして送信時点でブロックされる。実装ではnormalizeTitleForDedup_/normalizeProposerForDedup_/scanSheetForDedupKey_をモジュールトップに共通ヘルパー化し、これまでarchiveDuplicateDaoProposals_/restoreFromArchive/purgeByTitle(ソフト削除)/purgeByTitleHard(物理削除)の4箇所に重複コピーされていた正規化ロジックを単一定義に集約。今後の表記ゆれ対応も1箇所修正で済む。固定デプロイID(AKfycbxM2ybpJqfWLL-MPnOwZqeBdHjN6IQh5QB-_LubZAG-bD0x8jLkgbUn7NYRzYLFOPfj7g)へ@62として上書きデプロイ完了。 -
2026-05-11
「焼き鳥交流会」P0206 のみID指定で物理削除(cocola-dao-gas2 v27 @61)
同タイトル「焼き鳥交流会」が P0025(票=4/正規)と P0206(票=1/ID違いゾンビ/スダショウ 2026-04-19)の二重表示状態になっていたため、v25/v26 のタイトル一括ハード削除では P0025 まで巻き込まれる。v27 では
purgeProposalsByIdHard_(ids, dryRun)を新設し提案ID指定で物理削除する汎用関数を追加。ラッパーpurgeYakitoriP0206DryRun/Live経由で P0206 のみdao_proposals_archiveへ退避+物理削除し、P0025 は保全。Live実行直後にメンバーから「投票できない」報告が入ったため緊急調査したところ、公開dao/data.json側の同期前で P0206 が残ったままだったことが原因。update-dao-data.ymlを手動トリガーして同期完了(公開側 P0206 消失・proposals 18件・P0025 票=4 残存)、投票復旧確認。教訓:物理削除直後は必ず手動 workflow を回し公開 data.json と GAS を即同期させること。 -
2026-05-11
「464号線でマルシェがしたい」のタイトル一致全行を物理削除(cocola-dao-gas2 v26 @60)
v23.1 でテスト提案 P0179 をハード削除した後も「464号線でマルシェがしたい」が P0192 / P0206 と別IDで何度もゾンビ復活していたため、v25 と同じハード版(票数・公開状態を問わずタイトル一致行を全て物理削除)に切替。v26 では
purgeProposalsByTitleHard_(['464号線でマルシェがしたい'])を呼ぶラッパーpurgeMarcheOnRt464DryRun/Liveを追加。DryRun で7件確認後、Liveで P1000(票=2)・P1001・P1002・P1012・P0028・P0046・P0192(公開=true ステータス=投票中)をdao_proposals_archiveへ退避のうえ物理削除。GAS実行ログ「archived+deleted 7 rows, cache cleared」確認後、GAS の?mode=jsonエンドポイントで 464ヒット 0件、続いてupdate-dao-data.yml手動トリガーで公開dao/data.jsonからも 464 関連が消失(proposals 11件)。根因のisDuplicateRecentProposal_の dedup 透過は memory 側で 🔴 残タスクとして引き継ぎ。 -
2026-05-11
朝カフェ・竹箸作りのタイトル一致全行を物理削除(cocola-dao-gas2 v25 @59)
v23.1/v24 の対策後も、票数0で公開ページに「P0202 朝カフェ/P0200・P0198 竹箸つくり」等が再出現する現象が継続。根因は提案重複判定
isDuplicateRecentProposal_がタイトル完全一致のみで、表記ゆれ(つくり/作り/造り)や物理削除後の新ID再投稿に対して透過する穴を残していたこと。v25 では「票数・公開状態を問わずタイトル一致行を全て物理削除」する積極パージ関数purgeProposalsByTitleHard_を新設し、対象タイトル['朝カフェ', '4月朝カフェ', '竹箸作り', '竹箸つくり', '竹箸造り']用ラッパーpurgeAsacafeAndBambooDryRun/Liveを追加。タイトル正規化(空白除去・つくり/造り→作り・小文字化)を内蔵し、削除前にdao_proposals_archiveへarchived_reason: 'hard-purge by title (vote=N, pub=X, status=Y)'付きで退避。DryRunで35件確認後、票=1のP0021 4月朝カフェも含めユーザー明示指示により全件Live削除。GitHub Actionsupdate-dao-data.ymlを手動トリガーし、公開dao/data.jsonから朝カフェ/竹箸の全エントリが消失(proposals 12件)。 -
2026-05-11
DAO提案「投票0かつ終了」の汎用ハード削除UIを追加(cocola-dao-gas2 v24 @58)
これまで提案ごとに専用関数(朝カフェゾンビ用
purgeAsacafeZombiesLive、テスト提案用purgeTestProposalsLiveなど)を作って物理削除していたが、運用のたびにスクリプト追加が必要で煩雑だった。v24 では「ステータス=『終了』 かつ 投票数=0」を満たす提案行を一括で物理削除する汎用関数purgeAllZeroVoteSoftDeletedProposals_と、その doGet エンドポイント(?mode=purgeZeroVotesDryRun/?mode=purgeZeroVotesLive)を実装。dao-proposals.html?admin=1でだけ表示される管理セクションから、管理パスワード(DAO_ADMIN_PASSWORD)入力 → DryRunで対象件数確認 → ネイティブ confirm() ダイアログ → Live実行、の二段階フローで安全に呼べる。削除前にdao_proposals_archiveシートへ自動退避、票数 > 0 の行は安全弁として絶対に削除しない。GAS版数200制限に達したため旧バージョンを手動削除のうえ@58として固定デプロイIDへ上書き。 -
2026-05-11
DAO提案 朝カフェゾンビ復活の物理削除 & テスト提案 P0179 ハード削除(cocola-dao-gas2 v23.1 @57)
v21.1 で「公開列の自動 TRUE 修復」を撤廃した後も、票数 0 の古い提案(P0199 朝カフェ・P0201 4月朝カフェ)が公開ページに復活する事象が継続していたため、v23 で導入済みの
purgeAsacafeZombiesLive(タイトル一致+票数0行をアーカイブ→物理削除)を再実行し、行 193・194 をdao_proposals_archiveへ退避のうえスプレッドシートから物理削除。あわせて v23.1 @57 でテスト提案ハード削除用のpurgeTestProposalsDryRun/Liveラッパー(対象タイトル: 「464号線でマルシェがしたい」)を追加し、P0179 を物理削除。GitHub Actionsupdate-dao-data.ymlを手動トリガーして公開dao/data.jsonに反映(proposals 14→12, voting 14→12, 焼き鳥4票・竹箸つくり5票・健活5票・野草ハンター5票はそのまま保全)。なお、票数 0 行がフォーム経路から「同タイトル+新ID」で再出現する経路は別途追跡予定(取消ボタン=ソフト削除のままで残るため)。 -
2026-05-11
DAO提案アーカイブ関数の表記ゆれ対応・公開判定統一・列幅バグ修正(cocola-dao-gas2 v21.3.2 @54)
v21.1 で導入した
archiveDuplicateAndStaleDaoProposals_が「竹箸つくり/竹箸作り」のような表記ゆれを別タイトル扱いし、重複が4件残っていた問題を修正。(1) v21.3: dedup キーにタイトル正規化を導入(空白除去・つくり/造り → 作り・小文字化)し、表記ゆれ同士を同一提案として束ねる。(2) v21.3.1: アーカイブ関数の対象フィルタを「公開=TRUE のみ」厳格化(v21.1 で確立した「空欄=非公開、TRUE=公開」のセマンティクスに揃え、空欄行が drift で混入するのを防止)。(3) v21.3.2: 新規アーカイブシート作成時のヘッダ書き込みでgetRange(1,1,1,width)が 22 列だがheaders.concat(['archived_at','archived_reason'])が 24 要素となり「data has 24 but range has 22」で失敗していた件をwidth + 2に修正。Live 実行で 5 件(竹箸4件+焼き鳥1件)をdao_proposals_archiveに退避し、公開ページの重複が解消した(竹箸 5→1、焼き鳥 2→1)。 -
2026-05-11
DAO提案の「古い提案が復活する」不具合を構造的に根治(cocola-dao-gas2 v21.1 @48)
P0176等で繰り返し発生していた「管理者が公開を下ろした古い提案が、しばらくすると再び公開ページに復活する」現象を根治。真因は
repairDaoProposalDefaults_が doGet?mode=json のたびに「公開列の空欄を TRUE に自動修復」していたこと(読み取り時 defensive 補完)で、これが「手動で下ろした提案」と「単なる入力もれ」を区別できないまま全件再公開する revival 機構として働いていた。v21.1 では (1) 公開列の自動 TRUE 修復を撤廃して「空欄=非公開」「TRUE=公開」を一意化、(2) 新規フォーム送信は従来どおり即公開(公開=TRUE で挿入)を維持、(3) 重複検出を「直近60分」から「全期間 提案者+タイトル」の存在チェックに変更、(4) 既存の重複行・古いアーカイブ対象行をdao_proposals_archiveシートに退避するarchiveDuplicateAndStaleDaoProposals_関数(DryRun/Live両対応)を追加。これにより「新規提案は即公開、管理者が下ろした古い提案は二度と復活しない」が同時に成立する。 -
2026-05-10
千葉ニュータウン地区フィルタを「ホワイト+ブラックリスト」方式に再調整
events/index.html の地区判定を再調整。前回の二段階判定では市名フォールバックが効かず、印西市・白井市内のイベントの約9割が「その他」に振り分けられていた問題を修正。判定順を「①公式キーワード(千葉ニュータウン/CNT)→②CNT公式住区(中央北/原山/西の原/南山/けやき台 等)→③CNT外住区ブラックリスト(吉田・小林・印旛中央・本埜・木下・鹿黒・大森・浦部・別所・鎌苅・草深・根・神々廻 等)→④市名(印西市/白井市/小室)でCNT扱い」に変更。これにより「印西まちなか音楽祭」「ほくそう春まつり」「印西市文化ホールのコンサート」等を正しく CNT に分類しつつ、印西市域でも CNT 外(小林・吉田・本埜地区など)のイベントは「その他」に残るようにした。シミュレーション結果: 244件中 CNT 61件 (25%) / その他 183件。
-
2026-05-10
イベント一覧の千葉ニュータウン地区フィルタを精度改善
events/index.html の地区判定ロジックを刷新。従来は ['印西','白井','小室'] の単純キーワード一致で吉田・小林・印旛中央・本埜などの非CNT地区も誤って千葉ニュータウン扱いになっていた。千葉県企業局「千葉ニュータウン土地利用計画図(令和7年3月版)」を一次情報として、公式キーワード(千葉ニュータウン/CNT)即マッチ+市名(印西市/白井市/小室)が含まれる場合に限り住区名(中央北・原山・西の原・南山・けやき台 等)を照合する二段階判定に変更。文字列は NFKC 正規化して全角半角ゆれにも対応。
-
2026-05-09
Threads予約投稿の月間カレンダービューを追加(sns-gas @10)
新規 Calendar.gs を追加し、`?action=calendar` で予約済み下書きを月間グリッドで一覧できるビューを実装。各日セルに「HH:mm 投稿冒頭18文字」のチップを時刻昇順で表示し、クリックすると該当下書きの編集ページへ遷移する。前月/翌月ナビ・今日ハイライト・日曜赤/土曜青の配色・スマホ対応のレスポンシブグリッド付き。投稿候補一覧ページとトップページの両方からカレンダーへの導線を追加。
-
2026-05-09
Threads予約投稿機能を追加:日時指定で自動投稿(sns-gas @9)
投稿候補一覧の各カードに datetime-local 入力欄+「予約設定/予約解除」ボタンを追加。指定したJST日時を draft.scheduled_at に保存する。新規 SchedulePost.gs に runScheduledPosts() を実装し、5分ごとの時間トリガー(setupScheduleTrigger で登録)が scheduled_at <= 現在時刻 の下書きを自動的に Threads へ投稿し、成功した下書きは ScriptProperties から削除する。失敗時は scheduled_at をクリアし schedule_error にエラー内容を記録して再実行ループを停止する。
-
2026-05-09
Threads投稿のスマホ可読性向上:句点改行+絵文字活用(sns-gas @8)
GeneratePost.gs を改修し、投稿文の見やすさを向上。(1) プロンプトに「文章は『。』ごとに改行」「スマホ画面で読みやすい短い行」「絵文字を要所に1〜3個」のルールを追加、(2) 生成後の後処理 _postProcessText で「。」の直後に自動改行を挿入(ハッシュタグ行は対象外)。これにより、スマホで Threads を見た時に1文ごとに視線が止まりやすくなり、読みやすさが大幅に改善。
-
2026-05-09
Threads投稿フォーマット規定+キーワード保存ガード(sns-gas @7)
GeneratePost.gs を改修し、(1) Markdown強調記法 ** を投稿文から自動除去、(2) フックを「」ではなく【】で書く方針をプロンプトに明記、(3) 末尾に必ず #COCoLa #千葉ニュータウン #じぶんをつくる の3タグが入るよう生成後に自動補完。あわせて Keywords.gs に空配列ガード(空フォーム送信時は保存拒否&例外)と Logger.log を追加し、「保存したキーワードが時間経過でデフォルトに戻る」問題の原因特定を可能にした。
-
2026-05-09
Threads投稿候補一覧に「その場で生成」ボタンを追加
sns-gas Code.gs に action=fetch_and_generate / action=generate_now を追加(@6デプロイ)。投稿候補一覧の上部に「🔄 Web情報収集して生成」「✨ いま生成(既存キャッシュ使用)」の2ボタンを設置し、運営者が任意のタイミングで下書きをストックできるようにした。毎朝7時の自動生成(runDailyGenerate)と並行運用。
-
2026-05-09
TOP🔒管理モーダルにThreads運営ツールを統合
既存のTOPページ「🔒管理」ボタン(パスワード cocola2026)から開くadminOverlayモーダル内に、Threads運営ツールセクションを追加。投稿候補一覧・Web情報キャッシュ・キーワード管理の3リンクを集約し、運営管理を1か所に統合した。apps/ 一般公開ページに一時掲載した Threads リンクは取り下げ済。cocola-site/admin/index.html はURL直打ちフォールバックとして併存(noindex/nofollow)。
-
2026-05-08
TOPページ:DAO新規提案バーの重複表示を修正
GASスプレッドシート上に同一タイトルの提案が新旧IDで二重登録されており、data.jsonが1日以上古くなるとGASへフォールバックした際に最大8件(4ペア×2)が重複表示される問題を修正。index.html の renderDaoBar 関数にタイトル重複排除(Setによる先着1件)を追加し、データソース問わず同名提案は最初の1件のみ表示するよう改修。
-
2026-05-08
DAO提案:スキーマ漂流の構造的解消(v20 列名マップinsert・スキーマ正規化)
P0020投票方式変更(v18)以降、DAO_PROPOSAL_HEADERSの「賛成重み/反対重み/賛成率」とコード側の「協力重み/非協力重み/協力率」が併存し、ensureNamedColumn_が末尾に新列を追加することでシートが20+列に膨張、位置ベースsetValuesで末尾列が破壊されて公開列・回答キー列が空になっていた。v20で根本対策:①DAO_PROPOSAL_HEADERSを新列名へ統一、②insertを列名→値マップ化(insertDaoProposalRowByName_)、③回答キー欠損自動再生成、④起動時スキーマ検証ログ、⑤1回限りの移行関数migrateDaoProposalSchema_()追加(GASエディタから手動実行で旧列を新列へ統合し物理削除)。
-
2026-05-08
DAO提案:手動トリガー依存の根本解消(公開列自動修復・重複登録ガード)
cocola-dao-gas2 (v19, @37) に2件の安全装置を追加。①repairDaoProposalDefaults_ を新設し、提案行の「公開」空欄→TRUE・「ステータス」空欄→「投票中」に自動修復(getDaoProposalPageDataJson_ 経由で毎回実行)。②normalizeLatestDaoProposalResponse_ に isDuplicateRecentProposal_ ガードを追加し、同一タイトル+同一提案者が直近60分以内に登録済みの場合スキップ。P0176(団体パネル展示展)が公開=FALSE状態でサイト未表示になり、P0177-P0188 が重複作成された再発を防ぐ。GitHub Actions schedule 不安定への対策(onDaoProposalFormSubmit_ 内 triggerDaoSiteUpdate_)は既存(v18)で機能済。
-
2026-05-08
DAO投票ページ:シークレットウィンドウで提案が表示されない不具合を修正
dao/index.htmlのsetFormLink()関数に null ガード(if (!element) return;)を追加。voteForm要素がHTML上に存在しないためdocument.getElementById('voteForm')がnullを返し、applyDaoData()内でTypeErrorがスローされてrenderProposals()が実行されなかった。localStorageが空のシークレットウィンドウでのみ再現する不具合だった。
-
2026-05-08
TOPページ DAO通知バー:data.json陳腐化時のGAS直接フォールバック追加
GitHub Actionsスケジュールが一時停止しdao/data.jsonが24時間以上更新されない場合、ブラウザ側でGASエンドポイントへ直接フェッチするフォールバックをindex.htmlに追加。エラー時のcatch(() => {})をconsole.warnに変更して原因を可視化。data.jsonも手動ワークフロートリガーで最新化(generatedAt: 2026/05/08 08:33)。
-
2026-05-07
Threads自動投稿:イベントサイトURL誘導をフッターに追加
buildEventsText_()の末尾にhttps://you0810jmsdf.github.io/cocola-site/events/への固定URL誘導を追加。毎回の投稿に「↓ 詳細はこちら」としてイベントサイトへのリンクを表示する。threads-daily-post.gs.jsをv301としてデプロイ。
-
2026-05-07
Threads自動投稿:前日18時プレビューメール送信 + data.json自動更新トリガー追加
毎日18時JSTに翌日の投稿予定文をcocola.project@gmail.comへ自動メール送信するsendEveningPreview()を追加。同時にGitHub Actions(update-events-data.yml)をworkflow_dispatchでトリガーしevents/data.jsonを強制更新するtriggerDataJsonUpdate_()を実装。buildTodayEventsText_()をbuildEventsText_(offsetDays)に汎用化(0=今日、1=翌日)。threads-daily-post.gs.jsをv300としてデプロイ。⚠️ GITHUB_PAT有効期限 2026-05-19。
-
2026-05-07
Threads自動投稿:ヘッダーを「千葉イベント」に変更・印西市イベントを先頭表示
毎朝7時JST自動投稿の投稿文フォーマットを変更。ヘッダー「印西イベント」→「千葉イベント」に修正。📍印西市 を含むイベントをリスト先頭に並び替えるソートロジックを追加。threads-daily-post.gs.js を更新し v299 としてデプロイ。
-
2026-05-07
スケジュール:カレンダー変更時に schedule/data.json を即時更新する仕組みを追加
Googleカレンダーへのイベント追加・変更・削除を検知して GitHub の schedule/data.json を即時更新する installable trigger(onCalendarEventUpdated)を実装。calendar-trigger.gs.js を新規追加し、v176 として GHA live endpoint(AKfycbzVs_W...)@295 にデプロイ。GitHub Actions の schedule 待ちが不要になる。setupCalendarTrigger() を GASエディタで1回実行してトリガーを有効化する必要がある。
-
2026-05-07
DAO:提案提出時に貢献度ポイントを即時反映する仕組みを構築
DAO提案フォーム送信時にポイント処理が実行されず、メンバーページの貢献度に反映されない不具合を修正。onDaoProposalFormSubmit_ に提案者ポイント即時付与(processDaoProposalPointsFromAllRows_)と members/data.json 即時更新トリガー(triggerMemberSiteUpdate_)を追加。cocola-dao-gas2 v21 としてデプロイ済み。
-
2026-05-07
スケジュール:文字化けカレンダーイベントを非表示に修正
Googleカレンダー由来の文字化け(U+FFFD)を含むイベントがスケジュールページに表示される不具合を修正。GASのgetCalendarOnlyEvents_にフィルタを追加し、文字化けイベント12件を除外。あわせてGitHub ActionsのGASエンドポイントが古いデプロイIDを参照していた問題(修正が反映されない根本原因)を解消した。
-
2026-05-07
TOPページ:DAO新規提案通知バーを追加
直近7日以内に提出されたDAO提案をTOPページの通知バー(緑)に一覧表示する機能を追加。カテゴリー・タイトル・提案者・日付を表示し、DAO投票ページへリンク。
-
2026-05-07
DAO:提案フォーム送信時にGitHub Actions即時トリガー機能を追加
新規提案がフォームから送信された際、スプレッドシートの onFormSubmit トリガーが GitHub Actions
update-dao-data.ymlを即時発火させ、dao/data.jsonを数分以内に更新するようにしました。dao-points.jsにtriggerDaoSiteUpdate_・onDaoProposalFormSubmit_・installDaoProposalFormTrigger_を追加し、GAS メニュー「DAO運営 → 提案フォーム送信トリガーを設定」から初回登録できます(Script Properties にGITHUB_PAT要設定)。GAS 固定デプロイIDへ上書き済み(@34)。 -
2026-05-07
DAO提案/投票:「投票済み」表示をクロスデバイス対応
提案/投票 ページで、スマホで投票した提案がPCを開くと「未投票」に見える事象(その逆も含む)を修正しました。原因は「投票済み」判定がブラウザごとの
localStorage(COCOLA_DAO_VOTED_IDS)にのみ依存していたためです。GAS側でdao/data.jsonの各提案に投票者ニックネーム配列votersを追加(dao-points.jsのgetDaoVotersByProposal_)し、フロントは新しいCOCOLA_DAO_NICKNAMElocalStorage に保存したニックネームとvoters配列を照合して「投票済み」を判定するようにしました(dao/index.html)。投票モーダルのニックネーム選択肢は前回投票時の名前を自動選択します。GAS は固定デプロイIDへ上書き済み(@33)、GitHub Actions の DAO data.json 更新ワークフローを手動トリガーして公開ページに反映しました。 -
2026-05-06
DAO提案/投票:投票後に集計が反映されない問題を根本修正
提案/投票 ページで投票しても
協力重み・協力率・投票数が反映されない事象を根本修正しました。原因はdoGetの投票処理がprocessLatestDaoProposalVote(投票シートの最終行のみを集計対象とする実装)を呼んでいたため、ほぼ同時の投票や行順の前後で対象提案が取り違えられ、しかも集計エラーはtry/catchで握りつぶされていたことでした。doGetを全提案を再集計するprocessDaoProposalVotesFastに差し替え、集計エラーはvoteResult.aggregateErrorとして呼び出し元に返すよう変更しました(GAS v19 として固定デプロイIDへ上書き)。過去分はprocessDaoProposalVotesFastを一度実行して全提案を再集計し、P0066「COCoLaマスコットキャラクター募集」の「協力できる」票が反映されたことを公開 data.json で確認済みです。 -
2026-05-06
DAO提案/投票:「つる」「ゆう」の票が反映されていなかった問題を修正
提案/投票 ページの投票数が一部少なくなっていた問題を修正しました。原因は、過去のメンバー集合に「つるちゃん」「ゆうさん」が同時在籍していた時期に「つる」「ゆう」名義で投じられた8票が、別名候補の競合で ambiguous 判定となり名寄せ済み列・投票重み列が空のまま残っていたことでした。現在は「つるちゃん」「ゆうさん」がメンバーから外れて競合が解消されているため、
processDaoProposalVotesFastを再実行することで全行が再評価され、対象8票(つる: 6票 / ゆう: 2票)が自動的に名寄せされ、各提案の集計に反映されました。GitHub Actions の DAO data.json 更新ワークフローを手動トリガーして公開ページに反映済み。 -
2026-05-07
TOPページ:FreeFree新着投稿の通知バーを追加
COCoLa TOPページに、FreeFree掲示板の新着投稿(
start_dateが直近7日以内のポスター)をオレンジ系バーで表示する機能を追加しました。GAS APIへのfetchで取得し、投稿がない場合・7日以上継続中のものはバーを非表示にします。GAS側の変更は不要です。 -
2026-05-06
DAO提案/投票:公開ページに出ていた重複提案の検出ロジックを強化
提案/投票 ページに「印西市文化財活用に関するインタビュー」が同日付で P0063 / P0064 の2件表示されていた問題に対処しました。既存の重複検出(応答キーの照合)では拾いきれないケースに備えて、
dao-points.jsに「タイムスタンプ+タイトル+提案者」によるフィンガープリント重複検出(Phase 3)を追加し、GASエディタから引数なしで実行できるラッパー関数repairDuplicatedDaoProposalsLiveを追加しました。本番実行(dryRun=false)でスプレッドシートの P0064 を非公開化済み。GitHub Actions(DAO data.json 更新ワークフロー)を手動トリガーして公開ページに反映しました。 -
2026-05-05
メンバースケジュール:U+FFFD(文字化け)混入を保存前に拒否するガードを追加
メンバースケジュール 登録時に、入力欄(タイトル・場所・参加者・主催・メモ)へ U+FFFD(�)が混入していたら保存をブロックするガードを、フロント(
schedule/index.htmlのsaveEvent())と GAS(schedule.gs.jsのassertNoMojibake_())の二段で追加しました。原因は SJIS 由来の文字化けテキストをコピペで持ち込んだことで、入力経路自体は UTF-8 で安全でした。GAS は v287 で固定デプロイIDへ上書き済み。文字化けしていた既存9件は各カテゴリー担当者に再提出を依頼します。 -
2026-05-05
メンバースケジュール:文字化け対策のサニタイザーを反映するエンドポイント切替
v284 デプロイにサニタイザー(
sanitizeText_())を入れていたものの、メンバースケジュール ページと GitHub Actions の取得先が旧デプロイ(v173)のままで効いていませんでした。schedule/index.htmlと.github/workflows/update-schedule-data.ymlの両方を v284 エンドポイントへ差し替え、文字化けタイトルが「(文字化け)」表記となるようにしました。元データ修正対象として、Google カレンダー側で文字化けしている 「【月次】API使用量確認(Gemini・Claude)」(毎月1日繰り返し)と 「【要対応】COCoLa GitHub PAT 更新」(5/17)の2系統を特定済み(手動で再入力予定)。 -
2026-05-05
メンバー宛大量メール停止・BCC徹底・カレンダー文字化け対策
メンバーから「大量メールが届く・文字化けしている」との報告を受け、以下の対策を実施しました。 (1)DAO新提案通知のBCC一斉送信を停止し、管理者(cocola.project@gmail.com)のみへ通知に変更。 (2)メンバースケジュール登録時に Google カレンダーへ guests でメンバー全員を招待していた処理を停止(招待メール乱発の根本原因)。 (3)今後メンバー複数宛にメールを送信する場合は必ず BCC で送信するルールを徹底。 (4)メンバースケジュール ページで Google カレンダーから取得した既存イベントの表示にサニタイズ処理を追加し、文字化け(U+FFFD・◇◇◇連続等)を「(文字化け)」表記に置換して可読性を確保。新デプロイ(v284)に切り替えました。
-
2026-05-05
メンバーカレンダー:今期の実施事項12件を登録
全6カテゴリーの今期(2026年5〜6月)の実施事項を メンバースケジュール に登録しました。5/8 13:00〜 印西市役所文化振興課長との調整(@印西市役所内) を含む12件で、すべて全メンバー公開です。文化財関連は「つながりをつくる」カテゴリーに集約しています。
-
2026-05-04
メンバーカレンダー:TOPICSイベント編集時の「つくる」カテゴリが実績ページに反映されるよう修正
TOPICS由来イベントを編集して「つくる」カテゴリ(自分をつくる等)を変更しても、各カテゴリページの実績一覧(例:
/categories/jibun/)に反映されない問題を修正しました。GAS のeditTopicsEvent_がカテゴリ列・実績公開フラグを書き込むように修正し、新デプロイ(v276)に切り替えました。 -
2026-05-04
メンバーカレンダー:TOPICSイベント編集の「not found」エラーを修正
TOPICS由来イベント(印西市イベント)を編集して保存すると「保存に失敗しました: not found」になる問題を修正しました。GAS側に
editTopicsEvent_を実装し、サイトの GAS_ENDPOINT を最新デプロイに切り替えました。 -
2026-05-04
メンバーカレンダー:強制更新でイベントが消える問題を修正
Ctrl+Shift+R(強制更新)後にカレンダーに登録したイベントが消える問題を修正しました。ページ初期読み込みを GAS から直接取得する方式に変更し、静的 data.json はフォールバックとしてのみ使用するようにしました。
-
2026-05-04
メンバーカレンダー:TOPICSイベントの編集ボタンを非表示に
TOPICS(お知らせ)から表示されるイベントに編集ボタンが表示され、クリックすると「保存に失敗しました: not found」エラーになる問題を修正しました。TOPICSイベントには編集ボタンを表示しないよう変更しました。
-
2026-05-04
メンバーカレンダー:「TOPページへ戻る」リンクの404を修正
ヘッダーの「← TOPページへ戻る」リンクが404になる不具合を修正しました(href を
/から../へ変更)。 -
2026-05-03
メンバーカレンダー:企画者フィールド追加・DAOポイント連携
イベント登録フォームに「企画者」フィールドを追加しました。企画者・参加者として登録されたメンバーには自動的にDAOポイントが付与されます(企画者8pt・参加者1pt)。企画者や参加者がメンバー登録されていない場合はスキップされ処理が止まることはありません。
-
2026-05-03
メンバーカレンダー:Googleカレンダー直接登録イベントを編集可能に
Googleカレンダーに直接追加したイベント(📅バッジ表示)に「取り込んで編集」ボタンを追加。クリックするとスプレッドシートに取り込みながら内容を編集・保存できます。カレンダー幅も調整し見やすくしました。
-
2026-05-03
千葉ニュータウンイベント一覧:キーワード検索機能を追加
イベント一覧ページにキーワード絞り込み検索を追加しました。タイトル・場所・説明文・情報元を対象にリアルタイムでフィルタリングします。スペース区切りでAND検索に対応し、検索時は自動的にリスト表示に切り替わります。ヒット件数も表示します。
-
2026-05-03
DAO:提案提出後に自動公開されない不具合を修正
DAO提案フォームから提出しても提案が一覧に表示されない不具合を修正しました(cocola_topics GAS v249)。提出後のステータス更新処理が正しく動作するよう修正しました。
-
2026-05-03
freefree:GitHub Pagesへの移行完了
千葉ニュータウン事業主向け掲示板「freefree」をGAS WebアプリからGitHub Pages静的ホスティングに移行しました(GAS v60)。GAS側はAPIサーバーとして残し、フロントエンドのみ移行することでiOSのLINE WebViewなど各種ブラウザで安定して動作するようになりました。
-
2026-05-03
文化財MAP:Chrome以外のブラウザで表示できない不具合を修正
Firefox・Safari・Edge等のブラウザでGAS WebアプリのリダイレクトがブロックされてMAP画面が開けなかった不具合を修正しました。GAS依存をやめてGitHub Pages上に静的ページ(bunkazai-map/)として移行し、Google Maps Embed(iframeのみ・APIキー不要)を使用することで全ブラウザに対応しました。
-
2026-05-03
管理者ページ:ワークフロー手動起動ボタンを修復
管理者ページの「メンバーデータ」「イベントデータ」「DAOデータ」「イベントソース同期」「ヘルスチェック」ボタンが「通信エラー: Failed to fetch」になっていた不具合を修正しました。原因はGASのdoGetにtriggerWorkflowモードが未実装だったことによるCORSエラー。ハンドラを追加してデプロイし直しました。
-
2026-05-02
画像アップロードページに「イベント一覧に戻る」リンクを追加
イベント画像アップロードページにCOCoLaイベント一覧ページへの戻りリンクを追加しました。
-
2026-05-02
イベント一覧:管理者スキャンボタン追加・情報元バッジ表示
イベント一覧ページに「管理者スキャン」ボタンを追加しました(パスワード保護)。クリックするとGemini画像スキャンをその場で実行し、15秒後に最新データを再取得します。また、市民投稿・COCoLaメンバーによる画像登録イベントには情報元バッジ(市民投稿=オレンジ、COCoLa=青)を表示し、登録経路を一目で判別できるようになりました。
-
2026-05-02
画像アップロード後すぐにイベント登録処理を実行・サブフォルダ対応
「イベント画像アップロード」ページから画像を送信すると、アップロード完了と同時にGemini画像スキャン処理が自動実行されるようになりました(従来は最大5分待ちでした)。また、アップロード画像は「市民投稿(画像)」サブフォルダに保存され、ソース名もフォルダ名で自動識別されます。
-
2026-05-02
イベント一覧:画像スキャン時の日付抽出を改善・「森の音なみ vol.9」日付修正
「5.2(土)」「5/3」のようにドット・スラッシュ区切りで書かれた日付をGemini Vision APIが空文字で返すことがあり、イベントが「日付不明」グループに入って月・週カレンダーから消える問題がありました。Geminiへのプロンプトに日付変換の明示指示を追加し、任意形式の日付を「2026年X月X日」に変換するよう改善しました。あわせて「森の音なみ vol.9 in あんばい農園」(5月2日)の開催日時が空になっていたデータを修正しました。
2026年4月
-
2026-04-28
イベント一覧:複数日付チラシをカレンダーの全日に表示・「今すぐ反映」を即時反映に
「アヤナイ プレーパーク」のように1イベントで複数日程(4/29・5/4・5/23 など)が記載されているチラシが、最初の日付のセルにしか表示されない問題を修正しました。日付文字列から月日パターンを抽出し、月ビュー・週ビューのすべての該当セルに表示します。あわせて「今すぐ反映」ボタンを GAS への直接問い合わせに変更し、スプレッドシート編集後にボタンを押すと即時に反映されるようにしました(従来は GitHub Actions による data.json 更新を待つ必要があった)。GAS 側でも画像スキャン時の Gemini プロンプトを複数日付対応に改善し、曜日・祝日表記の括弧書きを除外するようにしました。
-
2026-04-28
GAS ソースコードをリポジトリで管理(clasp 連携)
これまで Google Apps Script の Web エディタ上にしか存在しなかった GAS コードを、@google/clasp を使って本リポジトリの
gas/配下で版管理できるようにしました。npm run gas:pullで取り込み、npm run gas:pushで反映します。これによりコードレビュー・ロールバック・差分追跡が可能になりました。 -
2026-04-28
イベント一覧:「今すぐ反映」ボタンを追加・年なし日付の自動補完を修正
画像登録したイベントを即時スキャンする「今すぐ反映」ボタンをイベント一覧ページに追加しました。また、Geminiが「4月29日」のように西暦なしで抽出した日付を今年の西暦に自動補完するよう修正しました(GAS v217)。補完は新規登録時・既存シート読み込み時の両方に適用されます。サイトへの反映は最大5分後となります。
-
2026-04-28
DAO:提案タイトルインデックスを追加
提案一覧の上部に、全提案のタイトルをリンクで並べたインデックスを追加しました。クリックすると該当カードまでスクロールします。フィルター(すべて/投票中/承認)に連動して表示内容が切り替わります。
-
2026-04-28
DAO:削除した提案が復活する問題を恒久修正(v20)
削除・非公開にした提案が再表示される問題を根本修正しました。原因は3か所:①集計処理が「公開」列を無視して非公開行を処理していた、②ステータス未設定の行を「投票中」として表示していた、③投票実績のない行に「投票中」を自動書き込みしていた。これらすべてを修正し、削除済み提案が復活しないようにしました。
-
2026-04-28
DAO:市民いいね数が0になっていた問題を修正
2026-04-27 の投票方式変更(P0020)に伴うGAS書き換えにより、市民いいね数の集計処理が欠落し、すべての提案で0件と表示されていた問題を修正しました。いいねの記録は「DAO市民いいね」専用シートに蓄積されており、そこから集計する処理を復元しました。
-
2026-04-27
DAO:投票方式を「協力できる/協力は難しい/検討中/わからない」に変更(P0020)
投票の選択肢を「賛成/反対」から4択形式に変更しました。承認条件は「協力率60%かつ参加率20%以上」に変わります。投票ポイント・入会初期ポイントの付与も追加しました。
-
2026-04-26
データ自動更新ワークフローの競合エラーを修正
DAO・イベント・メンバーの3つの自動更新ジョブが同時実行されると、先に完了した方が push した直後にもう一方が「更新を拒否された」エラーで失敗する問題を修正しました。push 前に最新状態を取り込む処理を追加し、競合を防ぎます。
-
2026-04-25
メンバーページ:リスト表示の行折り返しを改善
リスト表示で複数の列が重なって見づらい問題を改善しました。スキル・コメントなど長いテキスト列は折り返し表示、名前・役職など短い列はコンパクトに固定し、読みやすさを向上させました。
-
2026-04-25
印西市イベント:当日イベントがグレーアウトされるバグを修正
当日開催のイベントが「過去のイベント」として薄表示になってしまう不具合を修正しました。日本時間の深夜0時を過ぎた日を「過去」と判定するよう変更し、当日のイベントは終日、通常の色で表示されます。
-
2026-04-25
メンバーページ:リスト表示を追加・スマホ対応
メンバー一覧にカード表示に加えてリスト(表)表示を追加しました。表示する列はチェックボックスで選択でき、選択状態はブラウザに記憶されます。横スクロールや iOS でのスムーズなスワイプにも対応しました。
-
2026-04-24
メンバーページ:GAS版とGitHub Pages版の表示差異を解消
GAS版に追加したDAOポイント表示などがGitHub Pages版に反映されない二重管理問題を解消しました。GAS版を唯一の正とし、ビルドスクリプトで自動的にGitHub Pages版を生成する仕組みを導入しました。
-
2026-04-23
印西市イベント:画像から登録したイベントが表示されない問題を修正
チラシ画像をスキャンして登録したイベントが一覧に表示されないことがある問題を修正しました。AIが画像から日付を誤って解析した場合に、その値を日付フォールバックとして使わないよう変更しました。
-
2026-04-23
印西市イベント:コスモスパレットのイベントを自動収集
印西市文化ホール コスモスパレットのイベント情報を、毎週月曜日に自動で取得して一覧に追加するようにしました。
-
2026-04-20
DAO:Instagramなどアプリ内ブラウザで提案が表示されない問題を修正
InstagramのWebViewなど一部の環境でDAO提案一覧が表示されない問題を修正しました。GitHub Actionsによる5分ごとの自動データ更新を導入し、静的ファイルから確実に読み込めるようにしました。
-
2026-04-20
DAO:提案を取り消した後もカードが残るバグを修正
提案の取り消し操作後も画面にカードが残り続けたり、再読み込みで復活してしまう不具合を修正しました。取り消し直後に即座に非表示にし、ブラウザに取り消し済みIDを記録して再表示を防ぎます。
-
2026-04-20
DAO:スマホで最新情報が更新されない問題を修正
スマホで提案の取り消しや変更が反映されないことがある問題を修正しました。通信エラー時に画面へ警告を表示するようにし、データの取得方法も改善しました。
-
2026-04-20
トピックス:1件の投稿が2行登録されるバグを修正
フォームから1件投稿すると、まれにシートに2行登録されてしまう重複バグを修正しました。フォーム送信時のトリガー設定を見直し、重複が起きない構成に変更しました。
-
2026-04-20
メンバーページ:退会機能を追加
更新フォームから退会申請ができるようになりました。退会するとメンバー一覧から非表示になり、管理者にメール通知が届きます。
-
2026-04-20
印西市イベント一覧ページを公開
千葉ニュータウン周辺で開催されるイベントを月別・週別カレンダー形式で閲覧できるページを公開しました。印西市公式・観光協会・文化ホールなど複数ソースから毎週自動収集します。